Почему мой файл .Dockerignore не игнорирует файлы?

Когда я собираю контейнер и проверяю файлы, которые должны были быть проигнорированы, большинство из них не были проигнорированы.

Это структура моих папок.

Root/

  data/

  project/
    __pycache__/
    media/
    static/

  app/
    __pycache__/
    migrations/
    templates/

  .dockerignore
  .gitignore
  .env
  docker-compose.yml
  Dockerfile
  requirements.txt
  manage.py

Допустим, я хочу игнорировать папки __pycache__ & data (данные будут созданы командой docker-compose up при создании контейнера) и файлы .gitignore & .env.

Я буду игнорировать их с помощью следующего файла .dockerignore

.git
.gitignore

.docker

*/__pycache__/
**/__pycache__/

.env/
.venv/
venv/

data/

В итоге игнорируются только файлы git & .env. Папка data не была проигнорирована, но она недоступна из контейнера. И папки __pycache__ также не были проигнорированы.

Вот файлы docker.

docker-compose.yml

version: "3.8"

services: 

  app: 
    build: .
    volumes: 
      - .:/django-app
    ports: 
      - 8000:8000
    command: /bin/bash -c "sleep 7; python manage.py migrate; python manage.py runserver 0.0.0.0:8000"
    container_name: app-container
    depends_on: 
      - db

  db:
    image: postgres
    volumes:
      - ./data:/var/lib/postgresql/data
    environment: 
      - POSTGRES_DB=${DB_NAME}
      - POSTGRES_USER=${DB_USER}
      - POSTGRES_PASSWORD=${DB_PASSWORD}
    container_name: postgres_db_container

Dockerfile

FROM python:3.9-slim-buster

ENV PYTHONUNBUFFERED=1

WORKDIR /django-app
EXPOSE 8000

COPY requirements.txt requirements.txt

RUN apt-get update \
    && adduser --disabled-password --no-create-home userapp \
    && apt-get -y install libpq-dev \
    && apt-get -y install apt-file \
    && apt-get -y install python3-dev build-essential \
    && pip install -r requirements.txt

USER userapp

Вы на самом деле внедряете свой исходный код с помощью volumes:, а не во время сборки образа, и это не соответствует .dockerignore.

Запуск такого приложения Docker происходит в два этапа:

  1. Вы создаете многоразовый образ, который содержит среду выполнения приложения, любые зависимости библиотек для ОС и языка, а также код приложения; затем
  2. .
  3. Вы запускаете контейнер на основе этого образа.

Файл .dockerignore рассматривается только на первом этапе сборки. В вашей установке вы фактически не COPY ничего в образе помимо файла requirements.txt. Вместо этого вы используете volumes: для внедрения частей хост-системы в контейнер. Это происходит во время второй фазы и игнорирует .dockerignore.

В этом случае я бы рекомендовал пропустить volumes:, а вместо этого COPY указать требуемый исходный код в Dockerfile. Вам также следует обычно указывать по умолчанию CMD контейнер будет запускаться в Dockerfile, а не требовать этого в docker-compose.yml или docker run команде.

FROM python:3.9-slim-buster

# Do the OS-level setup _first_ so that it's not repeated
# if Python dependencies change
RUN apt-get update && apt-get install -y ...

WORKDIR /django-app

# Then install Python dependencies
COPY requirements.txt .
RUN pip install -r requirements.txt

# Then copy in the rest of the application
# NOTE: this _does_ honor .dockerignore
COPY . .

# And explain how to run it
ENV PYTHONUNBUFFERED=1
EXPOSE 8000
USER userapp
# consider splitting this into an ENTRYPOINT that waits for the
# the database, runs migrations, and then `exec "$@"` to run the CMD
CMD sleep 7; python manage.py migrate; python manage.py runserver 0.0.0.0:8000

Это означает, что при установке docker-compose.yml вам не нужно volumes:; код приложения уже находится внутри образа, который вы собрали.

version: "3.8"
services:
  app: 
    build: .
    ports: 
      - 8000:8000
    depends_on: 
      - db
    # environment: [PGHOST=db]
    # no volumes: or container_name:

  db:
    image: postgres
    volumes: # do keep for persistent database data
      - ./data:/var/lib/postgresql/data
    environment: 
      - POSTGRES_DB=${DB_NAME}
      - POSTGRES_USER=${DB_USER}
      - POSTGRES_PASSWORD=${DB_PASSWORD}
    # ports: ['5433:5432']

Такой подход также означает, что вам нужно docker-compose build создавать новый образ, когда ваше приложение меняется. Это нормально для Docker.

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

# Start the database but not the application
docker-compose up -d db

# Create a virtual environment and set it up
python3 -m venv venv
. venv/bin/activate
pip install -r requirements.txt

# Set environment variables to point at the Docker database
export PGHOST=localhost PGPORT=5433

# Run the application locally
./manage.py runserver

Для этого необходимо сделать базу данных видимой извне Docker (через ports:) и сделать расположение базы данных настраиваемым (возможно, через переменные окружения, задаваемые в Compose с помощью environment:).

Вернуться на верх