Knex migrate:latest不会从docker创建表

z31licg0  于 2023-03-22  发布在  Docker
关注(0)|答案(1)|浏览(126)

我正在做一个应用,需要在docker容器启动时预填充knex数据库模式(* 仅当数据库为空 *)。
如果我手动执行它:容器中的yarn knex --knexfile config/knexfile.js migrate:latest-它可以工作,但我需要在docker容器启动时这样做。

Dockerfile.dev

FROM node:18.15.0-alpine3.17

# Create app directory
WORKDIR /opt/app

COPY package*.json yarn*.lock ./

RUN yarn

COPY . .

ENTRYPOINT [ "node", "server.js" ]

docker-compose-dev.yml

backend:
    container_name: backend-dev
    build:
      context: ./backend
      dockerfile: Dockerfile.dev
    restart: unless-stopped
    env_file: ./backend/.env.dev
    command: bash -c "yarn knex --knexfile ./config/knexfile.js migrate:latest" && "node server.js"
    ports:
      - "3000:3000"
    networks:
      - network
    depends_on: 
      - db

没有错误或异常,但在DB容器内没有从迁移创建的关系。
我很乐意接受意见。
先谢谢你!

piah890a

piah890a1#

现在什么都没有发生,因为你在Dockerfile中使用ENTRYPOINT,并在Compose设置中单独设置了command:。当你同时设置了入口点和命令时,命令会作为附加参数传递给入口点,所以你会看到bash-c和另外三个参数作为Node应用程序的参数。
我在这里要做的第一件事是在Dockerfile中将ENTRYPOINT更改为CMD。这将使Compose command:覆盖生效。其中有一个语法问题(两个命令需要在相同的引号字符串中;sh -c只接受一个参数),但是如果您修复了这个问题,那么迁移应该可以工作。
但我实际上是将其实现为一个 * 入口点 Package 器脚本 *。如果CMD是要运行的实际命令,并且它作为参数传递给ENTRYPOINT,那么您可以将ENTRYPOINT用于第一次设置的脚本,然后运行作为参数传递给它的命令。例如:

#!/bin/sh
# entrypoint.sh

# Run migrations
yarn knex --knexfile ./config/knexfile.js migrate:latest

# Run the main container command
exec "$@"

请确保此文件作为可执行文件签入到源代码控制中,如果您使用的是Windows系统,请确保它具有Unix(仅限LF)行结尾。您现有的COPY命令将把它复制到映像中,因此您所需要做的就是运行它

ENTRYPOINT ["./entrypoint.sh"]  # must be JSON-array syntax
CMD ["node", "server.js"]       # what you currently have as ENTRYPOINT

并且您不需要覆盖docker-compose.yml文件中的command:
在问题中,你添加了一个限制条件“只有当数据库为空时”。我在这里展示的设置将无条件地运行数据库迁移。然而,入口点脚本只是一个shell脚本,你可以在那里编写任何你需要的逻辑。此外,由于它只是一个shell脚本,如果你在开发和调试过程中需要./entrypoint.sh echo hello,你可以在本地运行它。

相关问题