flask необычное поведение контейнера - PullRequest
1 голос
/ 06 августа 2020

Я запускаю пример приложения flask с поддержкой mysql с использованием docker -compose. Вот мой файл компоновки.

version: "2"
services:
  webapp:
    build:
      context: ./flask/
      dockerfile: Dockerfile
    ports:
      - "8000:5000"
    env_file: 
      - ./.env
    depends_on:
      - mysqldb
    networks:
      - my-bridge1
    volumes:
      - "./flask/flask-data:/usr/src"

  mysqldb:
    build:
      context: ./mysql/
      dockerfile: Dockerfile
    env_file:
      - ./.env
    networks:
      - my-bridge1
    volumes:
      - "./mysql/db-data:/var/lib/mysql"


networks:
  my-bridge1:
    driver: bridge

Проблема в том, что когда я монтирую каталог своего приложения вне контейнера, появляется

**error**: __init__.py file is not found

, который находится в WORKDIR. Эта проблема возникает только тогда, когда я монтирую свой том с кодом за пределами контейнера. Если я монтирую любой другой каталог, приложение работает нормально.

Вот мой docker файл для приложения:

FROM python:3

RUN mkdir /usr/src/FlaskApp
RUN mkdir /usr/src/FlaskApp/code

WORKDIR /usr/src/FlaskApp/code


COPY ./code ./
RUN pip install -r ./requirements.txt

COPY FlaskApp.wsgi /usr/src/FlaskApp/

EXPOSE 5000

VOLUME /usr/src

CMD [ "python", "__init__.py" ]

Я тестировал контейнер mysql, он копирует файлы из контейнера. Но контейнер python этого не делает.

EDIT1: Когда я изменяю аргумент CMD на «ls», каталог пуст. Когда я изменил аргумент CMD на «pwd», результат был следующим: «/ usr / src / FlaskApp / code»

EDIT2: Что еще более странно, так это то, что каталоги внутри связанного тома создаются снаружи. Но они пустые!

1 Ответ

0 голосов
/ 06 августа 2020

Данные также копируются в контейнер python, но вы скрываете эти данные с помощью монтирования привязки.

Сначала вы копируете файлы в /usr/src/FlaskApp/code в вашем Dockerfile, но затем вы создаете монтирование привязки в в том же месте, что означает, что /usr/src/ теперь будет содержать только содержимое ./flask/flask-data, которое находится на вашем локальном хосте (источнике привязки).

В результате вы получите /usr/src/<contents of ./flask/flask-data> , поэтому, если ./flask/flask-data на вашем локальном хосте не содержит файла __init__.py (и всей подструктуры каталогов, необходимой вашему приложению), то и контейнер не будет.

Таким образом, все эти строки в вашем Dockerfile в основном не имеет значения, пока вы используете это bind mount

RUN mkdir /usr/src/FlaskApp
RUN mkdir /usr/src/FlaskApp/code
WORKDIR /usr/src/FlaskApp/code
COPY ./code ./
COPY FlaskApp.wsgi /usr/src/FlaskApp/

Я не уверен, что именно вы пытаетесь достичь и как ваше приложение разрешает пути, но быстрое исправление будет заключаться в создании другой папки под /usr/src (возможно, /usr/src/FlaskData) и смонтируйте туда локальный каталог.

volumes:
      - "./flask/flask-data:/usr/src/FlaskData"

Теперь в вашем /usr/src будут и FlaskApp, и FlaskData, но вы r потребуется соответственно обновить пути к файлам в вашем приложении.

из Docker docs

Подключить в непустой каталог на контейнер

Если вы выполняете привязку-монтирование в непустой каталог в контейнере, существующее содержимое каталога скрывается привязкой монтирования. Это может быть полезно, например, когда вы хотите протестировать новую версию своего приложения без создания нового образа. Однако это также может быть неожиданным, и это поведение отличается от поведения docker томов.

И чтобы ответить, почему привязка mount ведет себя по-другому для MySQL контейнера - это не так.

Вы монтируете пустую папку в место, где данные записываются MySQL только после запуска контейнера, поэтому там нечего скрывать, потому что место назначения пусто для начала (то же самое относится к python, если вы напишете что-нибудь в /usr/src после запуска контейнера, вы увидите, что эти данные появятся на локальном хосте в ./flask/flask).

...