Современная веб-разработка всё чаще уходит от монолитных серверов в мир контейнеров, где каждый сервис живёт в изолированной среде. Docker-compose позволяет связать Django-приложение с PostgreSQL базой данных элегантно и предсказуемо, создавая идеальную среду для разработки, тестирования и даже продакшена. В этом руководстве мы разберём каждый шаг подключения, от базовой конфигурации до продвинутых практик.
Почему именно Docker-compose для Django и PostgreSQL?
Традиционная установка PostgreSQL на локальную машину часто приводит к "загрязнению" системы, конфликтам версий и сложностям при переходе между проектами. Docker-compose решает эти проблемы, предоставляя:
- Изоляцию окружений — каждый проект имеет свои версии ПО без конфликтов
- Воспроизводимость — конфигурация описывается кодом (YAML-файл)
- Портативность — проект запускается одинаково на любой системе с Docker
- Простота развёртывания — почти идентичная конфигурация для разработки и продакшена
Docker-compose — это инструмент для определения и запуска многоконтейнерных приложений. В нашем случае это будут два контейнера: для Django и для PostgreSQL.
Структура проекта и базовые файлы
Перед началом убедитесь, что у вас установлены Docker и Docker-compose. Типичная структура проекта:
myproject/
├── docker-compose.yml
├── Dockerfile
├── requirements.txt
└── src/ # Ваш Django-проект
├── manage.py
└── myproject/
└── settings.py
1. Dockerfile для Django
Создайте Dockerfile в корне проекта:
FROM python:3.11-slim ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY ./src . CMD ["gunicorn", "myproject.wsgi:application", "--bind", "0.0.0.0:8000"]
2. docker-compose.yml — сердце конфигурации
Это ключевой файл, связывающий все компоненты:
version: '3.8'
services:
db:
image: postgres:15-alpine
volumes:
- postgres_data:/var/lib/postgresql/data/
environment:
- POSTGRES_DB=mydatabase
- POSTGRES_USER=myuser
- POSTGRES_PASSWORD=mypassword
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U myuser"]
interval: 10s
timeout: 5s
retries: 5
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- ./src:/app
ports:
- "8000:8000"
depends_on:
db:
condition: service_healthy
environment:
- DATABASE_URL=postgres://myuser:mypassword@db:5432/mydatabase
volumes:
postgres_data:
Использование Alpine-версий образов значительно уменьшает размер контейнеров. Для продакшена замените runserver на Gunicorn или uWSGI.
Настройка Django для работы с PostgreSQL в контейнере
Конфигурация settings.py
Обновите настройки базы данных в Django:
import os
from urllib.parse import urlparse
# Получаем URL из переменной окружения или используем значения по умолчанию
DATABASE_URL = os.environ.get('DATABASE_URL',
'postgres://myuser:mypassword@localhost:5432/mydatabase')
parsed_url = urlparse(DATABASE_URL)
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': parsed_url.path[1:], # Убираем первый слэш
'USER': parsed_url.username,
'PASSWORD': parsed_url.password,
'HOST': parsed_url.hostname,
'PORT': parsed_url.port or 5432,
}
}
Установка зависимостей
В requirements.txt обязательно добавьте:
Django>=4.2 psycopg2-binary>=2.9 python-dotenv>=1.0 # для управления переменными окружения
Работа с проектом: основные команды
- Запуск контейнеров:
docker-compose up --build - Запуск в фоновом режиме:
docker-compose up -d - Остановка:
docker-compose down - Просмотр логов:
docker-compose logs -f web - Выполнение команд в контейнере:
docker-compose exec web python manage.py migrate - Создание суперпользователя:
docker-compose exec web python manage.py createsuperuser
Продвинутые практики и оптимизации
Использование .env файла для конфиденциальных данных
Никогда не храните пароли в коде! Создайте файл .env:
POSTGRES_DB=mydatabase
POSTGRES_USER=myuser
POSTGRES_PASSWORD=secure_password_here
DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}
И обновите docker-compose.yml:
environment:
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
Настройка volumes для разработки
Для hot-reload во время разработки используйте bind mounts:
volumes: - ./src:/app - ./static:/app/static # для статических файлов - ./media:/app/media # для медиафайлов
Добавление pgAdmin для управления базой
В docker-compose.yml можно добавить:
pgadmin:
image: dpage/pgadmin4
environment:
- PGADMIN_DEFAULT_EMAIL=admin@example.com
- PGADMIN_DEFAULT_PASSWORD=admin
ports:
- "5050:80"
depends_on:
- db
Распространённые проблемы и их решения
Если Django не может подключиться к PostgreSQL, убедитесь что контейнер базы данных полностью запустился (healthcheck прошёл успешно). Используйте docker-compose logs db для диагностики.
- "Connection refused" ошибка: Убедитесь, что в settings.py указан host='db' (имя сервиса из compose), а не 'localhost'
- Миграции не применяются: Выполните
docker-compose exec web python manage.py migrate - Медленная работа в Windows/Mac: Используйте WSL2 на Windows или увеличьте ресурсы Docker Desktop
- Потеря данных при остановке: Все данные сохраняются благодаря volume 'postgres_data'
FAQ: Часто задаваемые вопросы
Как сохранить данные PostgreSQL между перезапусками?
Docker-compose автоматически сохраняет данные благодаря объявленному тому 'postgres_data'. Данные сохраняются даже после docker-compose down.
Можно ли использовать эту конфигурацию для продакшена?
Базовую структуру — да, но потребуются доработки: использование Gunicorn/uWSGI, настройка Nginx, SSL-сертификаты, правильные настройки безопасности PostgreSQL.
Как импортировать существующую базу данных?
Скопируйте dump-файл в контейнер и выполните восстановление:
docker-compose exec -T db psql -U myuser mydatabase < backup.sql
Почему используется порт 5432:5432 если контейнеры изолированы?
Проброс порта 5432 на хост-машину нужен для подключения внешних инструментов (например, DBeaver, DataGrip) к контейнеру с базой данных.
Как обновить версию PostgreSQL?
Измените тег образа в docker-compose.yml (например, на 'postgres:16-alpine'), сделайте backup базы, пересоздайте контейнеры и восстановите данные.
Можно ли подключить несколько Django-проектов к одной базе?
Технически — да, но это плохая практика. Лучше создавать отдельные базы данных или использовать схемы PostgreSQL для изоляции.