javascript - How to run knex migrations from Dockerfile or docker-compose - Stack Overflow

I have Dockerfile that works with API and MySQL database and it should do migrations:FROM nodeWORKDIR

I have Dockerfile that works with API and MySQL database and it should do migrations:

FROM node

WORKDIR /api

COPY . .

RUN npm install

EXPOSE 3001

VOLUME [ "/api/node_modules" ]

CMD [ "npm", "start" ]

Also, there is a docker-pose file where I have database as a service:

  db:
    image: mysql
    container_name: database
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_PASSWORD: password
      MYSQL_DATABASE: testdb

The problem is, I don't know how to run migrations. Should I do it from docker-pose file or Dockerfile?

I was trying to do something like this in Dockerfile, but it doesn't seem to be working:

...
CMD [ "knex", "migrate:latest" ]
...

Or:

...
RUN knex migrate:latest
...

I have Dockerfile that works with API and MySQL database and it should do migrations:

FROM node

WORKDIR /api

COPY . .

RUN npm install

EXPOSE 3001

VOLUME [ "/api/node_modules" ]

CMD [ "npm", "start" ]

Also, there is a docker-pose file where I have database as a service:

  db:
    image: mysql
    container_name: database
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_PASSWORD: password
      MYSQL_DATABASE: testdb

The problem is, I don't know how to run migrations. Should I do it from docker-pose file or Dockerfile?

I was trying to do something like this in Dockerfile, but it doesn't seem to be working:

...
CMD [ "knex", "migrate:latest" ]
...

Or:

...
RUN knex migrate:latest
...
Share Improve this question asked Jan 29, 2022 at 20:23 dokichandokichan 6414 gold badges22 silver badges59 bronze badges 2
  • For a different technology stack, there's some discussion of the options in How do you perform Django database migrations when using Docker-Compose?. Broadly, the major options are to docker-pose run your-app knex migrate:latest manually, or to set up an ENTRYPOINT wrapper script to do it automatically on every startup. Does that question have enough detail to help you, even if you're on a different language/migration system? – David Maze Commented Jan 29, 2022 at 22:15
  • I agree with you. I can create such ENTRYPOINT script and this will work, I guess, but I would like to implement it only using docker and docker-pose tools. – dokichan Commented Jan 29, 2022 at 22:31
Add a ment  | 

2 Answers 2

Reset to default 6

Chaining the mand or using and entrypoint is less optimal in case you want to horizontally scale your application.

Then all replicas will do the migration, at the same time. It's likely to not cause real problems, but It's still not perfect IMO.

Instead, this should be handled separately, as a one shot mand when actually required. For example, in Kubernetes in would be good to run a dedicated migration job along with your application release, if the database schema has actually changed.

With pose, there are no jobs, but you can achieve similar behavior.

services:
  migration:
    image: busybox
    mand: sh -c 'echo "running migration..."; sleep 20; echo "migration pleted"'
  app:
    image: busybox
    mand: echo "app started"
    depends_on:
      migration:
        condition: service_pleted_successfully
    deploy:
      replicas: 3

Now you run the migration only once, and all 3 app replicas wait for the migration to plete before they start up.

$ docker pose up
Attaching to app_1, app_2, app_3, migration_1
migration_1  | running migration...
migration_1  | migration pleted
migration_1 exited with code 0
app_2        | app started
app_3        | app started
app_1        | app started

In your case, you would use the same image you build from the Dockerfile for both migration and app service. In the migration service you use knex migrate and in the app service you use npm run start.

If you need the migration to even wait for the DB, depends_on might not be sufficient, unless you build in a health check that reflects if the database is actually ready to accept a connection. If you have a health check, then you can use the condition service_healthy.

For example, you could dome something like this.

services:
  db:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: "root"
      MYSQL_DATABASE: "wordpress"
      MYSQL_USER: "wordpressuser"
      MYSQL_PASSWORD: "wordpresspassword"
    healthcheck:
      test: mysqladmin -u root --password=$$MYSQL_ROOT_PASSWORD ping

  migration:
    image: busybox
    mand: sh -c 'echo "running migration..."; sleep 20; echo "migration pleted"'
    depends_on:
      db:
        condition: service_healthy

  app:
    image: busybox
    mand: echo "app started"
    depends_on:
      migration:
        condition: service_pleted_successfully
    deploy:
      replicas: 3

You can see the health check output by inspecting the container.

$ docker inspect sample_db_1 --format \
  '{{range .State.Health.Log}}{{.End}} | Exit Code: {{.ExitCode}} | {{.Output}}{{end}}'
2022-01-30 12:53:43.749365 +0000 UTC | Exit Code: 0 | mysqladmin: [Warning] Using a password on the mand line interface can be insecure.
mysqld is alive

If you don't want to use a health check, you can also use third party solutions like https://github./Eficode/wait-for.

I solved this problem, probably in stupid way, but it works. So, what I did is just added this on my API container:

restart: on-failure
mand: bash -c "npm run knex && npm run start"

Now, it just restarts container until get connection to database and does all migrations.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744906328a4600279.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信