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 и автоматическое применение миграций.