Разница между Docker Attach и Docker Exec
Оба смогут выполнять команды в контейнере. Оба могут отсоединить контейнер.
Так в чем же разница между docker exec и docker attach?
3 ответа
Был коммит PR, который добавил в документ:
Примечание: эта команда (
attach
) не для запуска нового процесса в контейнере. Увидеть:docker exec
,
Ответ на " Докер. Как получить bash\ssh внутри запущенного контейнера ( run -d
)? "иллюстрирует разницу:
(docker> = 1.3) Если мы используем
docker attach
Мы можем использовать только один экземпляр оболочки.
Поэтому, если мы хотим открыть новый терминал с новым экземпляром оболочки контейнера, нам просто нужно запуститьdocker exec
если докер контейнер был запущен с помощью
/bin/bash
команда, вы можете получить к нему доступ с помощью attach, если нет, то вам нужно выполнить команду для создания экземпляра bash внутри контейнера, используяexec
,
Как уже упоминалось в этом выпуске:
- Присоединение не для запуска дополнительной вещи в контейнере, это для присоединения к запущенному процессу.
- "
docker exec
"специально для запуска новых вещей в уже запущенном контейнере, будь то оболочка или какой-то другой процесс.
Та же проблема добавляет:
В то время как
attach
не очень хорошо назван, особенно из-за команды LXClxc-attach
(что более похожеdocker exec <container> /bin/sh
(но только для LXC), у него есть определенная цель - буквально присоединить вас к процессу, запущенному Docker.
В зависимости от процесса поведение может отличаться, например,/bin/bash
даст вам оболочку, но подключение к redis-серверу будет таким же, как если бы вы только что начали redis напрямую, без демонизации.
Когда контейнер запускается с использованием /bin/bash, он становится PID 1 контейнера, и присоединение к докеру используется для входа в PID 1 контейнера. Таким образом, docker attach
В то время как в команде docker exec вы можете указать, в какую оболочку вы хотите войти. Это не приведет вас к PID 1 контейнера. Это создаст новый процесс для bash.docker exec -it <идентификатор контейнера> bash. Выход из контейнера не остановит контейнер.
Вы также можете использовать nsenter для входа в контейнеры.nsenter -m -u -n -p -i -t
Примечание: Если вы запустили свой контейнер с флагом -d, то выход из контейнера не остановит контейнер, используете ли вы attach или exec для входа внутрь.
Как заявил Майкл Сан в своем ответе
docker exec
выполняет новую команду / создает новый процесс в среде контейнера, аdocker attach
просто подключает стандартный ввод / вывод / ошибку основного процесса (с PID 1) внутри контейнера с соответствующим стандартным вводом / выводом / ошибкой текущего терминала (терминал, который вы используете для запуска команды).
Мой ответ будет больше сосредоточен на том, чтобы позволить вам подтвердить приведенное выше утверждение и понять его более четко.
Откройте окно терминала и запустите команду docker run -itd --name busybox busybox /bin/sh
. Команда вытянет изображениеbusybox
если еще не присутствует. Затем он создаст контейнер с именемbusybox
используя это изображение.
Вы можете проверить статус вашего контейнера, выполнив команду docker ps -a | grep busybox
.
Если ты бежишь docker top busybox
, вы должны увидеть что-то вроде этого.
UID PID PPID C STIME TTY TIME CMD
root 7469 7451 0 11:40 pts/0 00:00:00 /bin/sh
Конечно, PID
, PPID
и другие значения будут другими в вашем случае. Вы можете использовать другие инструменты и утилиты, напримерpstree
, top
, htop
чтобы увидеть список PID
а также PPID
.
В PID
а также PPID
означает идентификатор процесса и идентификатор родительского процесса. Процесс начался, когда мы создали и запустили наш контейнер с помощью команды/bin/sh
. Теперь запустите командуdocker attach busybox
. Это подключит стандартный поток ввода / вывода / ошибок контейнера к вашему терминалу.
После присоединения контейнера создайте сеанс оболочки, выполнив команду sh
. НажмитеCTRL-p CTRL-q
последовательность. Это отсоединит терминал от контейнера и продолжит работу контейнера. Если ты сейчас побежишьdocker top busybox
, вы должны увидеть в списке два процесса.
UID PID PPID C STIME TTY TIME CMD
root 7469 7451 0 11:40 pts/0 00:00:00 /bin/sh
root 7737 7469 0 11:43 pts/0 00:00:00 sh
Но PPID
из двух процессов будет отличаться. Фактически,PPID
второго процесса будет таким же, как PID
первого. Первый процесс действует как родительский процесс для только что созданного сеанса оболочки.
Теперь беги docker exec -it busybox sh
. Оказавшись внутри контейнера, проверьте список запущенных процессов для контейнера.busybox
в другом окне терминала, выполнив команду docker top busybox
. Вы должны увидеть что-то вроде этого
UID PID PPID C STIME TTY TIME CMD
root 7469 7451 0 11:40 pts/0 00:00:00 /bin/sh
root 7737 7469 0 11:43 pts/0 00:00:00 sh
root 7880 7451 0 11:45 pts/1 00:00:00 sh
В PPID
первого и третьего процесса будут одинаковыми, что подтверждает, что docker exec
создает новый процесс в среде контейнера, пока docker attach
просто соединяет стандартный ввод / вывод / ошибку основного процесса внутри контейнера с соответствующим стандартным вводом / выводом / ошибкой текущего терминала.
Docker exec выполняет новую команду / создает новый процесс в среде контейнера, в то время как Docker attach просто соединяет стандартный ввод / вывод / ошибку основного процесса (с PID 1) внутри контейнера с соответствующим стандартным вводом / выводом / ошибкой тока терминал (терминал, который вы используете для запуска команды).
Контейнер - это изолированная среда, в которой выполняются некоторые процессы. В частности, контейнер имеет свое собственное пространство файловой системы и пространство PID, которые изолированы от хоста и других контейнеров. Когда контейнер запускается с использованием "docker run –it …", основной процесс будет иметь псевдо-tty, а STDIN останется открытым. При подключении в режиме tty вы можете отсоединиться от контейнера (и оставить его работающим), используя настраиваемую последовательность клавиш. Последовательность по умолчанию - CTRL-p CTRL-q. Вы конфигурируете последовательность клавиш, используя опцию --detach-keys или файл конфигурации. Вы можете присоединить к отдельному контейнеру с присоединением докера.
Docker exec просто запускает новый процесс внутри среды контейнера, то есть принадлежит к PID-пространству контейнера.
Например, если вы запускаете свой контейнер с помощью "docker run –dit XXX /bin/bash", вы можете подключиться к контейнеру (основной процесс) с помощью двух разных терминалов. Когда вы вводите данные на одном терминале, вы можете видеть, что он появляется на другом терминале, поскольку оба терминала подключены к одному и тому же терминалу. Будьте осторожны, теперь вы находитесь в основном процессе контейнера, если вы наберете "exit", вы выйдете из контейнера (поэтому будьте осторожны, используя отсоединяемые ключи), и вы увидите, что оба терминала вышли. Но если вы запускаете "docker exec –it XXX /bin/bash" в двух терминалах, вы запускаете два новых процесса внутри контейнера, и они не связаны друг с другом и с основным процессом, и вы можете безопасно выйти из них,