Как запустить flask_migrate в Docker - PullRequest
0 голосов
/ 18 марта 2019

У меня есть проект со следующей структурой:

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

Моя цель - запустить миграции из каталога приложения для создания таблиц в базе данных во время docker-compose.

python manage.py db upgrade

Dockerfile

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

Как я могу это сделать?

Ответы [ 3 ]

1 голос
/ 18 марта 2019

Я бы добавил скрипт bash, содержащий команды, которые вы хотите запустить во время запуска, и использовал бы его в качестве точки входа по умолчанию в вашем образе.Обычно рекомендуется вызывать этот сценарий entrypoint.sh

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

А затем в вашем Dockerfile замените последнюю строку следующей

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
0 голосов
/ 18 марта 2019

попробуем с 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
0 голосов
/ 18 марта 2019

Как насчет использования третьего контейнера для этой задачи?Поскольку он должен выполняться только один раз, насколько я знаю, поэтому добавление его к точке входа может оказаться не лучшим решением, если у вас нет проверок, чтобы избежать его запуска каждый раз, когда контейнер запускается, даже если он не причинит вреда.ненужный процесс.

Использование третьего контейнера приведет к следующему:

Когда вы запустите docker-compose up, он запустится в соответствии с желаемым порядком, запустит команду и завершится.Что касается пути, вы можете создать общий именованный том между фактическим контейнером приложения и контейнером задачи миграции.Например:

Я добавил сервис base, чтобы избежать дублирования в 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-it или wait-for, как объяснено в следующий ответ
...