Поведение команды docker -compose не совпадает с выполнением в Dockerfile - PullRequest
0 голосов
/ 12 января 2020

У меня есть проект Django, и я боролся с автоматизацией генерации файлов stati c. В моей структуре проекта есть файл docker-compose.yml и Dockerfile для каждого образа контейнера.

Файл docker -compose.yml для моего проекта:

version: '3'

services:
  web:
    build: ./dispenser
    command: gunicorn -c gunicorn.conf.py dispenser.wsgi
    volumes:
      - ./dispenser:/dispenser
    ports:
      - "8000:8000"
    restart: on-failure
  nginx:
    build: ./nginx/
    depends_on:
      - web
    command: nginx -g 'daemon off;'
    ports:
      - "80:80"
    volumes:
      - ./dispenser/staticfiles:/var/www/static
    restart: on-failure

Файл Docker для проект Django, который я использую:

FROM python:3.7.4

ENV PYTHONUNBUFFERED=1 \
    PYTHONDONTWRITEBYTECODE=1 \
    WEBAPP_DIR=/dispenser \
    GUNICORN_LOG_DIR=/var/log/gunicorn

WORKDIR $WEBAPP_DIR

RUN mkdir -p $GUNICORN_LOG_DIR \
    mkdir -p $WEBAPP_DIR

ADD pc-requirements.txt $WEBAPP_DIR
RUN pip install -r pc-requirements.txt

ADD . $WEBAPP_DIR

RUN python manage.py makemigrations && \
    python manage.py migrate && \
    python manage.py collectstatic --no-input

После нескольких часов тестирования и исследований я обнаружил, что при выполнении команд collectstati c и миграций из Dockerfile не выдается то же самое. результат в виде аргумента command в файле docker -compose.yml.

Если я сделаю это, как показано выше, когда наступит время для запуска команды collectstati c, только " создается папка staticfiles (внутри нее нет файлов). Также миграции базы данных не применялись (обратите внимание, что я использую стандартную версию .sqlite3 db). Несмотря на то, что в stdout при создании контейнера говорится, что были применены миграции и сгенерированы статические файлы.

Единственный найденный мной способ заставить его работать - это выполнить bash из контейнера и затем выполнить эти команды оттуда.

Но позже я обнаружил, что, если я укажу эти команды в docker -file.yml, все будет работать как положено. Оставьте файлы следующим образом:

docker -compose.yml

version: '3'

services:
  web:
    build: ./dispenser
    command: bash -c "python manage.py makemigrations && python manage.py migrate && python manage.py collectstatic --no-input && gunicorn -c gunicorn.conf.py dispenser.wsgi"
    volumes:
      - ./dispenser:/dispenser
    ports:
      - "8000:8000"
    restart: on-failure
  nginx:
    build: ./nginx/
    depends_on:
      - web
    command: nginx -g 'daemon off;'
    ports:
      - "80:80"
    volumes:
      - ./dispenser/staticfiles:/var/www/static
    restart: on-failure

Dockerfile

FROM python:3.7.4

ENV PYTHONUNBUFFERED=1 \
    PYTHONDONTWRITEBYTECODE=1 \
    WEBAPP_DIR=/dispenser \
    GUNICORN_LOG_DIR=/var/log/gunicorn

WORKDIR $WEBAPP_DIR

RUN mkdir -p $GUNICORN_LOG_DIR \
    mkdir -p $WEBAPP_DIR

ADD pc-requirements.txt $WEBAPP_DIR
RUN pip install -r pc-requirements.txt

ADD . $WEBAPP_DIR

Может кто-нибудь объяснить мне, почему это происходит? И если есть другой способ добиться того, что я намереваюсь, без указания команд в файле docker -compose.yml?

1 Ответ

1 голос
/ 12 января 2020

Когда вы монтируете каталог хоста в контейнер, содержимое каталога хоста затеняет содержимое контейнера.

volumes:
      - ./dispenser:/dispenser

Таким образом, при запуске вашего контейнера начальное содержимое /dispenser внутри контейнера будет содержимым ./dispenser с хост-компьютера. Любой контент уже в /dispenser внутри контейнера затеняется. Таким образом, содержимое, сгенерированное во время сборки образа с помощью инструкций RUN в вашем Dockerfile, будет потеряно.

При втором подходе использования command в файле compose вы сначала монтируете том, а затем генерируете контент, и, следовательно, он работает.

Инструкция command в Dockerfile используется для переопределения команды по умолчанию в образе Docker, которую можно установить с помощью инструкции CMD в Dockerfile. Поскольку вы хотите использовать первый подход к запуску сценария python во время сборки образа с использованием инструкций RUN, вы можете RUN их в другом каталоге (скажем, / tmp / dispenser) и как часть command в compose или CMD в Dockerfile вы можете переместить сгенерированный контент с /tmp/dispenser на /dispenser.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...