Оба могут выполнять команды в контейнере. Оба могут отсоединить контейнер.
Итак, какова реальная разница между приложением docker exec и docker?
Оба могут выполнять команды в контейнере. Оба могут отсоединить контейнер.
Итак, какова реальная разница между приложением docker exec и docker?
Был коммит PR, который добавил в документ:
Примечание. Эта команда (
attach
) не предназначена для запуска нового процесса в контейнере. Смотрите:docker exec
.
Ответ на "Docker. Как получить bash\ssh внутри запущенного контейнера (run -d
)?" иллюстрирует разницу:
(docker> = 1.3) Если мы используем
docker attach
, мы можем использовать только один экземпляр оболочки.
Поэтому, если мы хотим открыть новый терминал с новым экземпляром оболочки контейнера, нам просто нужно запуститьdocker exec
Если контейнер Docker был запущен с помощью команды
/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 < container-id > приведет вас внутрь терминала bash, как и PID 1, как мы упоминали при запуске контейнера. Выход из контейнера остановит контейнер.
В то время как в команде docker exec вы можете указать, в какую оболочку вы хотите ввести. Это не приведет вас к PID 1 контейнера. Он создаст новый процесс для bash. docker exec -it < container-id > bash. Выход из контейнера не остановит контейнер.
Вы также можете использовать nsenter для ввода внутри контейнеров. nsenter -m -u -n -p -i -t < pid контейнерa > Вы можете найти PID контейнера, используя: docker inspect < container-id > | grep PID
Примечание.. Если вы запустили свой контейнер с флагом -d, то выход из контейнера не остановит контейнер, если вы используете attach или exec для входа внутрь.
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", вы можете подключиться к контейнеру (основной процесс) с помощью двух разных терминалов. Когда вы вводите данные на одном терминале, вы можете видеть, что он появляется на другом терминале, поскольку оба терминала подключены к одному и тому же терминалу. Будьте осторожны, что вы сейчас находитесь в основном процессе контейнера, если вы наберете "выход", вы выйдете из контейнера (поэтому будьте осторожны, используя detach-ключи для отсоединения), и вы увидите, что оба терминала вышли. Но если вы запускаете "docker exec –it XXX/bin/bash" в двух терминалах, вы запускаете два новых процесса внутри контейнера, и они не связаны друг с другом и с основным процессом, и вы можете безопасно выйти из них,
Как заявил Майкл Сан в своем ответе
docker exec
выполняет новую команду/создает новый процесс в среде контейнеров, в то время какdocker attach
просто соединяет стандартный ввод/вывод/ошибку основного процесса (с PID 1) внутри контейнера с соответствующим стандартным вводом/выводом/ошибкой тока терминал (терминал, который вы используете для запуска команды).
Мой ответ будет сосредоточен на том, чтобы позволить вам подтвердить приведенное выше утверждение и понять его более четко.
Откройте окно терминала и запустите командную docker run -itd --name busybox busybox/bin/sh
. Команда busybox
изображение busybox
если его еще нет. Затем он создаст контейнер с именем busybox
используя это изображение.
Вы можете проверить состояние вашего контейнера, запустив команду docker ps -a | grep 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
просто соединяет стандартный ввод/вывод/ошибку основного процесса внутри контейнера с соответствующим стандартным вводом/выход/ошибка текущего терминала.