Переменная в Docker Compose не обновилась: найдите значение до пересоздания контейнера

В .env уже написано API_HOST=new.example, а сервис продолжает обращаться к old.example. Кажется, что Compose проигнорировал файл. Но нужно различить два момента: какое значение попало в итоговую конфигурацию и с каким значением был создан работающий контейнер. Смена файла на диске сама по себе не переписывает окружение запущенного процесса.

Сначала найдите, откуда Compose взял значение

Возьмём маленький compose.yaml. Сервису передаётся результат подстановки ${API_HOST}. В соседнем .env лежит новый адрес:

services:
  api:
    image: alpine:3.20
    command: ["sh", "-c", "sleep 3600"]
    environment:
      API_HOST: ${API_HOST}
API_HOST=new.example

Если в оболочке, из которой запускают Compose, уже задано API_HOST=old.example, для подстановки победит значение оболочки. Команда docker compose config --environment показывает значения, взятые для подстановки, а docker compose config — итоговую модель сервиса. В этом случае в обеих проверках для API_HOST будет old.example. Не вставляйте полный вывод в чат или заявку: рядом с нужной строкой могут быть секреты других сервисов.

docker compose config --environment
docker compose config

Исправление здесь — убрать старую переменную из запускающей оболочки либо задать в ней новый адрес. Повторите config теми же флагами -f и --env-file, с которыми запускаете проект. Если модель уже показывает new.example, источник старого значения находится на следующем этапе.

.env, env_file и environment решают разные задачи

Файл .env обычно даёт значения для подстановки в compose.yaml; одно только присутствие строки в нём не создаёт переменную внутри контейнера. Для передачи служат environment, как в примере, или env_file внутри описания сервиса. Если одновременно указаны env_file и явное environment: API_HOST: old.example, явное значение победит. Поэтому сначала смотрите итоговую модель, а затем выясняйте, какая запись её сформировала. Приоритеты Compose полезны именно при таком конфликте.

Также проверьте, что команда читает нужный проект. Другой рабочий каталог, дополнительные файлы через -f и альтернативный --env-file могут дать конфигурацию, отличную от той, которую вы редактировали. Убедиться можно по имени сервиса и разрешённым значениям в docker compose config; для подстановки отдельно смотрите --environment.

Теперь сравните модель с работающим контейнером

Когда config показывает новый адрес, а приложение всё ещё использует старый, контейнер мог быть создан до правки. docker compose restart запускает тот же контейнер заново и не применяет новое окружение из Compose. Чтобы применить новое значение, выполните docker compose up -d api: при изменении конфигурации Compose пересоздаст сервис, и на время пересоздания API прервёт работу. Затем проверьте фактическое значение командой docker compose exec -T api printenv API_HOST и поведением приложения.

Если и после пересоздания процесс обращается к старому адресу, проверьте, читает ли приложение API_HOST вообще. Веб-клиент с адресом API, встроенным при сборке JavaScript, не изменится от новой переменной запуска контейнера: ему нужна новая сборка. Но сначала доведите до совпадения три наблюдения — итоговую модель, окружение контейнера и то, что выводит само приложение. Так причина окажется в конкретном звене, а не в абстрактном «кэше Docker».

Продолжение практики

В платном курсе «Docker и Docker Compose» вы настроите переменные проекта, соедините учебный HTTP-сервис с PostgreSQL, проверите готовность базы и передадите проект другому разработчику. Там же есть практикум с ошибками Compose-конфигурации и диагностика по состоянию контейнера. Откройте пробный урок «Сборка и переменные проекта» и посмотрите программу курса.

Если в конфигурации оказался секрет, полезен разбор секрета в build-arg. Другие поломки запуска собраны в серии статей о Docker.

Продолжить на практике

  • Docker и Docker Compose: контейнеризация приложений ↗

    Упакуйте приложение в Docker и запустите его с PostgreSQL через Compose. Образы, сети, тома, диагностика поломок, обновление версий и восстановление данных — с практикой и итоговым проектом.