Как настроить docker ports и environment в docker compose
В этом руководстве мы подробно разберём параметры docker-compose.yml: открытие портов через ports, настройку сетей через networks, управление переменными окружения (environment variables) с использованием .env-файлов. Все настройки рассмотрим на примере запуска популярного Python-фреймворка Django.
Сетевые настройки сервиса в docker compose: ports и networks
Сетевые настройки в файле docker-compose.yml определяют, как контейнер будет взаимодействовать с другими сервисами или с пользователями. Без этих настроек приложение останется изолированным: оно будет недоступно для подключения из браузера, а другие сервисы не смогут с ним взаимодействовать. В docker-compose.yml за это отвечают два параметра: ports и networks.
Настройка docker-compose.yml: ports
Параметр ports в docker-compose.yml открывает доступ к приложению внутри контейнера для внешних клиентов: браузера, curl или других сервисов. Существует несколько форматов указания портов.
ports:
- "8000:80"^O Записать ^X ВыходСамый простой и распространённый способ. В примере порт 8080 на хосте перенаправляется на порт 80 внутри контейнера (формат «хост:контейнер»). Если веб-сервер внутри контейнера слушает порт 80, то после проброса приложение станет доступно в браузере по адресу http://localhost:8080. По умолчанию Docker использует TCP, который гарантирует доставку данных. Указывать протокол явно («8080:80/tcp» или «8080:80/udp») нужно только для UDP-сервисов, где важнее скорость, а не гарантия доставки (например, видеопотоки или DNS), либо когда один порт работает сразу по обоим протоколам.
Проброс диапазона портов используется, когда приложению нужно слушать несколько портов одновременно.
ports:
- "8000-8010:8000-8010"^O Записать ^X ВыходТакая запись создаёт попарное соответствие:
Количество портов слева и справа должно совпадать. Эту настройку используют для приложений с динамическими портами, например медиа-серверов или SIP-телефонии, чтобы не прописывать каждый порт отдельной строкой.
Настройка docker-compose.yml: networks
По умолчанию Docker Compose создаёт для всех сервисов одну общую сеть. В ней контейнеры видят друг друга по имени и могут обмениваться данными без ограничений.
Чтобы изолировать сервисы, можно использовать секцию networks. Вы можете создать отдельные сети и явно указать их в настройках каждого сервиса. Контейнер будет подключён только к перечисленным сетям и не увидит сервисы из других сетей. Например, так можно отделить базу данных от веб-сервера.
services:
web:
image: python
networks:
- frontend
# другие настройки сервиса
api:
image: my-api
networks:
- frontend
- backend
# другие настройки сервиса
db:
image: postgres
networks:
- backend
# другие настройки сервиса
networks:
frontend:
backend:^O Записать ^X ВыходВ этом примере созданы две изолированные сети: frontend и backend.
Корневая секция networks в конце файла обязательна. Без неё Docker Compose не создаст указанные сети и выдаст ошибку при запуске.
Переменные окружения environment и env_file
Переменные окружения в docker-compose.yml позволяют вынести настройки приложения (например: логин, пароль, параметры подключения) из кода в конфигурационный файл. Это сделано для того, чтобы не хранить чувствительные данные внутри образа и иметь возможность изменить их без пересборки. В docker-compose.yml для этого используются два параметра: environment и env_file.
Параметр docker-compose.yml environment
Параметр environment позволяет задать переменные окружения (environment variables) внутри файла docker-compose.yml. При запуске Docker передаёт эти переменные контейнеру, который использует их как системные настройки.
У переменных окружения нет универсального списка, потому что сервисы работают со своим набор параметров. Например, образу postgres нужны: пользователь (POSTGRES_USER) и пароль (POSTGRES_PASSWORD). Чтобы правильно задать переменные окружения для запуска сервиса необходимо ознакомиться с его документацией.
Переменные задаются отдельно для каждого сервиса. Они не являются общими для всего файла docker-compose.yml. Если двум контейнерам нужна одна и та же переменная (например, TZ), её нужно прописать в секции environment обоих сервисов.
Внутри секции environment используется формат словаря YAML (KEY: value). Если значение (value) содержит особые символы (например, #, {, }), его нужно заключать в двойные кавычки. Без них YAML интерпретирует эти символы как часть синтаксиса и выдаст ошибку парсинга при сборке docker-compose.yml:
Также поддерживается строковый формат KEY=value, но его применяют в основном в .env-файлах.
services:
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: homeassistant
POSTGRES_PASSWORD: mysecretpassword
POSTGRES_DB: hass
TZ: Europe/Moscow^O Записать ^X ВыходВ этом примере база данных создастся с суперпользователем homeassistant, паролем mysecretpassword и базой hass. Часовой пояс TZ опционален и нужен, чтобы время в логах и записях совпадало с вашим регионом.
Использование сикретов в файле удобно при локальной разработке, но для продакшена пароли и ключи лучше выносить в отдельный .env-файл, чтобы не хранить их в открытом виде в конфигурации.
Параметр docker-compose.yml env_file
Параметр env_file позволяет вынести переменные окружения (environment variables) в отдельный файл, который обычно называется .env и размещается рядом с docker-compose.yml. В самом compose-файле достаточно указать путь к нему. Один и тот же .env могут использовать сразу несколько сервисов:
services:
db:
image: postgres:16-alpine
env_file:
- .env
api:
image: my-api
env_file:
- .env^O Записать ^X ВыходСинтаксис наполнения .env-файла отличается от YAML: каждая строка в нем содержит одну переменную в виде KEY=value, без отступов и кавычек, а комментарии начинаются с #:
# Общие переменные для обоих сервисов
TZ=Europe/Moscow
# Переменные только для PostgreSQL (api их проигнорирует)
POSTGRES_USER=homeassistant
POSTGRES_PASSWORD=mysecretpassword
POSTGRES_DB=hass
# Переменные только для API (PostgreSQL их проигнорирует)
API_PORT=8000
DB_HOST=db^O Записать ^X ВыходКаждый сервис получает все переменные из файла, но использует только те, которые ему нужны — остальные игнорируются. Если переменная указана и в env_file, и в environment, приоритет будет у значения из environment.
Для разделения конфигураций продакшена и тестовой среды используют разные файлы: .env.prod, .env.test, .env.dev. Путь к нужному файлу можно указать напрямую в docker-compose.yml или переопределить при запуске через флаг —env-file:
# Запуск с тестовой конфигурацией
docker compose --env-file .env.test up -d
# Запуск с продакшен-конфигурацией
docker compose --env-file .env.prod up -dФайлы с сикретами принято добавлять в .gitignore, чтобы случайно не опубликовать их в репозитории.
Запуск Python-фреймворка Django через Docker Compose
Django — это популярный фреймворк для создания веб-приложений на языке Python. Вместо установки Python, его зависимостей и базы данных на хост — можно использовать технологию Docker для запуска проекта. Этот способ упрощает развёртывание: все настройки для работы с Python уже есть в сборке и готовы к использованию.
Подготовка файлов для Django на хосте
Перед тем как начать описывать сервисы в docker-compose.yml нужно создать базовую структуру проекта Django на хосте. Для работы в Docker будут нужны четыре файла и ниже мы создадим каждый из них.
Для начала, перейдите в директорию проекта (там где лежит docker-compose.yml) и создайте произвольную подпапку для Django-приложения, например, /app.
cd ~/docker_projects && mkdir app && cd appВсе файлы для Django будут находиться внутри этой произвольной папки app. В дальнейшем эту директорию мы укажем в docker-compose.yml как контекст сборки.
Теперь создадим файлы для Django.
Сверьте список файлов в вашей директории с изображением ниже. У вас должны появиться те же файлы и папки.

Создание docker-compose.yml для запуска Django-приложения
Теперь, когда все файлы готовы, создадим файл docker-compose.yml в корне проекта (docker-projects), рядом с папкой /app. Конфигурация отличается в зависимости от выбранной базы данных.
docker-compose.yml для Django с SQLite
Если вы не дорабатывали settings.py под PostgreSQL и будете использовать SQLite, то база данных будет храниться в файле внутри контейнера. Внешний сервис БД в этом случае не нужен, поэтому конфигурация будет состоять только из веб-сервиса.
Создадим docker-compose.yml:
nano docker-compose.ymlНаполним файл инструкциями для запуска Django с SQLite:
services:
djangoweb:
build: ./app
container_name: django_web
ports:
- "8000:8000"
env_file:
- .env^O Записать ^X ВыходСоздайте в директории проекта рядом с docker-compose.yml файл .env с переменными для Django. Стандартный settings.py не читает параметры подключения к БД из окружения, поэтому секция DB_* для sqlite не нужна:
nano .env# Переменные Django
WEB_DEBUG=1
WEB_SECRET_KEY=your-secret-key-here^O Записать ^X ВыходОтдельные переменные для подключения к SQLite не нужны. Стандартный settings.py уже содержит конфигурацию SQLite по умолчанию, а база данных хранится в файле db.sqlite3 внутри контейнера.
docker-compose.yml для Django с PostgreSQL
Если вы будете использовать PostgreSQL вместо SQLite и не доработали settings.py ранее, сделайте это сейчас. База данных запускается как отдельный контейнер, а веб-сервис связывается с ней через общую сеть и переменные окружения. Параметр depends_on гарантирует, что веб-сервис запустится только после старта сервиса базы данных.
Создадим docker-compose.yml и наполним его инструкциями:
nano docker-compose.ymlservices:
djangoweb:
build: ./app
container_name: django_web
ports:
- "8000:8000"
env_file:
- .env
depends_on:
- db
db:
image: postgres:15
container_name: django_db
env_file:
- .env^O Записать ^X ВыходСоздайте в директории проекта рядом с docker-compose.yml общий файл .env с переменными для Django и PostgreSQL. Значения DB_* из файла должны совпадать со значениями, указанными в os.getenv() внутри settings.py:
nano .env# PostgreSQL (создание базы и пользователя)
POSTGRES_USER=admin
POSTGRES_PASSWORD=supersecret123
POSTGRES_DB=mysite_db
# Подключение Django к БД
DB_HOST=db
DB_PORT=5432
DB_USER=admin
DB_PASSWORD=supersecret123
DB_NAME=mysite_db
# Переменные Django
WEB_DEBUG=1
WEB_SECRET_KEY=your-secret-key-here^O Записать ^X ВыходСборка и запуск контейнеров Django
Теперь все файлы готовы, можно собирать образ и запускать сервисы:
docker compose up --build -dФлаг -d запускает контейнеры в фоне и освобождает терминал. Если позже вы измените код или зависимости и захотите пересобрать образ заново, просто повторите эту команду — Docker автоматически подхватит изменения. Подробнее о том, как работает сборка, пересоздание контейнеров и управление жизненным циклом (остановка, логи, удаление), мы разбирали в прошлой статье.
Независимо от того, какая СУБД была выбрана, Django не создаёт таблицы автоматически при первом запуске приложения, потому нужно выполнить команду миграции вручную:
docker compose exec djangoweb python manage.py migrateЭта команда выполняется внутри запущенного контейнера djangoweb. Она создаёт системные таблицы (пользователи, сессии, права доступа) и применяет все миграции ваших приложений.
Далее откройте в браузере http://localhost:8000 и вы увидите стартовую страницу Django.

Итоги: ports, environment и запуск многоконтейнерных приложений
В этой статье мы успешно собрали многоконтейнерное приложение на примере популярного Python-фреймворка Django. Разобрали как работает связка веб-сервиса и базы данных PostgreSQL через docker-compose.yml. Вынесли чувствительные настройки приложения в .env — файл.
Следующий шаг — научиться работать с томами (volumes). Без них данные в базе и изменения в коде будут теряться при пересоздании контейнеров, что критично для любой разработки.


