docker compose restart не перечитывает .env
Значение в .env изменено, docker compose restart прошёл, приложение видит старое.
dockerdocker compose
Поменяли переменную в .env, перезапустили сервис — приложение упорно работает
со старым значением.
docker compose restart app # прошло, контейнер поднялся
Логи чистые, контейнер Up, а внутри — прежнее окружение.
Причина
restart не пересоздаёт контейнер. Он останавливает и запускает тот же самый
контейнер, с тем же набором переменных окружения.
Переменные фиксируются в момент создания контейнера. .env читается тогда же —
Compose подставляет значения в конфигурацию и запекает их в объект контейнера.
Дальше файл никого не интересует: контейнер живёт с тем снимком окружения,
который получил при рождении.
Проверяется в лоб:
docker compose exec app env | grep ИМЯ_ПЕРЕМЕННОЙ
Видите старое значение при новом .env — вопрос закрыт.
Решение
Пересоздать контейнер:
docker compose up -d app
up -d сравнивает желаемую конфигурацию с фактической, видит расхождение
и пересоздаёт контейнер с новым окружением. Именно это и нужно.
Для верности, когда важно исключить сомнения:
docker compose up -d --force-recreate app
Почему это ловит даже опытных
restart звучит как «применить изменения». В большинстве систем перезапуск сервиса
именно этим и занимается — systemd перечитает unit, nginx перечитает конфиг.
У Docker другая модель: контейнер — это не процесс, а объект с зафиксированной
конфигурацией, и «перезапуск» относится к процессу внутри, а не к объекту.
Тот же принцип объясняет соседние сюрпризы: правка docker-compose.yml тоже
не применяется по restart, изменение образа — тоже. Правило одно:
Поменяли то, что описывает контейнер, — нужен
up -d. Поменяли то, что читается на лету внутри него, — хватитrestart.
Как не наступить снова
В скриптах выката использовать up -d, а не restart. Он идемпотентен: если
менять нечего, контейнер не тронется. Проигрыша нет, а класс ошибок закрывается
целиком.