К содержимому

nginx в контейнере не видит правку конфига, хотя файл смонтирован

Конфиг изменён в примонтированном файле, nginx -s reload проходит, поведение прежнее.

dockernginx

Конфиг nginx проброшен в контейнер через bind-mount. Правите файл на хосте, делаете reload — поведение не меняется.

docker compose exec server nginx -s reload   # прошло без ошибок

Ошибки нет, значит конфиг валиден. Но работает старый.

Причина

Bind-mount отдельного файла в Docker привязывается к иноде, а не к пути. Многие редакторы при сохранении не пишут в тот же файл: они создают новый и переименовывают его поверх старого — так безопаснее, при сбое не остаётся обрезанного файла.

После такого сохранения на хосте лежит новая инода. Контейнер продолжает видеть старую — ту, которую примонтировали при старте. Файл внутри и файл снаружи разъехались, хотя путь один и тот же.

Проверяется прямо:

docker compose exec server cat /etc/nginx/conf.d/default.conf | head -20

Если внутри старое содержимое — дело именно в этом, и reload тут бессилен: он честно перечитывает файл, который видит контейнер.

Решение

Перезапустить контейнер — при старте монтирование выполнится заново:

docker compose restart server

Чтобы не возвращаться к этому: монтировать каталог, а не отдельный файл.

volumes:
  - ./nginx/conf.d:/etc/nginx/conf.d:ro   # каталог — переживает пересоздание файлов

С каталогом подмена инод внутри не ломает связь, и reload начинает работать так, как от него ждут.

Где ещё это стреляет

Тот же механизм — с любым одиночным файлом в bind-mount: .env, конфиги приложения, сертификаты. Симптом всегда одинаковый и всегда сбивает с толку: на хосте новое, в контейнере старое, никакой ошибки.

Правило простое: монтируем каталоги, файлы — только когда точно знаешь, что их не пересоздают.

Дальше

Новые разборы выходят в Telegram раньше, чем попадают сюда. Без анонсов курсов — только материалы.

Читать в Telegram →