Оба смогут выполнять команды в контейнере. Оба могли отсоединить контейнер.
Так в чем же реальная разница между docker exec и docker attach?
Оба смогут выполнять команды в контейнере. Оба могли отсоединить контейнер.
Так в чем же реальная разница между docker exec и docker attach?
Был commit PR, который добавил в документ:
Примечание. Эта команда (
attach
) не предназначена для запуска нового процесса в контейнере. См.:docker exec
.
Ответ на вопрос «Docker. Как получить bash\ssh внутри запущенного контейнера (run -d
)?" иллюстрирует разницу:
(docker >= 1.3) Если мы используем
docker attach
, мы можем использовать только один экземпляр оболочки.
Поэтому, если мы хотим открыть новый терминал с новым экземпляром оболочки контейнера, нам просто нужно запуститьdocker exec
если контейнер docker был запущен с помощью команды
/bin/bash
, вы можете получить к нему доступ, используя присоединение, если нет, вам нужно выполнить команду для создания экземпляра 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 ‹ container-id > перенесет вас внутрь терминала bash, так как его PID 1, как мы упоминали при запуске контейнера. Выход из контейнера остановит контейнер.
В то время как в команде docker exec вы можете указать, в какую оболочку вы хотите войти. Это не приведет вас к PID 1 контейнера. Это создаст новый процесс для bash. docker exec -it ‹ идентификатор-контейнера > bash. Выход из контейнера не остановит контейнер.
Вы также можете использовать nsenter для входа внутрь контейнеров. nsenter -m -u -n -p -i -t ‹ PID контейнера > Вы можете найти PID контейнера, используя: docker inspect ‹ container-id > | grep PID
Примечание. Если вы запустили свой контейнер с флагом -d, то выход из контейнера не остановит контейнер, независимо от того, используете ли вы присоединение или exec для входа внутрь.
nsenter
. Можете ли вы уточнить? Объяснение вариантов было бы в порядке. Почему бы не ввести все пространства имен? Почему именно эти?
- person x-yuri; 29.06.2019
Как заявил Майкл Сан в своем ответе
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…», основной процесс будет иметь псевдотерминал, а STDIN останется открытым. При подключении в режиме tty вы можете отсоединиться от контейнера (и оставить его работающим) с помощью настраиваемой последовательности клавиш. Последовательность по умолчанию — CTRL-p CTRL-q. Вы настраиваете последовательность клавиш, используя параметр --detach-keys или файл конфигурации. Вы можете повторно подключиться к отдельному контейнеру с помощью подключения докера.
Docker exec просто запускает новый процесс внутри среды контейнера, то есть принадлежит пространству PID контейнера.
Например, если вы запускаете свой контейнер с помощью «docker run –dit XXX /bin/bash», вы можете подключиться к контейнеру (основной процесс) с помощью двух разных терминалов. Пока вы вводите данные в один терминал, вы можете видеть, что он появляется в другом терминале, поскольку оба терминала подключены к одному и тому же tty. Будьте осторожны, сейчас вы находитесь в основном процессе контейнера, если вы наберете «exit», вы выйдете из контейнера (так что будьте осторожны, используйте клавиши отсоединения для отсоединения), и вы увидите оба терминала вышли. Но если вы запустите «docker exec –it XXX /bin/bash» в двух терминалах, то у вас внутри контейнера запустились два новых процесса, причем они не связаны друг с другом и с основным процессом, и вы можете спокойно выйти из них .