Разница env_file и --env-file в Docker Compose: dev/prod
Разница между директивой env_file в docker-compose.yml и опцией --env-file. Организация .env файлов для dev и prod на Ubuntu. Лучшие практики, приоритеты переменных и примеры конфигураций для безопасного запуска.
В чем разница между директивой env_file в docker-compose.yml и запуском docker-compose с опцией --env-file? Как правильно организовать настройки для разработки (dev) и продакшена (prod) в Docker Compose с использованием .env файлов на Ubuntu с последними версиями Docker и Docker Compose, чтобы избежать запуска неправильных настроек? Какие лучшие практики подключения .env файлов считаются стандартными?
Директива env_file в docker-compose.yml загружает переменные окружения прямо в контейнеры сервисов, делая их доступными внутри приложения, в то время как опция --env-file при запуске docker compose --env-file=.env.dev up задаёт файл для интерполяции переменных в самом compose-файле (как основной .env). Для dev и prod на Ubuntu с Docker Compose v2.24+ организуйте отдельные .env.dev и .env.prod, указывайте их явно при запуске (docker compose --env-file .env.dev up), а секреты храните в env_file с опцией required: false и никогда не коммитьте в Git. Это стандартная практика из официальной документации Docker, минимизирующая риски запуска неверных настроек.
Содержание
- Разница между env_file и --env-file в Docker Compose
- Приоритеты переменных (precedence)
- Организация .env для dev и prod на Ubuntu
- Практические примеры конфигураций
- Лучшие практики подключения .env файлов
- Безопасность и избежание ошибок
- Источники
- Заключение
Разница между env_file и --env-file в Docker Compose
Представьте: вы пишете docker-compose.yml и хотите подсунуть переменные в контейнер. env_file — это директива внутри секции сервиса, типа services: app: env_file: - .env.secrets. Она берёт указанный файл и грубо скидывает все его переменные как environment variables внутрь запущенного контейнера. Приложение внутри увидит их через os.environ или process.env. Плюс, можно несколько файлов — они обрабатываются по порядку, поздние перезаписывают ранние, как указано в документации по env_file.
А --env-file? Это опция командной строки: docker compose --env-file=.env.custom up. Она заменяет дефолтный .env в корне проекта — тот самый файл, который Docker Compose парсит для подстановки ${VAR} прямо в yaml. То есть, интерполяция: ${DB_HOST} в compose превратится в postgres из вашего кастомного файла. Но внутрь контейнера эти переменные не попадут автоматически! Разница огромная: один для контейнера (env_file), другой для парсинга compose (--env-file).
Почему путают? Потому что оба работают с .env-подобными файлами, но контексты разные. В Stack Overflow прямо пишут: env_file — для контейнера, не для сборки или интерполяции compose. А --env-file с docker run вообще для одиночных контейнеров, без compose.
Коротко: env_file = переменные в контейнере. --env-file = переменные для compose-парсера.
Приоритеты переменных (precedence)
Docker Compose не просто берёт переменные — у него строгая иерархия, чтобы избежать хаоса. Вот как это работает по официальным правилам precedence:
environment:в compose (явно заданные в yaml) — топ приоритета.env_file:— следующие, но перезаписываютсяenvironment.- Переменные хоста или дефолтный
.env(для интерполяции). - Dockerfile
ENV/ARG— только если compose их не трогает.
Хостовые env перебивают .env! Если у вас DB_PASSWORD=secret в терминале, ваш .env с другим значением проиграет. В блоге vsupalov это называют “gotcha”. А в issue GitHub docker/compose разбирают: environment всегда доминирует над env_file.
На практике: для docker compose env file (124 запроса в Yandex) это критично. Тестируйте с docker compose config, чтобы увидеть финальные значения.
Организация .env для dev и prod на Ubuntu
На свежем Ubuntu (скажем, 24.04 с Docker 27+ и Compose v2.24.0 по состоянию на 2026-01-19) схема простая: не держите один .env, а разведите на окружения. Создайте:
.env.dev— локалка:DB_HOST=localhost, порты открыты..env.prod— прод:DB_HOST=prod-db.internal, секреты из Vault или SSM.
Запуск: docker compose --env-file .env.dev up -d. Для прод — --env-file .env.prod up. Добавьте в .gitignore: *.env и .env.* кроме шаблонов.
В docker-compose.yml:
services:
app:
env_file:
- config/.env.db # общие для всех
- .env.secrets # optional с required: false (v2.24+)
environment:
- DEBUG=true # перезапишет env_file
env_file можно делать опциональным: env_file: required: false. Если файл пропущен — warning, но не краш. Идеально для dev/prod, где секреты подключают по-разному.
А чтобы избежать фейла: скрипт deploy.sh:
#!/bin/bash
ENV=${1:-dev}
docker compose --env-file .env.${ENV} up -d --build
./deploy.sh prod — и никаких сюрпризов.
Практические примеры конфигураций
Давайте кодом. Базовый docker-compose.yml для Node.js app с PostgreSQL:
version: '3.8'
services:
db:
image: postgres:16
env_file: # внутрь контейнера
- .env.db
environment: # приоритет выше
- POSTGRES_DB=${POSTGRES_DB:-app}
app:
build: .
env_file:
- .env.app
ports:
- "${APP_PORT:-3000}:3000" # интерполяция из --env-file или .env
.env.dev:
APP_PORT=3000
DB_HOST=db
POSTGRES_PASSWORD=devpass
.env.prod:
APP_PORT=80
DB_HOST=prod-db.example.com
POSTGRES_PASSWORD=strong_prod_pass
Запуск dev: docker compose --env-file .env.dev up. Prod: то же с .env.prod. В Warp.dev такой подход хвалят за простоту.
Проверьте: docker compose config покажет подстановку, docker compose logs app — переменные внутри.
Лучшие практики подключения .env файлов
Стандарты из сообщества и Build with Matija:
- Не коммитьте секреты:
.env.secretsв.gitignore. Используйте Docker Secrets или внешние менеджеры (AWS SSM, HashiCorp Vault). - Группируйте файлы:
env_file: - common.env - ${ENV:-dev}.env(но интерполяция в env_file не работает!). - Избегайте
.envкак env_file: Смешивает интерполяцию и контейнер — антипаттерн, по Stack Overflow. - Скрипты и Makefile:
make dev-up ENV=dev. - Тестирование:
docker compose --env-file .env.test config | grep DB. - Множественные env_file: Порядок: базовые → окружение → секреты.
В The Data Farm подчёркивают: держите локальные .env вне Git.
Для docker compose переменные (94 запроса) — всегда docker compose config перед деплоем.
Безопасность и избежание ошибок
Что если запустите prod-скрипт с dev-.env? Беда: открытый порт, слабый пароль. Решение: в CI/CD проверяйте docker compose config | grep -E 'DEBUG|devpass' и фейлите билд.
required: false в env_file спасает от missing secrets. Нет интерполяции в env_file — не пытайтесь ${VAR} внутри него.
На Ubuntu: sudo docker compose --env-file .env.prod up в systemd или с user namespaces. Мониторьте с docker compose ps.
Риски: хост env overrides — экспортируйте чистый терминал или env -i docker compose up.
Источники
- Interpolation | Docker Docs
- Set environment variables | Docker Docs
- Environment variables precedence in Docker Compose
- How can I use environment variables in docker-compose? - Stack Overflow
- Specify the env file docker compose uses - Stack Overflow
- Using env_file with environment · Issue #1171 · docker/compose
- Docker Compose env_file: When to Use vs environment Variables
- Docker ARG, ENV and .env - a Complete Guide
- A Small Lesson on env Files in docker-compose
- Use An .env File in Docker Compose | Warp
Заключение
Разница между env_file (для контейнера) и --env-file (для интерполяции compose) фундаментальна — первая внутри app, вторая для yaml. Для dev/prod на Ubuntu используйте --env-file .env.dev/prod up, группируйте секреты в env_file и проверяйте config. Эти практики из официальной документации Docker и сообщества спасут от фейлов. Начните с шаблонов — и забудьте о случайных деплоях.