Вопрос или проблема
Мой текущий docker-compose.yml
выглядит так:
version: '3'
services:
testsite-nginx:
image: nginx:alpine
container_name: test_site_nginx
restart: unless-stopped
tty: true
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./example.co.uk:/var/www
ports:
# Я действительно хочу сопоставить его с портом 8080 на моем локальном компьютере, а не 80
- 8080:80
networks:
- app-network
testsite-mysql:
image: mysql:5.7.22
container_name: test_site_mysql
restart: unless-stopped
tty: true
ports:
# Я действительно хочу сопоставить его с портом 3309 на моем локальном компьютере, а не 3306
- 3309:3306
environment:
MYSQL_DATABASE: laravel
MYSQL_ROOT_PASSWORD: somethingreallysecure
SERVICE_TAGS: dev
SERVICE_NAME: mysql
volumes:
- dbdata:/var/lib/mysql/
- ./example.co.uk/mysql/my.cnf:/etc/mysql/my.cnf
networks:
- app-network
testsite-app:
build:
context: .
image: example.co.uk/app
container_name: test_site_app
restart: unless-stopped
tty: true
environment:
SERVICE_NAME: app
SERVICE_TAGS: dev
working_dir: /var/www
volumes:
- ./php/local.ini:/usr/local/etc/php/conf.d/local.ini
- ./example.co.uk:/var/www
depends_on:
- testsite-nginx
- testsite-mysql
networks:
- app-network
networks:
app-network:
driver: bridge
volumes:
dbdata:
driver: local
Однако, когда я запускаю docker-compose up --build -d
, а затем запускаю docker-compose ps
, я вижу, что мой контейнер nginx постоянно перезапускается:
$ docker-compose ps
Name Command State Ports
--------------------------------------------------------------------------------------
test_site_app docker-php-entrypoint php-fpm Up 9000/tcp
test_site_mysql docker-entrypoint.sh mysqld Up 0.0.0.0:3309->3306/tcp
test_site_nginx /docker-entrypoint.sh ngin ... Restarting
Я пробовал использовать tty: true
, как упоминалось в предыдущих вопросах на ServerFault, но это не решило проблему, как видно выше. Есть ли какие-либо решения?
При выполнении docker compose logs test_site_nginx
благодаря пользователю на Reddit, я увидел эту ошибку:
2021/01/20 12:37:18 [emerg] 1#1: invalid number of arguments in "user" directive in /etc/nginx/nginx.conf:2
nginx: [emerg] invalid number of arguments in "user" directive in /etc/nginx/nginx.conf:2
Оказалось, что я пропустил точку с запятой в конце строки конфигурации при объявлении
user www-data; # <-- я не добавил ;
После перезагрузки сервис запустился как ожидалось, и мои логи работали нормально.
У меня возникла похожая проблема после перезагрузки моего хоста. Когда хост снова запустился, мой контейнер nginx застрял в цикле перезапуска.
Попытка проверить журналы для контейнера с помощью sudo docker logs <*container_id*> -f
не показывала никаких новых сообщений.
Мне пришлось сделать следующее:
- отключить перезапуск
sudo docker update --restart=no <*nginx-container-id*>
- остановить контейнер
sudo docker stop <*nginx-container-id*>
- удалить контейнер
sudo docker rm <*nginx-container-id*>
При попытке заново собрать контейнер он выдал ошибку “failed to bind host port for 0.0.0.0:80:container_ip:80/tcp address already in use”
sudo lsof -i :80
показал, что nginx использует порт.
Оказалось, что я также имел службу nginx, запущенную на локальном хосте. Не уверен, как и почему. Я остановил её с помощью sudo systemctl stop nginx
и отключил её с помощью sudo systemctl disable nginx
. После этого я смог заново собрать контейнер sudo docker compose up -d
. Всё запустилось и работало как и до перезагрузки.
.
Ответ или решение
Проблема с постоянной перезагрузкой контейнера Nginx в Docker возникает часто и может быть обусловлена различными факторами. Рассмотрим данную ситуацию детально, анализируя предоставленный docker-compose.yml
и указанные ошибки.
Теория
Контейнеры Docker могут входить в состояние перезагрузки по нескольким причинам. Один из частых случаев — это неверная конфигурация приложения или конфигурационного файла. В контексте Nginx это может быть вызвано ошибкой в nginx.conf
. Неправильные или некорректные директивы могут приводить к вынужденной перезагрузке контейнера до тех пор, пока ошибка не будет исправлена.
Docker при этом позволяет указывать политику перезапуска, например, restart: unless-stopped
, что означает, что контейнер будет автоматически пытаться перезапуститься после завершения работы, если его не остановить вручную. Таким образом, контейнер с ошибкой в конфигурации может бесконечно перезагружаться, не начиная корректную работу.
Пример
В предоставленной конфигурации Docker Compose у вас три сервиса: Nginx, MySQL и веб-приложение. Проблема возникает с контейнером Nginx, который находится в состоянии "Restarting". Из логов мы видим ошибку на второй строке файла nginx.conf
:
2021/01/20 12:37:18 [emerg] 1#1: invalid number of arguments in "user" directive in /etc/nginx/nginx.conf:2
nginx: [emerg] invalid number of arguments in "user" directive in /etc/nginx/nginx.conf:2
Эта ошибка указывает на неверную директиву user
, которая была исправлена добавлением необходимой точки с запятой:
user www-data;
Другое замечание касается конфликта портов, который может возникнуть, если другой процесс уже использует необходимый порт. В вашем случае, на порту 80 уже работала другая инстанция Nginx, не связанная с Docker. Это привело к ошибке привязки порта при перезапуске контейнера. Эту проблему удалось разрешить остановкой и отключением локального сервиса Nginx.
Применение
Рассмотрев возможные причины и решение этой проблемы, можно сделать несколько выводов и рекомендаций:
-
Проверка конфигурационных файлов: Всегда проверяйте на синтаксические ошибки все конфигурационные файлы сервисов, работающих в контейнерах. Вы можете использовать команду
nginx -t
для проверки конфигурации Nginx. -
Анализ логов: Используйте логи для диагностики проблем. Команда
docker logs <container_id>
предоставит информацию о том, какие именно ошибки происходят при запуске. -
Отсутствие конфликтов портов: Перед запуском контейнеров убедитесь, что порты, требуемые для их работы, свободны. Это можно сделать командами
lsof -i :port_number
для проверки, какие процессы используют данный порт. -
Правильная настройка политики рестарта: Политика
unless-stopped
может иногда запутывать диагностику, так как контейнер будет постоянно перезапускаться. Используйтеno
во время диагностики, чтобы контейнер не пытался перезагрузиться самостоятельно. -
Контроль за внешними сервисами: Убедитесь, что версии приложений, установленные на главной машине, не конфликтуют с контейнеризированными версиями тех же сервисов.
При тщательном подходе и внимании к деталям, решение подобных проблем сводится к методичному убиранию препятствий и полному анализу всех входных данных. Надеюсь, приведенные рекомендации и рассуждения помогут в быстром решении подобных проблем в будущем.