Почему мой файл .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 происходит в два этапа:
- Вы создаете многоразовый образ, который содержит среду выполнения приложения, любые зависимости библиотек для ОС и языка, а также код приложения; затем .
- Вы запускаете контейнер на основе этого образа.
Файл .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:
).