LINUX.ORG.RU
ФорумAdmin

Docker не перезапускает контейнеры при перезагрузке хоста

 ,


0

2

Суть проблемы: есть docker-compose.yml следующего вида:

services:
  cnt1:
    <skip>
    restart: always
    networks:
      - servicenet
    <skip>

  cnt1-zerotier:  
    image: zerotier/zerotier:1.14.0
    <skip>
    restart: always
    depends_on:
      cnt1:
        condition: service_started
        restart: true
    network_mode: service:cnt1
    devices:
      - /dev/net/tun:/dev/net/tun
    cap_add:
      - NET_ADMIN

networks:
  servicenet:
    external: true

При перезагрузке хоста наблюдаю следующее - примерно каждый второй раз после окончания загрузки контейнер cnt1-zerotier находится в статусе Exited - code 255. Логи у контейнера пустые. В /var/log/docker.log упоминания контейнера нет. Если перезапустить контейнер вручную или сделать docker-compose down/up всего стэка - всё прекрасно подымается(каждый раз) и работает.

Таких compose-стэков несколько и с ними наблюдается одна и та же описанная проблема. Из общего знаменателя только - использование одним контейнером сети другого.

Что я пробовал:
- менять 'service:cnt1' на 'container:cnt1' (по рекомендациям в этих ваших Интернетах);
- менять 'condition: service_started' на 'condition: service_healthy'

Результат - ничего не поменялось, контейнер при перезапуске хоста по прежнему стартует не всегда.

В данный момент вставлен костыль в cron, который перезапускает контейнер, если он находится в статусе Exited, но хотелось бы разобраться какого черта происходит.

Просьба к коллективному разуму о помощи: может не хватает какого-то параметра и я что-то упустил, читая маны?

Или возможно изначальную задачу надо решать по другому? Сама задача выглядит следующим образом: дать определенному контейнеру(не всему хосту!) доступ в VPN-сеть(в данном случае Zerotier), не пересобирая образ самого контейнера и не запуская в нём дополнительных процессов.

★★★★★

Последнее исправление: Pinkbyte (всего исправлений: 4)

Тут явно что-то не так.

Есть мысль, что надо либо этот zerotier поднимать внешними средствами (тут понадобится намного больше контекста).

Либо надо сделать, чтобы контейнер поднимался только после того, как запустится контейнер с zerotier (depends_on: zerotier, condition: service_healthy, и добавить healthchecks).

Chiffchaff
()
Ответ на: комментарий от Chiffchaff

Есть мысль, что надо либо этот zerotier поднимать внешними средствами (тут понадобится намного больше контекста).

Сейчас это делается костылем в cron, но оставлять так не хотелось бы

Либо надо сделать, чтобы контейнер поднимался только после того, как запустится контейнер с zerotier (depends_on: zerotier, condition: service_healthy, и добавить healthchecks).

healthcheck-и есть, зависимости прописаны, они не помогают, как я уже говорил. Менять зависимости контейнеров и network/network_mode местами пробовал - ситуация аналогичная, просто не стартует контейнер с приложением, а контейнер с zerotier чувствует себя прекрасно. Проблемный контейнер - всегда тот где прописан network_mode

Pinkbyte ★★★★★
() автор топика
Последнее исправление: Pinkbyte (всего исправлений: 3)
Ответ на: комментарий от splinter

Блок depends_on собственно и появился в попытке решить эту проблему, его убирание проблему не устраняет :-)

Ручной рестарт из консоли работает, из крона - тоже. Хотелось бы чтобы docker это сам решал, без вмешательства со стороны.

Pinkbyte ★★★★★
() автор топика
Ответ на: комментарий от Pinkbyte

Не помню подробностей — лень копировать твой скрипт в бот(и че ты сам этого еще не сделал?)

В общем, в docker-compose нормально функционирующего решения для старта второго контейнера строго после первого — нет (как и нет много чего еще, потому в проде никто его и не пользует). Он пользуется скорей или для одновременного старта всех описанных в нем контейнеров, или для ситуативного запуска вручную части из них по тегах или именам.

По-ленивому, можно наговнокодить таймер перед запуском основного приложения в cnt1-zerotier, если сеть не критична (кстати не хочешь организовать сеть между ними по-человечески?)

А по факту, или оркеструй их скриптами и докером без compose, или уже зови конницу (swarm, kubernetes или че там щас модно)

hargard ★★★
()
Последнее исправление: hargard (всего исправлений: 1)
Ответ на: комментарий от hargard

@hargard дело говорит, depends_on не работает нихрена, так задумано. Я напилил враппер для энтрипоинта, чтобы эту проблему решить (у меня аппки ждут опенбао для того, чтобы секреты забрать).

pekmop1024 ★★★★★
()
Ответ на: комментарий от hargard

лень копировать твой скрипт в бот(и че ты сам этого еще не сделал?)

Мой опыт решения проблем через ИИ резко отрицательный - по финальным результатам еще ни разу не натыкался на правдивые ответы, а не на галлюцинированный бред.

Что-то простое вида «как написать разрешающее правило для iptables на такой-то порт» спрашивать не пробовал - я и сам такое умею :-)

кстати не хочешь организовать сеть между ними по-человечески?

Готов выслушать предложения о том как сделать нормально, чтобы и сам сервис мог достучаться через VPN до нужных ресурсов и к нему могли обратиться по VPN-адресу другие клиенты VPN.

или уже зови конницу

Kubernetes - сразу нет, это для моих целей дикий overkill, я тратить на обслуживание всего хозяйства буду больше времени, чем оно работать будет, это я уже проверил. Кубер хорош, когда у тебя команда из минимум трех-четырех человк

В Swarm впринципе depends_on не работает. И network_mode - тоже, но если для host networking можно накостылять через отдельный external network с именем host(да, я такое делал), то вот поделить один сетевой стек между двумя контейнерами в Swarm у меня сходу не получилось.

Pinkbyte ★★★★★
() автор топика
Ответ на: комментарий от pekmop1024

Ну у меня он на простых примерах работает, а вот тут какой-то дикий затык случился. И ладно бы он перезапускал контейнер после такого фэйла(restart: always же), но складывается ощущение что он просто при старте не видит network namespace другого контейнера(потому что тот не стартанул еще) и складывает лапки типа «ну и хрен с ним».

Pinkbyte ★★★★★
() автор топика
Ответ на: комментарий от pekmop1024

Веришь нет - никак мне Portainer с кубером не помог(в отличие от standalone докера и swarm, где я юзаю его плотно). Все равно то одно отваливалось, то другое и приходилось лезть к консоль и дербанить kubectl.

Может я просто не умею готовить кубер, тут спорить не буду. Со Swarm таких проблем я не имел. Зато честно скажу, имел другие. Ведь если в кубере есть несколько достаточно живых shared storage-ей которые разворачиваются в режиме далее-далее-далее(и потом еще и работают!), то в Swarm пришлось делать всё самому(CephFS+AutoFS оказалось единственным стабильно-рабочим вариантом у меня)

Pinkbyte ★★★★★
() автор топика
Ответ на: комментарий от Pinkbyte

Так она там и так external: true, куда еще статичнее?

ну, она должна при этом еще и существовать независимо от контейнеров, я про это. Ее не поднимает какой-то еще контейнер?

pekmop1024 ★★★★★
()
Ответ на: комментарий от pekmop1024

ks3 на трех нодах(HA) у меня дважды эпично развалился так, что я не смог его починить.

В одном случае etcd как-то похерился. В другом, я уже и не вспомню что именно пошло не так, просто отказывались pod-ы стартовать.

Знакомый куберовод посмотрев логи в последнем случае посоветовал все снести и накатить из бэкапа. Я его послушал, только теперь там не k3s, а swarm. Который, в отличие от кубера уже полтора годика отпахал.

Так что без поддерживающего плеча(то есть в одиночку) я больше в пет-проектах своих в кубер не сунусь, накушался.

Pinkbyte ★★★★★
() автор топика
Последнее исправление: Pinkbyte (всего исправлений: 1)
Ответ на: комментарий от pekmop1024

Нет, не поднимает, она заранее создана. И если просто два контейнера на нее ссылаются(в пределах одного yaml или в разных) - они прекрасно и всегда подымаются при ребуте

Pinkbyte ★★★★★
() автор топика
Ответ на: комментарий от pekmop1024

Нет, это другой сервер, так standalone docker

Про неумение Swarm-а в depends_on и network_mode я сам чуть выше упоминал :-)

Pinkbyte ★★★★★
() автор топика
Последнее исправление: Pinkbyte (всего исправлений: 1)
Ответ на: комментарий от Pinkbyte

Я посмотрел на свой стек с ваергардом, там у обоих контейнеров выставлено. Не помню уже с чем связано, дела давно минувших дней. А портейнер на этом хосте есть?

pekmop1024 ★★★★★
()
Ответ на: комментарий от pekmop1024

Есть. Но кажись он тут тоже не помощник:

If you want services to be up after an OS reboot, better configure a systemd service to execute docker compose up and enforce application is running/restarted

Просто потрясающе :-(

Pinkbyte ★★★★★
() автор топика
Последнее исправление: Pinkbyte (всего исправлений: 1)
Ответ на: комментарий от pekmop1024

На проблемном сервере у меня Alpine 3.21 и Docker 27, попробую воспроизвести на AlmaLinux конечно

P.S. О, Alpine 3.22 вышел, но обновляться я пожалуй пока всё же повременю, а то уже был опыт когда Swarm я обновил, а Portainer оказался к этому не совсем готов, в результате просмотр логов из Portainer отсох пока там не допилили поддержку Docker 26

Pinkbyte ★★★★★
() автор топика
Ответ на: комментарий от pekmop1024

У меня Alpine, тут OpenRC и этой вашей параллельной загрузки нет(точнее ее можно включить, но для сервера где 3,5 службы, одна из которых Docker и весь кипиш уже внутри него, это нафиг не надо), модули грузятся в boot runlevel, а docker - в default. Это - четкая гарантия последовательности запуска.

Pinkbyte ★★★★★
() автор топика
Последнее исправление: Pinkbyte (всего исправлений: 1)
Ответ на: комментарий от Pinkbyte

А оно точно подгружается в boot runlevel? Вообще, конечно, альпинисты это все не для железа пилили, зря ты так)

pekmop1024 ★★★★★
()
Последнее исправление: pekmop1024 (всего исправлений: 1)
Ответ на: комментарий от pekmop1024

Точно-точно:

May 30 21:18:22 docker daemon.info init: starting pid 2654, tty '': '/sbin/openrc default'
May 30 21:18:23 docker daemon.info chronyd[2759]: chronyd version 4.5 starting (+CMDMON +NTP +REFCLOCK +RTC +PRIVDROP +SCFILTER +SIGND +ASYNCDNS +NTS +SECHASH +IPV6 -DEBUG)
May 30 21:18:23 docker daemon.info chronyd[2759]: Frequency -25.395 +/- 18.180 ppm read from /var/lib/chrony/chrony.drift
May 30 21:18:27 docker daemon.info chronyd[2759]: System's initial offset : 0.892628 seconds slow of true (slew)
May 30 21:18:29 docker cron.info crond[2786]: crond (busybox 1.36.1) started, log level 8
May 30 21:18:29 docker daemon.info supervise-daemon[2843]: Supervisor command line: supervise-daemon docker --start --retry TERM/60/KILL/10 --stdout-logger log_proxy -m /var/log/docker.log --stderr-logger log_proxy -m /var/log/docker.log --respawn-delay 2 --respawn-max 5 --respawn-period 1800 /usr/bin/dockerd --
May 30 21:18:29 docker daemon.info supervise-daemon[2845]: Child command line: /usr/bin/dockerd

docker [~]# stat /proc
  File: /proc
  Size: 0               Blocks: 0          IO Block: 1024   directory
Device: 14h/20d Inode: 1           Links: 390
Access: (0555/dr-xr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2025-05-30 21:18:13.720000000 +0300
Modify: 2025-05-30 21:18:13.720000000 +0300
Change: 2025-05-30 21:18:13.720000000 +0300

docker [~]# grep tun /var/log/dmesg
[    7.035020] tun: Universal TUN/TAP device driver, 1.6

21:18:13 - старт системы
7 секунд после - загрузка модуля tun
21:18:22 - старт syslog
21:18:29 - старт docker

И это как раз лог когда контейнер не стартанул

Pinkbyte ★★★★★
() автор топика
Последнее исправление: Pinkbyte (всего исправлений: 1)
Ответ на: комментарий от pekmop1024

Вообще, конечно, альпинисты это все не для железа пилили, зря ты так)

Какое железо - это виртуалка на Proxmox-е :-)

Pinkbyte ★★★★★
() автор топика
Последнее исправление: Pinkbyte (всего исправлений: 1)
Ответ на: комментарий от Pinkbyte

healthcheck-и есть, зависимости прописаны, они не помогают

В топике нет одного healthcheck

Проблемный контейнер - всегда тот где прописан network_mode

А зачем какой-то network_mode, если docker compose по определению запускает сервисы из одного docker-compose.yml в одной сети?

router ★★★★★
()

Кстати, а как настроен запуск через compose? Насколько я помню, сам он ничего не умеет, и это делается через написание systemd unit’а. А если он есть, то пора посмотреть логи этого unit’а

Если ты рассчитываешь, что дело обойдется голым docker, без юнита для запуска compose, то это вряд ли будет работать

router ★★★★★
()
Последнее исправление: router (всего исправлений: 1)
Ответ на: комментарий от router

А зачем какой-то network_mode, если docker compose по определению запускает сервисы из одного docker-compose.yml в одной сети?

В одной сети != у контейнеров будет 1 IP-адрес. Мне нужно именно последнее: в одном контейнере запущен сервис, в другом - VPN, через который нужно получить доступ к этому сервису

Да, можно вспотеть и пересобрать контейнер, вкорячить туда VPN и supervisord чтобы запускал сам сервис и VPN-клиента. И я так даже делал(не с VPN, просто объединял несколько сервисов в рамках одного контейнера). И это работает. Просто выглядит ИМХО не очень :-(

Pinkbyte ★★★★★
() автор топика
Последнее исправление: Pinkbyte (всего исправлений: 2)
Ответ на: комментарий от router

Насколько я помню, сам он ничего не умеет, и это делается через написание systemd unit’а

Ты путаешь с podman - вот там да, там ВСЁ через systemd.

Если ты рассчитываешь, что дело обойдется голым docker, без юнита для запуска compose, то это вряд ли будет работать

У меня это всё запускает Portainer. И это ПРЕКРАСНО работает уже не первый год, просто вот для такой конфигурации - это не работает, и как я уже давал ссылку выше - это видимо не собираются чинить.

Pinkbyte ★★★★★
() автор топика
Последнее исправление: Pinkbyte (всего исправлений: 2)
Ответ на: комментарий от router

Для справки - контейнеры созданные через из консоли через docker-compose на Alpine не создают ни дополнительных init-скриптов, ни systemd-юнитов. Но при этом - вполне себе перезапускаются при ребуте(или рестарте dockerd), правда, как выяснилось, без соблюдения порядка запуска.

Так что да, подход того же podman выглядит честнее - не следить за запуском контейнеров самому, а просто переложить это на systemd

Pinkbyte ★★★★★
() автор топика
Ответ на: комментарий от Pinkbyte

У меня это всё запускает Portainer. И это ПРЕКРАСНО работает уже не первый год, просто вот для такой конфигурации - это не работает, и как я уже давал ссылку выше - это видимо не собираются чинить

Better configure a systemd service to execute docker compose up and enforce application is running/restarted

Ну.. А я о чём? ;)

router ★★★★★
()
Ответ на: комментарий от Pinkbyte

правда, как выяснилось, без соблюдения порядка запуска.

Именно

Скорее всего, тебе их запускает docker или твой portainer. А все healthcheck и зависимости идут лесом

Если ты хочешь, чтобы compose запускался при старте хоста, тебе нужно писать .service файл

router ★★★★★
()
Ответ на: комментарий от Pinkbyte

Не надо в кроне. Напиши простейший service

Который будет при shutdown останавливать твой docker-compose.yml, а при загрузке запускать. Это прям основы docker compose

router ★★★★★
()
Ответ на: комментарий от router

Если ты хочешь, чтобы compose запускался при старте хоста, тебе нужно писать .service файл

Фишка в том, что .yml-файлы находятся в sqlite-базе Portainer, а не напрямую в файловой системе. Я-то конечно могу написать скрипт чтоб их оттуда доставать и проходится по ним 'docker-compose up'. Но выглядит это как еще больший костыль, если честно.

Update: А хотя возможно и нет, возможно в базе только настройки Portainer, вроде какие-то yml файлы есть прямо в data directory самого Portainer. Обмозгую этот вариант, это чуть проще получается.

Pinkbyte ★★★★★
() автор топика
Последнее исправление: Pinkbyte (всего исправлений: 1)
Ответ на: комментарий от pekmop1024

дело говорит, depends_on не работает нихрена, так задумано. Я напилил враппер для энтрипоинта, чтобы эту проблему решить (у меня аппки ждут опенбао для того, чтобы секреты забрать).

Как это не работает? Всё работает, ни разу не видел, чтобы не работало.

Проблема может быть только в корректности написания хелсчека. А так, если хелсчек корректно определяет поднялся контейнер, или нет, то и depends_on всё поднимет в нужной последовательности. У меня это работает уже несколько лет, с кучей зависимостей, которые надо поднимать в определённой последовательности.

Chiffchaff
()