简体   繁体   English

如何从 Dockerfile 或 docker-compose 运行 knex 迁移

[英]How to run knex migrations from Dockerfile or docker-compose

I have Dockerfile that works with API and MySQL database and it should do migrations:我有 Dockerfile 与 API 和 MySQL 数据库一起使用,它应该进行迁移:

FROM node

WORKDIR /api

COPY . .

RUN npm install

EXPOSE 3001

VOLUME [ "/api/node_modules" ]

CMD [ "npm", "start" ]

Also, there is a docker-compose file where I have database as a service:此外,还有一个 docker-compose 文件,其中我将数据库作为服务:

  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-compose file or Dockerfile?我应该从 docker-compose 文件还是 Dockerfile 执行它?

I was trying to do something like this in Dockerfile, but it doesn't seem to be working:我试图在 Dockerfile 中做这样的事情,但它似乎不起作用:

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

Or:或者:

...
RUN knex migrate:latest
...

I solved this problem, probably in stupid way, but it works.我解决了这个问题,可能是以愚蠢的方式,但它有效。 So, what I did is just added this on my API container:所以,我所做的只是在我的 API 容器上添加了这个:

restart: on-failure
command: npm run knex

Now, it just restarts container until get connection to database and does all migrations.现在,它只是重新启动容器,直到连接到数据库并执行所有迁移。

Chaining the command 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.它可能不会引起真正的问题,但它仍然不是完美的 IMO。

Instead, this should be handled separately, as a one shot command 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.例如,在 Kubernetes 中,如果数据库架构实际上已更改,那么与您的应用程序版本一起运行专用迁移作业会很好。

With compose, there are no jobs, but you can achieve similar behaviour.使用 compose,没有作业,但您可以实现类似的行为。

services:
  migration:
    image: busybox
    command: sh -c 'echo "running migration..."; sleep 20; echo "migration completed"'
  app:
    image: busybox
    command: echo "app started"
    depends_on:
      migration:
        condition: service_completed_successfully
    deploy:
      replicas: 3

Now you row the migration only once and all 3 app replicas wait for the migration to complete before they start up.现在,您只需执行一次迁移,所有 3 个应用程序副本都会等待迁移完成,然后再启动。

$ docker compose up
Attaching to app_1, app_2, app_3, migration_1
migration_1  | running migration...
migration_1  | migration completed
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.在您的情况下,您将使用从 Dockerfile 构建的相同映像用于迁移和应用程序服务。 In the migration service you use knex migrate and in the app service you use npm run start .在迁移服务中使用knex migrate ,在应用服务中使用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.如果您需要迁移甚至等待数据库,depends_on 可能还不够,除非您构建反映数据库是否实际准备好接受连接的运行状况检查。 If you have a health check, then you can use the condition service_healthy .如果您有健康检查,那么您可以使用条件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
      interval: 30s
      timeout: 10s
      retries: 10

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

  app:
    image: busybox
    command: echo "app started"
    depends_on:
      migration:
        condition: service_completed_successfully
    deploy:
      replicas: 3

You can health check logs by doing a container inspect.您可以通过执行容器检查来检查日志。

$ 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 command 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.com/Eficode/wait-for .如果您不想使用健康检查,也可以使用第三方解决方案,例如https://github.com/Eficode/wait-for

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Docker-Compose:来自具有相同 Dockerfile 的本地图像的多个服务 - Docker-Compose : Multiple services from local images with the same Dockerfile 如何在docker-compose中运行量角器测试 - how to run protractor tests in docker-compose 如何使用 JavaScript 而不是 CLI 运行 knex 迁移? - How to run knex migrations with JavaScript instead of CLI? 使Dockerfile VOLUME的行为类似于docker-compose卷 - Make Dockerfile VOLUME behave like docker-compose volumes 由于绑定挂载,找不到Dockerfile和docker-compose的节点模块 - Node modules not found with Dockerfile and docker-compose due to bind mount 从 docker-compose 中的服务连接到 azurite - Connecting to azurite from service in docker-compose 使用 Docker-Compose 时,Dockerfile 中的“ENTRYPOINT [”./init.sh“]”会产生“没有这样的文件或目录”? - “ENTRYPOINT [”./init.sh“]” in Dockerfile produces “no such file or directory” when using Docker-Compose? Db knex 迁移:docker 内的 KnexTimeoutError - Db knex migrations: KnexTimeoutError inside docker 如何避免docker-compose中的“无效挂载路径” - How to avoid ` invalid mount path` in docker-compose 如何在 docker-compose 中将 Nuxt 应用程序链接到 API 服务器 - How to link a Nuxt app to an API server in docker-compose
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM