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

问题描述 投票:0回答:2

我有可与 API 和 MySQL 数据库配合使用的 Dockerfile,它应该进行迁移:

FROM node

WORKDIR /api

COPY . .

RUN npm install

EXPOSE 3001

VOLUME [ "/api/node_modules" ]

CMD [ "npm", "start" ]

此外,还有一个 docker-compose 文件,其中我将数据库作为服务:

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

问题是,我不知道如何运行迁移。我应该从 docker-compose 文件还是 Dockerfile 中执行此操作?

我试图在 Dockerfile 中执行类似的操作,但它似乎不起作用:

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

或者:

...
RUN knex migrate:latest
...
javascript node.js docker database-migration knex.js
2个回答
5
投票

如果您想水平扩展应用程序,链接命令或使用入口点并不是最佳选择。

然后所有副本将同时进行迁移。它可能不会造成真正的问题,但在我看来它仍然不完美。

相反,这应该单独处理,在实际需要时作为一次性命令。例如,在 Kubernetes 中,如果数据库架构实际上已更改,则最好在应用程序版本发布时运行专用迁移作业。

使用 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

现在您只需运行一次迁移,所有 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

在您的情况下,您将使用从 Dockerfile 构建的相同映像进行迁移和应用程序服务。在迁移服务中您使用

knex migrate
,在应用服务中您使用
npm run start

如果您需要迁移来等待数据库,

depends_on
可能还不够,除非您构建反映数据库是否确实准备好接受连接的运行状况检查。如果您有健康检查,那么您可以使用条件
service_healthy

例如,你可以做这样的圆顶。

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
    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

您可以通过检查容器来查看健康检查输出。

$ 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

如果您不想使用健康检查,您还可以使用第三方解决方案,例如https://github.com/Eficode/wait-for


0
投票

我解决了这个问题,可能是用愚蠢的方式,但它有效。所以,我所做的只是将其添加到我的 API 容器中:

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

现在,它只是重新启动容器,直到连接到数据库并执行所有迁移。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.