В корне нашего проекта я создам папку docker, а также файл docker-compose.yml и Dockerfile.
Сам файл Dockerfile будет содержать одно из главных: Python 3.10 и необходимые модули как для самой операционной системы в контейнеры, также и модули необходимые для виртуального окружения нашего Django проекта.
Создадим файл requirements.txt с помощью команды
pip freeze > requirements.txt
Пояснение:
- Этот файл необходим для установки всех модулей виртуального окружения, в том числе и самого Django.
- Также в получившийся файл нужно добавить gunicorn. Его можно прописать вручную:
requirements.txt
gunicorn
amqp==5.1.1
asgiref==3.5.2
async-timeout==4.0.2
billiard==3.6.4.0
celery==5.2.7
click==8.1.3
click-didyoumean==0.3.0
click-plugins==1.1.1
click-repl==0.2.0
colorama==0.4.5
Deprecated==1.2.13
Django==4.1
django-ckeditor-5==0.2.0
django-cleanup==6.0.0
django-debug-toolbar==3.6.0
django-js-asset==2.0.0
django-mptt==0.13.4
django-recaptcha==3.0.0
django-taggit==3.0.0
kombu==5.2.4
packaging==21.3
Pillow==9.2.0
prompt-toolkit==3.0.31
psycopg2==2.9.3
pyparsing==3.0.9
pytils==0.4.1
pytz==2022.2.1
redis==4.3.4
six==1.16.0
sqlparse==0.4.2
tzdata==2022.2
vine==5.0.0
wcwidth==0.2.5
wrapt==1.14.1
Также в settings.py нужно добавить следующее:
backend/settings.py
ALLOWED_HOSTS = ['127.0.0.1']
CSRF_TRUSTED_ORIGINS = ['http://127.0.0.1']
Пояснение:
- Необходимо добавить для того, чтобы сервер Django работал на деплое.
- Где
127.0.0.1
- ваш будущий домен.
Dockerfile
FROM python:3.10.6-buster
ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1
# Обновление системы
RUN apt-get update
RUN apt-get -y install postgresql-client gcc
# Обновление pip python
RUN pip install --upgrade pip
# Установка требований
COPY requirements.txt ./requirements.txt
RUN pip install -r requirements.txt
# Рабочий каталог
WORKDIR /app
# Копирование проекта
COPY . .
docker-compose.yml
version: '3.8'
volumes:
pgdata:
static:
media:
services:
# Веб-приложение Django (env добавить)
django:
build:
context: .
ports:
- '8000:8000'
container_name: django
env_file:
- docker/env/.env.prod
volumes:
- ./:/app
- static:/app/static
- media:/app/media
depends_on:
- postgres
- redis
command: sh -c "python manage.py collectstatic --no-input &&
python manage.py makemigrations &&
python manage.py migrate &&
gunicorn --workers=4 --reload --max-requests=1000 backend.wsgi -b 0.0.0.0:8000"
# Веб-сервер NGINX
nginx:
build: docker/nginx/
container_name: nginx
restart: always
volumes:
- ./docker/nginx/:/etc/nginx/conf.d
- ./docker/letsencrypt:/etc/letsencrypt
- static:/app/static
- media:/app/media
ports:
- '80:80'
- '443:443'
links:
- django
depends_on:
- django
# База данных PostgreSQL
postgres:
image: postgres:buster
container_name: postgres
restart: always
env_file:
- docker/env/.env.prod
volumes:
- pgdata:/var/lib/postgresql/data/
# База кэширования Redis
redis:
image: redis:buster
container_name: redis
env_file:
- docker/env/.env.prod
expose:
- 6379
volumes:
- ./docker/redis/data:/data
- /.docker/redis/etc/redis.conf:/usr/local/etc/redis/redis.conf
# Асинхронный обработчик
celery-worker:
build: .
container_name: celery-worker
restart: always
env_file:
- docker/env/.env.prod
volumes:
- ./:/app
- media:/app/media
command: celery -A backend worker -B --loglevel=info --logfile=docker/logs/celery-worker.log
depends_on:
- redis
Пояснение:
- В сервисах мы создаем Django, Nginx, Postgres, Redis и Celery контейнеры.
- Задаем определенные названия через
container_name
- Я в работу проекта подключу env_file с глобальными переменными для виртуального окружения.
- .env.prod будет находиться у нас в папке docker/env. Надеюсь вы знаете как работают env файлы, для чего они нужны, и как настраивать данные в settings.py для работы с env.
- Логи celery тоже будут храниться в папке docker/logs/
- А такие данные, как например конфиг и сохраненный кэш будет храниться тоже в папке docker/redis.
Nginx у нас создается из файла Dockerfile, который мы создадим в папке docker/nginx.
docker/nginx/Dockerfile
FROM nginx:latest
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d
Пояснение:
- Устанавливаем последнюю версию nginx, удаляем дефолтный конфиг и копируем свой конфиг. Этот конфиг покажу ниже:
docker/nginx/nginx.conf
upstream django {
server django:8000;
}
server {
listen 80;
# Settings
client_max_body_size 100M;
charset utf-8;
# Gzip
gzip on;
gzip_disable "msie6";
gzip_min_length 1000;
gzip_vary on;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript;
location / {
proxy_pass http://django;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
location /static/ {
alias /app/static/;
expires 15d;
}
location /media/ {
alias /app/media/;
expires 7d;
}
}
Также в папке Docker создам папку logs, redis, env.
В папке env я создам файл .env.prod со своими необходимыми переменными.
DJANGO_SECRET_KEY=
DJANGO_DEBUG=0
CSRF_TRUSTED_ORIGINS=
ALLOWED_HOSTS=
POSTGRES_USER=
POSTGRES_PASSWORD=
POSTGRES_DB=
POSTGRES_HOST=
POSTGRES_PORT=
CELERY_BROKER_URL=redis://redis:6379/0
CELERY_RESULT_BACKEND=redis://redis:6379/0
REDIS_LOCATION=redis://redis:6379/1
RECAPTCHA_PUBLIC_KEY=
RECAPTCHA_PRIVATE_KEY=
EMAIL_HOST=
EMAIL_PORT=
EMAIL_USE_TLS=
EMAIL_HOST_USER=
EMAIL_HOST_PASSWORD=
После = свои значения.
В settings.py подключать следующим образом, пример покажу из небольшого фрагмента кода:
backend/settings.py
import os
SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY')
DEBUG = int(os.environ.get('DJANGO_DEBUG', default=0))
ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS').split()
CSRF_TRUSTED_ORIGINS = os.environ.get('CSRF_TRUSTED_ORIGINS').split()
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ.get('POSTGRES_DB'),
'USER': os.environ.get('POSTGRES_USER'),
'PASSWORD': os.environ.get('POSTGRES_PASSWORD'),
'HOST': os.environ.get('POSTGRES_HOST'),
'PORT': os.environ.get('POSTGRES_PORT'),
}
}
Думаю вам будет ясно, как добавлять значения и для других настроек.
Структура должна получиться такой же:

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