Repository navigation
fix(panel): hang up container terminal shells on close, keep Reload on the running build - #127
Merged
Merged
Conversation
…n the running build Closing a container terminal killed only the local `docker exec` client. The daemon keeps the exec terminal open, so the shell inside the container never got a hangup and kept running: one more idle shell per opened terminal, on local and remote servers alike. Every terminal session now carries a random DOKPLOY_TERMINAL_SESSION marker in its environment. When the terminal closes, the panel sends SIGHUP to the session's first process in the container; over SSH it does so before it ends the connection. The shell passes the hangup on to its jobs and a process started with nohup keeps running, as when an SSH session closes. Server -> Reload on the AgentHits channel ran the update command, so it pulled the newest `agenthits-dev` build. It now restarts the build the panel runs, pinned by digest (or image id for a locally built image), because swarm pulls a tag again whenever it starts a task. Update and Reload now log who started them: user, role, browser session or API key, address and user agent. Audit entries are stored only with an enterprise licence, so the panel log was the only place left for this. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
agentHits
added a commit
that referenced
this pull request
Oct 29, 2026
…ему тегу Команда Update записывала в сервис dokploy плавающий тег ghcr.io/agenthits/dokploy:agenthits-dev без digest. Swarm заново скачивает образ по тегу при каждом старте задачи, поэтому падение контейнера, healthcheck, перезагрузка сервера или рестарт Docker могли молча поднять более новую сборку. Теперь после docker pull скрипт читает RepoDigests скачанного образа, берёт digest того же репозитория и запускает docker service update --no-resolve-image --image <репозиторий>:<тег>@sha256:…. Swarm не скачивает образ по digest, если он уже есть на сервере, а если его нет, скачивает ровно эту сборку. Без digest этого репозитория в сервис пишется ID образа, как в Reload. Если после pull не нашёлся и сам образ, скрипт завершается с ошибкой и сервис не трогает. Официальный канал работает так же: в ту же команду попадают canary и feature, а это плавающие теги. Для тегов версий закрепление ничего не меняет. Маркер после pull, DOKPLOY_PREVIOUS_IMAGE, RELEASE_TAG, DOKPLOY_OFFICIAL_VERSION, DOKPLOY_FORK_VERSION, DOKPLOY_KEEP_OLD_IMAGES, stop-first и rollback остались прежними. Проверка обновлений уже брала digest из <образ>@sha256:…, и тест подтверждает, что после обновления панель не предлагает ту же сборку снова. Зависит от #127: ветка начата от fix/terminal-shell-and-reload. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
agentHits
added a commit
that referenced
this pull request
Oct 29, 2026
…ему тегу Команда Update записывала в сервис dokploy плавающий тег ghcr.io/agenthits/dokploy:agenthits-dev без digest. Swarm заново скачивает образ по тегу при каждом старте задачи, поэтому падение контейнера, healthcheck, перезагрузка сервера или рестарт Docker могли молча поднять более новую сборку. Теперь после docker pull скрипт читает RepoDigests скачанного образа, берёт digest того же репозитория и запускает docker service update --no-resolve-image --image <репозиторий>:<тег>@sha256:…. Swarm не скачивает образ по digest, если он уже есть на сервере, а если его нет, скачивает ровно эту сборку. Без digest этого репозитория в сервис пишется ID образа, как в Reload. Если после pull не нашёлся и сам образ, скрипт завершается с ошибкой и сервис не трогает. Официальный канал работает так же: в ту же команду попадают canary и feature, а это плавающие теги. Для тегов версий закрепление ничего не меняет. Маркер после pull, DOKPLOY_PREVIOUS_IMAGE, RELEASE_TAG, DOKPLOY_OFFICIAL_VERSION, DOKPLOY_FORK_VERSION, DOKPLOY_KEEP_OLD_IMAGES, stop-first и rollback остались прежними. Проверка обновлений уже брала digest из <образ>@sha256:…, и тест подтверждает, что после обновления панель не предлагает ту же сборку снова. Продолжает #127: там то же закрепление сделано для Server → Reload. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
agentHits
added a commit
that referenced
this pull request
Oct 29, 2026
…ему тегу (#128) Команда Update записывала в сервис dokploy плавающий тег ghcr.io/agenthits/dokploy:agenthits-dev без digest. Swarm заново скачивает образ по тегу при каждом старте задачи, поэтому падение контейнера, healthcheck, перезагрузка сервера или рестарт Docker могли молча поднять более новую сборку. Теперь после docker pull скрипт читает RepoDigests скачанного образа, берёт digest того же репозитория и запускает docker service update --no-resolve-image --image <репозиторий>:<тег>@sha256:…. Swarm не скачивает образ по digest, если он уже есть на сервере, а если его нет, скачивает ровно эту сборку. Без digest этого репозитория в сервис пишется ID образа, как в Reload. Если после pull не нашёлся и сам образ, скрипт завершается с ошибкой и сервис не трогает. Официальный канал работает так же: в ту же команду попадают canary и feature, а это плавающие теги. Для тегов версий закрепление ничего не меняет. Маркер после pull, DOKPLOY_PREVIOUS_IMAGE, RELEASE_TAG, DOKPLOY_OFFICIAL_VERSION, DOKPLOY_FORK_VERSION, DOKPLOY_KEEP_OLD_IMAGES, stop-first и rollback остались прежними. Проверка обновлений уже брала digest из <образ>@sha256:…, и тест подтверждает, что после обновления панель не предлагает ту же сборку снова. Продолжает #127: там то же закрепление сделано для Server → Reload. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Зачем
После закрытия терминала контейнера в контейнере продолжал работать его bash. Панель завершала только свою локальную команду
docker exec, а Docker держит терминал exec открытым, поэтому bash не получал сигнал отбоя. Каждое открытие терминала оставляло ещё один простаивающий процесс; на живой панели нашёлся bash, проработавший больше суток.Пункт Server → Reload на канале AgentHits не перезапускал панель, а запускал команду обновления и скачивал самую свежую сборку
agenthits-dev. Так панель могла незаметно перейти на сборку, которую ещё не выпускали.Кто запустил обновление или Reload, нигде не записывалось: журнал аудита хранится только с enterprise-лицензией.
Что изменилось
docker exec, bash в контейнере оставалсяDOKPLOY_TERMINAL_SESSION; при закрытии панель посылает SIGHUP первому процессу этой сессии в контейнере, через SSH до закрытия соединенияagenthits-devи обновить сервисОтбой получает только первый процесс сессии. Поэтому shell передаёт сигнал своим задачам, а процесс, запущенный через
nohup, продолжает работать, как при закрытии SSH-сессии. Busyboxshне передаёт отбой фоновым задачам; так же он ведёт себя и при обрыве SSH.Reload закрепляет образ по digest, потому что swarm заново скачивает образ по тегу при каждом запуске задачи. Для образа, указанного по digest или ID, повторной загрузки нет, если образ уже есть на хосте (
pullImageиDOCKER_SERVICE_PREFER_OFFLINE_IMAGEв исходниках moby). Официальный канал Dokploy не тронут.Пример строки в логе:
Проверки
docker exec, отбой при закрытии, порядок закрытия SSH, отказ каналаsh -n, без изменений после экранирования для SSHdocker: digest, ID образа, нет запущенной задачиdocker pull; без задачи панель не перезапускаетсяx-forwarded-forиx-real-ipsh) и debian (bash) тем же путём, что в панели (node-pty,docker exec -it)nohupпродолжает работатьapps/dokployvector-validate.test.tsповторяются на базе без этих правок (локальный Docker на Mac не видит временную папку теста), к PR не относятсяtscдляapps/dokployиpackages/server, biomeЧто проверить вручную на dev
sleep 1000 &, закрыть окно. Через пару секунд вdocker top <контейнер>не должно остаться ни bash, ниsleep 1000.docker service inspect dokploy --format '{{.Spec.TaskTemplate.ContainerSpec.Image}}'— показать образ с@sha256:.[panel] Reload requested by ….🤖 Generated with Claude Code