如何在 Docker 中 运行 flask_migrate

How to run flask_migrate in Docker

我有一个结构如下的项目:

proj
  src
    application
      app.py
      manage.py
      migrations
  Dockerfile
  docker-compose.yaml

我的目标是 运行 在 docker-compose 期间从应用程序目录迁移以在数据库中创建表。

python manage.py db upgrade

Docker 文件

FROM python:3.7-alpine

ADD requirements.txt /code/
WORKDIR /code

RUN apk add --no-cache postgresql-dev gcc python3 musl-dev && \
    pip3 install -r requirements.txt


ADD . /code

EXPOSE 5000
WORKDIR /code/src/application

CMD ["flask", "run", "--host=0.0.0.0"]

docker-compose.yaml

---
version: "3"
services:
  web:
    links:
      - "db"
    build: .
    ports:
      - "5000:5000"
    volumes:
      - .:/code
    depends_on:
      - db
    env_file:
      - .env

  db:
    image: postgres:10
    restart: always
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_DB=app
    ports:
      - "5432:5432"
    expose:
      - 5432

我该怎么做?

为这个任务使用第三个容器怎么样?据我所知,因为它只需要执行一次,所以将它添加到入口点可能不是最好的做法,除非你有一些检查来避免每次容器启动时 运行ning 它,即使它不会造成伤害,这是一个不必要的过程。

使用第三个容器将执行以下操作:

当您 运行 docker-compose up 时,它将根据您想要的顺序启动,然后 运行 命令退出。关于路径,您可以在实际应用程序容器和迁移任务容器之间创建共享命名卷。例如:

I have added a base service to avoid duplication in the docker-compose

version: "3"
services:
  base:
    build: .
    volumes:
      - .:/code
    env_file:
      - .env
    command: 'false'

  web:
    extends:
      service: base
    command: flask run --host=0.0.0.0
    links:
      - "db"
    ports:
      - "5000:5000"
    depends_on:
      - db

  db:
    image: postgres:10
    restart: always
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_DB=app
    ports:
      - "5432:5432"
    expose:
      - 5432

  migrations:
    extends:
      service: base
    command: python manage.py db upgrade
    depends_on:
      - db

其他说明:

  • links 不需要,因为 docker-compose 默认会创建一个网络。
  • expose 也不需要,容器只要在同一个网络中就会看到彼此的端口。
  • 您可能会遇到某种竞争条件,您的数据库实际上还没有准备好进行连接,而您的 Django 应用程序试图连接到它。因此,为了解决此问题,您需要使用 wait-for-itwait-for,如 the following answer
  • 中所述

让我们试试 docker-compose.yml

---
version: "3"
services:
  web:
    links:
      - "db"
    build: .
    ports:
      - "5000:5000"
    volumes:
      - .:/code
    entrypoint:
      - python
      - manage.py
      - db
      - upgrade
    depends_on:
      - db
    env_file:
      - .env

  db:
    image: postgres:10
    restart: always
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_DB=app
    ports:
      - "5432:5432"
    expose:
      - 5432

我会添加一个 bash 脚本,其中包含您想要在启动期间 运行 执行的命令,并将其用作映像中的默认入口点。通常最好将此脚本称为 entrypoint.sh

#!/usr/bin/env bash
python manage.py db upgrade
flask run --host=0.0.0.0

然后,在您的 Docker 文件中,将最后一行替换为以下内容

RUN chmod u+x ./entrypoint.sh
ENTRYPOINT ["./entrypoint.sh"]

如果你想 运行 只在 Docker compose 中升级命令,那么你可以像这样在 compose 文件中覆盖它而不是更改图像中的默认入口点

  web:
    links:
      - "db"
    build: .
    ports:
      - "5000:5000"
    volumes:
      - .:/code
    depends_on:
      - db
    entrypoint: /code/entrypoint.sh
    env_file:
      - .env