Переменные окружения и конфигурация контейнеров

Рейтинг: 75.8% · 12 голосов
Практический курс по Docker: образы, контейнеры, тома, сети, Compose и продакшен. Уроки по главам с обсуждением.
Ответить
Аватара пользователя
Marina_DevOps
Сообщения: 25
Зарегистрирован: 11 май 2026, 05:31

Переменные окружения и конфигурация контейнеров

Сообщение Marina_DevOps »

АкадемияDocker с нуляГлава 7 из 17
Оглавление курса (17)
  1. Что такое Docker и какие задачи он решает
  2. Установка Docker и запуск первого контейнера
  3. Образы: слои, теги и реестр Docker Hub
  4. Пишем свой Dockerfile
  5. Тома и хранение данных: volumes и bind mounts
  6. Сети в Docker: связываем контейнеры между собой
  7. Переменные окружения и конфигурация контейнеров (вы здесь)
  8. Docker Compose: поднимаем многоконтейнерное приложение
  9. Оптимизация образов: multi-stage сборка, размер и кэш слоёв
  10. Логи, отладка и мониторинг контейнеров
  11. Базовая безопасность контейнеров
  12. Подготовка к продакшену: что важно учесть
  13. Dockerfile глубже: ENTRYPOINT и CMD, HEALTHCHECK, .dockerignore, запуск не от root
  14. Реестры образов: приватные registry, push и pull, теги и digest, imagePullSecrets
  15. BuildKit и buildx: multi-arch сборки, секреты сборки, экспорт кэша
  16. Docker в CI/CD: автосборка, сканирование образов (Trivy, Docker Scout), публикация
  17. Итоговый проект и куда расти: от Dockerfile до прода, обзор оркестрации (Kubernetes, Podman, OCI)
Один и тот же образ должен работать на ноутбуке разработчика, на тестовом стенде и в продакшене. Отличается только конфигурация: адрес базы, пароли, режим отладки. Зашивать её в образ нельзя, иначе под каждое окружение придётся пересобирать. Эта глава о том, как передавать настройки в контейнер снаружи и какой способ когда уместен.

Передача переменных при запуске:

Самый частый способ, флаг -e у docker run. Официальный образ postgres без пароля вообще не стартует, так что пример живой:

Код: Выделить всё

docker run -d --name db \
  -e POSTGRES_PASSWORD=secret123 \
  -e POSTGRES_DB=shop \
  postgres:16
Если указать -e без значения, например -e POSTGRES_PASSWORD, Docker возьмёт значение из окружения вашей оболочки. Удобно, чтобы не светить пароль в истории команд.

Проверить, что контейнер реально получил, можно командой docker exec db env, она печатает всё окружение главного процесса. А docker inspect db покажет тот же список в блоке Config.Env. Отсюда важный вывод: любой, у кого есть доступ к Docker на этой машине, видит ваши переменные через inspect. Для обычной конфигурации это нормально, а для серьёзных секретов в продакшене используют другие механизмы, вернёмся к этому в главе 11.

Файл с переменными:

Когда переменных больше трёх, флаги превращаются в кашу. Сложите их в файл и подключите через --env-file:

Код: Выделить всё

# app.env
DATABASE_URL=postgres://app:secret123@db:5432/shop
REDIS_HOST=cache
APP_DEBUG=false

# запуск:
# docker run -d --env-file app.env myapp:1.2
Формат файла нарочно примитивный: KEY=VALUE, по одной паре на строку, строки с # игнорируются. Никакой подстановки переменных и никакой обработки кавычек: если написать APP_NAME="shop", кавычки станут частью значения. Это не shell-скрипт, хотя выглядит похоже. И сразу добавьте такой файл в .gitignore, а не после первого утёкшего пароля.

ENV и ARG в Dockerfile:

В Dockerfile из главы 4 вы уже встречали инструкцию ENV. Она задаёт значение по умолчанию, которое попадает в каждый контейнер из этого образа:

Код: Выделить всё

FROM node:20-alpine
ARG BUILD_VERSION=dev
ENV NODE_ENV=production \
    APP_PORT=3000
LABEL version=$BUILD_VERSION
WORKDIR /app
COPY . .
CMD ["node", "server.js"]
ARG живёт только во время сборки (docker build --build-arg BUILD_VERSION=1.4.2 .) и в готовом контейнере его уже нет. ENV наоборот переезжает в рантайм, и его можно перекрыть при запуске. Приоритет простой: -e и --env-file сильнее, чем ENV из Dockerfile.

И ARG, и ENV остаются видимыми в docker history и docker inspect образа. Передавать через них токены и пароли на этапе сборки нельзя, они останутся в слоях навсегда.

Конфиги целиком:

Не всё сводится к переменным. Если приложению нужен полноценный конфиг-файл, например nginx.conf, проще смонтировать его с хоста, как в главе 5:

Код: Выделить всё

docker run -d -p 8080:80 \
  -v "$(pwd)/nginx.conf:/etc/nginx/nginx.conf:ro" \
  nginx:1.27
Хорошие образы комбинируют оба подхода: entrypoint-скрипт читает переменные окружения и генерирует конфиг при старте. Загляните как-нибудь в entrypoint официального образа postgres, поучительное чтение.

Типичные грабли:

Переменные нельзя поменять у работающего контейнера. docker exec -e подсунет значение только в ту команду, которую вы выполняете, сам контейнер не изменится. Нужно новое окружение, пересоздавайте контейнер. Это нормально, контейнеры одноразовые.

Вторая ловушка, кавычки и пробелы в env-file, о ней выше. Третья, опечатка в имени переменной: Docker имена не валидирует, контейнер молча стартует без нужного значения, а приложение падает с невнятной ошибкой где-то глубоко. Привычка прогонять docker exec ... env после первого запуска экономит часы.

Четвёртая: ENV с паролем, добавленный в Dockerfile "временно, для теста", имеет свойство уезжать в реестр вместе с образом. Проверяйте docker history перед push.

Что в итоге: переменные окружения передаются через -e, --env-file и ENV, приоритет у того, что задано при запуске. Секреты в образ не зашиваются, объёмные конфиги монтируются томами. В следующей главе соберём всё наработанное в docker-compose.yml, и там переменные заиграют по-новому: Compose умеет подставлять их прямо в свою конфигурацию из файла .env.
👍7 ❤️2 🔥2 😄 🤔1
✔ Лучший ответ сформирован автоматически — vimsmith
Marina_DevOps писал(а):если написать APP_NAME="shop", кавычки станут частью значения вот на это я убил вечер на прошлой неделе. приложение падало с invalid connection string, а в DATABASE_URL приехали кавычки из env-file, который я скопировал из docker-compose доков. так что да, форматы у env-file для docker run и для compose разные, имейте в виду
Перейти к ответу →
Аватара пользователя
vimsmith
Сообщения: 1
Зарегистрирован: 27 май 2026, 12:03

Re: Переменные окружения и конфигурация контейнеров

Сообщение vimsmith »

✔ Лучший ответ — сформирован автоматически
Marina_DevOps писал(а):если написать APP_NAME="shop", кавычки станут частью значения
вот на это я убил вечер на прошлой неделе. приложение падало с invalid connection string, а в DATABASE_URL приехали кавычки из env-file, который я скопировал из docker-compose доков. так что да, форматы у env-file для docker run и для compose разные, имейте в виду
👍 ❤️2 🔥 😄 🤔1
Аватара пользователя
Boome
Сообщения: 1
Зарегистрирован: 14 май 2026, 07:24

Re: Переменные окружения и конфигурация контейнеров

Сообщение Boome »

а если одна и та же переменная есть и в ENV в Dockerfile, и в env-file, но в файле она пустая, типа APP_DEBUG= без значения? контейнер получит пустую строку или дефолт из образа?
👍2 ❤️1 🔥 😄 🤔
Аватара пользователя
martynho
Сообщения: 1
Зарегистрирован: 22 май 2026, 07:02

Re: Переменные окружения и конфигурация контейнеров

Сообщение martynho »

спасибо за приоритеты, наконец уложилось в голове. проверил на постгресе: задал POSTGRES_DB в Dockerfile своего образа, перекрыл через -e, в inspect видно именно значение из -e. и про docker history не знал, нашел у себя в старом образе токен от приватного npm, который туда положил полгода назад. пошел перевыпускать
👍2 ❤️ 🔥2 😄 🤔
Аватара пользователя
shadow4
Сообщения: 1
Зарегистрирован: 15 май 2026, 21:17

Re: Переменные окружения и конфигурация контейнеров

Сообщение shadow4 »

добавлю из опыта: env-file на сервере стоит класть с правами 600 и владельцем root или deploy-юзера. через inspect его содержимое все равно увидит любой из группы docker, но хотя бы случайный юзер по ssh файл не прочитает. и в бекапы он тоже попадает, об этом часто забывают
👍 ❤️ 🔥 😄 🤔
Ответить
← Предыдущая глава
Сети в Docker: связываем контейнеры между собой
Следующая глава →
Docker Compose: поднимаем многоконтейнерное приложение

Все главы курса «Docker с нуля»

Поделиться темой: ✈ Telegram VK

Вернуться в «Docker с нуля»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость