Поясніть різницю між docker exec і docker attach.
docker exec і docker attach обидва способи взаємодії з running-container, але підключають до різних речей. Нерозуміння, що є що, веде до класу багів, де ти випадково вбиваєш прод, натиснувши Ctrl+C у неправильному вікні.
Теорія
TL;DR
docker exec= новий процес всередині container. Існуючий PID 1 container продовжує крутитися незалежно.docker attach= підключення до stdio PID 1. Бачиш, що PID 1 бачить (його stdin/stdout/stderr).- Вбивство твого
exec-shell: лише твій shell виходить. Container лишається running. - Вбивство/Ctrl+C твоєї
attach-сесії: PID 1 отримує SIGINT. Container, скоріш за все, зупиниться. - Detach з attach без вбивства: Ctrl+P, потім Ctrl+Q (має бути
-it-режим). - 99% часу хочеш
exec.attachрідко.
Що робить docker exec
$ docker run -d --name web nginx
$ docker exec -it web sh
/ # ps aux
USER PID COMMAND
root 1 nginx: master process
nginx 29 nginx: worker process
root 45 sh # ← мій shell, окремий процес
root 51 ps aux
/ # exit
# Container ще running.Shell це процес 45 всередині container. Крутиться поряд з nginx (PID 1 і 29). Вийди з shell → процес 45 завершується, nginx не зачеплено, container ще running.
Що робить docker attach
$ docker run -d --name web nginx
$ docker attach web
# (тиша, stdio nginx, без поточного output)
# Натисни Ctrl+C
# nginx отримує SIGINT → виходить → container зупиняєтьсяТи підключений до stdio nginx. Усе, що nginx друкує, ти бачиш. Усе, що набираєш, nginx отримує на stdin. Ctrl+C шле SIGINT на nginx. nginx виходить. Container завершується.
Для debug це майже ніколи не те, що хочеш.
Side-by-side
docker exec | docker attach | |
|---|---|---|
| Створює процес | так (новий) | ні (підключення до PID 1) |
| Вбиває container на Ctrl+C | ні | так (шле SIGINT на PID 1) |
| Ctrl+P, Ctrl+Q для безпечного detach | n/a | так |
| Бери для | debug, inspect, ad-hoc команд | REPL як PID 1, console-app |
| Поширена помилка | майже жодної | випадкове вбивство проду |
Detach з attach
Escape-послідовність, щоб вийти з attach без вбивства PID 1:
Ctrl+P, Ctrl+Q
Має бути у -it-режимі (interactive + TTY). Без -t немає terminal-послідовності для інтерпретації; без -i stdin закритий. Без escape-послідовності твої лише опції це Ctrl+C (вбиває container) або kill docker-процесу ззовні.
У shell, що override Ctrl+P (деякі tmux-конфіги), можливо, треба перемапити перед attach.
Коли attach реально корисний
REPL як PID 1
docker run -d --name nodejs node:22 node
# nodejs running як PID 1, REPL чекає input
docker attach nodejs
> 1+1
2
> .exit
# Ctrl+P, Ctrl+Q для detach натомістьPython або Node REPL, запущений як PID 1, приймає input лише через attach. exec породив би новий shell, що не те, що хочеш.
Console-based застосунки
Застосунки, що взаємодіють через stdio як свій primary-інтерфейс (chess-сервери, console-ігри, певні admin-tools), потребують attach.
Watching live PID 1 output
docker attach web
# nginx access-лог стрімить у реальному часіХоча docker logs -f web зазвичай кращий вибір, той самий ефект, без ризику вбивства.
Типові помилки
Бери attach, коли хотів exec
# НЕПРАВИЛЬНО
docker attach web # підключається до stdio nginx
# Натисни Ctrl+C → вбиває nginx → container зупиняється → outage
# ПРАВИЛЬНО
docker exec -it web sh # новий shell
# Натисни Ctrl+D (або exit) → shell завершується → container не зачепленоНайпоширеніша attach-помилка це сприймати його як exec. Та сама інтуїція («підключитися до running-container»), дуже різні наслідки.
Забути -it з attach
docker attach --no-stdin web # вимикає stdin
# більше не можна Ctrl+P, Ctrl+Q для detach (без TTY)
# тільки Ctrl+C, що вбиваєЯкщо мусиш attach без TTY, прийми, що Ctrl+C твій єдиний вихід. Краще: просто не роби.
Використовувати --sig-proxy=false у attach без розуміння
docker attach --sig-proxy=false web
# Ctrl+C тепер НЕ propagate на PID 1, container виживаєОбхід для безпечнішого attach. Але якщо тобі це треба, ти, скоріш за все, хотів exec.
Спроба attach на stopped-container
$ docker attach stopped-web
Error: container is not runningAttach потребує running. Бери docker start -ai stopped-web, щоб оживити exited-container з прикріпленим stdio (інше, але пов'язане).
Реальне застосування
execдля 99% debug: shell у running-container, one-off команда, inspect файли, check env. Безпечно і стандартно.attachконкретно для: взаємодії з REPL як PID 1 (рідко), console-app, де stdio це API (рідко), watching live-output безdocker logs(рідко; logs зазвичай краще).- Ніколи
attachна прод-веб-сервер, який не хочеш вбити. Бериdocker logs -f.
Питання для поглиблення
Q: Чому Ctrl+C вбиває container з attach, але не з exec?
A: З attach ти підключений до stdio PID 1. Ctrl+C шле SIGINT на PID 1 (головний процес). PID 1 виходить, container виходить. З exec твій shell це окремий процес; Ctrl+C вбиває shell, не PID 1.
Q: Чи можуть кілька user attach до того самого container?
A: Так, усі бачать output PID 1 і ділять stdin. Працює як screen-сесія. Корисно для collaborative-debug; ризиково, бо хтось може випадково Ctrl+C.
Q: Яка різниця між docker attach і docker exec -it container bash?
A: Attach підключається до stdio існуючого PID 1. Exec створює новий bash-процес всередині container. Новий bash незалежний; PID 1 shared.
Q: Що дає docker run -d потім docker attach vs docker run (без -d)?
A: Той самий результат (бачиш output PID 1). Комбо -d + attach корисне, коли хочеш стартувати detached, зробити інші речі, тоді attach пізніше. docker run без -d це attach-by-default.
Q: (Senior) Коли б ти написав custom-container, що потребує docker attach понад docker exec?
A: Коли мета container Є взаємодія через stdio як primary-інтерфейс, як кастомний REPL, інтерактивний admin-tool, що user запускає періодично, а не як daemon, або game-сервер з admin-консоллю. Навіть тоді сучасні дизайни віддають перевагу HTTP або gRPC API над stdio-attachment заради usability і multi-user-підтримки. Pure-stdio інтерфейси все рідше; якщо тягнешся за attach, спитай, чи твій дизайн часом не релікт.
Приклади
Безпечний debug з exec
# Прод-веб-сервер. Інспектуй БЕЗ ризику outage.
docker exec -it web sh
/ # cat /etc/nginx/nginx.conf
/ # netstat -tlnp
/ # ps aux
/ # exit
# nginx ніколи не помітив; uptime збережено.Ризикований live-tail з attach
# НЕ роби це у проді
docker attach prod-web
# Стрімить live access-логи.
# Випадковий Ctrl+C → SIGINT → nginx виходить → 502 для юзерів.
# Краще:
docker logs -f prod-web # той самий output, безпечноDetach демо
$ docker run -d --name pyrepl python:3.13 python
# Python REPL чекає у фоні як PID 1
$ docker attach pyrepl
>>> 2 + 2
4
>>> # Тепер натисни Ctrl+P, потім Ctrl+Q
read escape sequence
$ docker ps --filter name=pyrepl
STATUS NAMES
Up 2 minutes pyrepl # ще runningDetach безпечно; container тримає REPL живим; можна re-attach пізніше.
Коли attach реально потрібен
# Кастомний container, спроектований як інтерактивний tool
docker run -d --name console myorg/admin-console:1.0
docker attach console
admin> help
admin> reset --user 42
admin> exit
# Кастомна 'exit' команда каже застосунку завершитися.Якщо дизайн застосунку «говори зі мною через stdio», attach це єдиний шлях. Але цей дизайн нечастий.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.
Коментарі
Ще немає коментарів