Docker-compose для разработки: видим изменения на лету

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

Давайте рассмотрим код-пример:

version: '3.8'

volumes:
  postgres_data:

services:
  db:
    image: postgres:12.4
    restart: always
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    env_file:
      - ./.env
  django:
    build: .
    depends_on:
      - db
    restart: always
    env_file:
      - ./.env
    volumes:
      - .:/code/
    entrypoint: /code/entrypoint.sh

  nginx:
    image: nginx:1.19.0-alpine
    ports:
      - "127.0.0.1:1111:80"
    volumes:
      - ./static:/code/static
      - ./media:/code/media
      - ./nginx:/etc/nginx/conf.d/
    depends_on:
      - django
    restart: always

Мы оставили на томе только базу данных. Все остальные данные вместо этого мы прикрепили к нужным папкам в нашем проекте.

Смотрите, весь корень проекта в папке code, статика и медиа подключена напрямую к контейнеру nginx, как и его конфиг. Вот как он выглядит:

upstream djangodocker {
    server django:8000;
}

server {

    listen 80;

    location / {
        proxy_pass http://djangodocker;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_redirect off;
    }
    location /static/ {
        alias /code/static/;
    }

    location /media/ {
        alias /code/static/;
    }

}

Описание того, что здесь происходит, можно найти в статье про docker-compose. Там же вы увидите разбор entrypoint.sh:

#!/bin/sh

sleep 2
python manage.py migrate
python manage.py createcachetable

if [ "$DJANGO_SUPERUSER_USERNAME" ]; then
  python manage.py createsuperuser \
    --noinput \
    --username "$DJANGO_SUPERUSER_USERNAME" \
    --email $DJANGO_SUPERUSER_EMAIL
fi

python manage.py collectstatic --noinput
gunicorn foodgram.wsgi:application --bind 0.0.0.0:8000

exec "$@"

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

DB_ENGINE=django.db.backends.postgresql # указываем, что работаем с postgresql
DB_NAME=postgres # имя базы данных
POSTGRES_USER=postgres # логин для подключения к базе данных
POSTGRES_PASSWORD=postgrespostgres # пароль для подключения к БД (установите свой)
DB_HOST=db # название сервиса (контейнера)
DB_PORT=5432 # порт для подключения к БД
SECRET_KEY=SECRET_KEYSECRET_KEYSECRET_KEY
DJANGO_SUPERUSER_PASSWORD=12345678
DJANGO_SUPERUSER_EMAIL=example@example.com
DJANGO_SUPERUSER_USERNAME=admin

Чтобы новая установка Django подключилась к Postgres — измените настройки подключения в файле settings.py:

DATABASES = {
    'default': {
        'ENGINE': os.environ.get('DB_ENGINE'),
        'NAME': os.environ.get('DB_NAME'),
        'USER': os.environ.get('POSTGRES_USER'),
        'PASSWORD': os.environ.get('POSTGRES_PASSWORD'),
        'HOST': os.environ.get('DB_HOST'),
        'PORT': os.environ.get('DB_PORT'),
    }
}

И не забудьте, что для работы базы данных вам нужна зависимость:

pip install psycopg2-binary

Еще один важный момент — это изменения в файле Dockerfile. Теперь нам не нужно копировать весь проект на контейнер, мы и так туда подключим всю папку, но предварительная установка зависимостей и старт контейнера зависят от двух файлов, которые уже должны быть в контейнере:

FROM python:3.9-slim

ENV PYTHONDONTWRITEBYTECODE 1

ENV PYTHONUNBUFFERED 1


WORKDIR /code
#COPY . /code
COPY ./requirements.txt /code
COPY ./entrypoint.sh /code
RUN pip install -r /code/requirements.txt


ENTRYPOINT ["/code/entrypoint.sh"]

После этого вы просто запускаете команду docker-compose up и получаете рабочий прототип проекта на своей машине, со статикой:

И что самое важное, вы сможете вносить изменения на лету и тут же их видеть!

Отдельное спасибо за идею с прямым подключением файлов Leon Sandøy в его репозитории Django-Starter. Добавил сюда nginx и автоматическое применение миграций.