🐳 Сравнение команд Docker Exec и Docker Attach

В чем разница между exec и attach

by itisgood

1. Обзор

Docker – это популярная платформа для контейнеризации.

С помощью инструмента командной строки docker она предлагает различные подкоманды, которые значительно упрощают управление контейнерами в системе.

Среди этих подкоманд exec и attach – две команды, обычно используемые для взаимодействия с запущенным контейнером.

Несмотря на кажущуюся схожесть функциональности, команды docker exec и docker attach сильно отличаются друг от друга при взаимодействии с запущенным контейнером.

Чтобы понять эти различия, важно узнать, как эти две команды работают под капотом.

В этом руководстве мы узнаем, что делают команды docker attach и docker exec и в чем их различия.

2. Docker Exec

Команда docker exec выполняет любую произвольную команду в запущенном контейнере.

В частности, команда docker exec запускает заданную команду в рабочей директории контейнера по умолчанию под новым процессом.

Как правило, команда имеет следующее выражение:

docker exec [OPTIONS] CONTAINER COMMAND

Важно отметить, что COMMAND должна быть исполняемым файлом, а не цитируемым скриптом.

Это связано с тем, что движок Docker передает COMMAND системному вызову exec под капотом.

Например, распространенной ошибкой является передача однострочного скрипта оболочки в качестве COMMAND

$ docker exec ubuntu "echo hello && echo world"
OCI runtime exec failed: exec failed: unable to start container process: exec: "echo hello && echo world": executable file not found in $PATH: unknown

Проблема в том, что однострочный скрипт не является исполняемым файлом.

Чтобы запустить скрипт оболочки с помощью docker exec, мы должны указать исполняемый файл, sh, и передать скрипт в качестве аргументов команде sh.

Поэтому правильным способом запуска однострочного скрипта оболочки является префикс исполняемого файла sh -c:

$ docker exec ubuntu sh -c "echo hello && echo world"
hello
world

Кроме того, docker exec предлагает различные опции для использования с командой.

Важными являются опции -i и -t, которые позволяют держать открытым поток STDIN и выделять pseudo-tty для таких случаев, как запуск интерактивной оболочки в контейнере.

3. Docker Attach

Команда docker attach прикрепляет стандартные потоки ввода, вывода и ошибок текущего терминала к основному процессу запущенного контейнера.

С присоединенными потоками мы можем взаимодействовать с процессом внутри контейнера так, как если бы он был запущен на нашем терминале.

Прежде чем продолжить, давайте рассмотрим значение первичного процесса в контексте контейнера Docker.

3.1. Первичный процесс

Внутри работающего контейнера Docker будет запущен обычный процесс с PID, равным 1.

Этот процесс с PID, равным 1, называется первичным процессом.

Первичный процесс – это процесс, который запускается командой, указанной в ENTRYPOINT или CMD в образе Docker.

Когда мы выполняем команду docker attach на контейнере, команда прикрепляется к первичному процессу контейнера.

3.2. Команда

Команда docker attach принимает список опций и имя контейнера:

docker attach [OPTIONS] CONTAINER

Аргумент CONTAINER должен быть именем или идентификатором запущенного в данный момент контейнера Docker.

Кроме того, команда поддерживает такие опции, как -no-stdin, чтобы явно не подключать стандартный поток ввода.

Кроме того, мы можем предотвратить отправку сигналов процессу, указав опцию -sig-proxy false.

3.3. Демонстрация

Для демонстрации мы используем команду redis-cli, поскольку она представляет собой процесс, который слушает стандартный поток ввода и печатает в поток вывода.

Это позволяет нам продемонстрировать присоединение стандартного входного и выходного потоков.

Для начала мы запустим отдельный Docker-контейнер, используя Docker-образ redis.

Важно отметить, что нам нужно будет выполнить команду redis-cli, чтобы запустить его в качестве основного процесса нашего контейнера:

$ docker run -dit –name redis —rm redis redis-cli 2d3d508df8ad7b7e9c3864ae9733b1bd32e12f94330559f1ee6a4f753c299b9e

$ docker run -dit --name redis --rm redis redis-cli
2d3d508df8ad7b7e9c3864ae9733b1bd32e12f94330559f1ee6a4f753c299b9e

Очень важно, что мы указали опцию -it, чтобы сохранить входной поток контейнера открытым.

Кроме того, мы запускаем контейнер в отсоединенном режиме с помощью опции -d.

Затем мы можем присоединиться к процессу redis-cli с помощью команды docker attach:

$ docker attach redis
not connected>

Как и ожидалось, redis-cli не может подключиться к серверу Redis, потому что мы переписали стандартный CMD, запускающий сервер Redis.

Но это не повлияет на нашу демонстрацию, поскольку нас интересует только то, что поток ввода и вывода нашего терминала и основных процессов связаны.

Давайте выполним команду SET через стандартный поток ввода:

not connected> SET user bob
Could not connect to Redis at 127.0.0.1:6379: Connection refused
not connected>

Как мы видим, процесс redis-cli считывает команды, которые мы поместили в стандартный поток ввода, и действует соответствующим образом.

Кроме того, любой вывод или ошибки, которые процесс поместил в стандартные потоки вывода и ошибок, отображаются на нашем терминале благодаря вложению.

4. Разница между Docker Exec и Docker Attach

Основное различие между командами docker exec и docker attach заключается в том, что docker exec выполняет команду в новом процессе.

Обычно она используется для запуска интерактивной оболочки в работающем контейнере или для выполнения произвольных команд в среде контейнера.

С другой стороны, команда docker attach не запускает никакого нового процесса.

Она присоединяет стандартные потоки ввода и вывода текущего терминала к основному процессу запущенного контейнера.

Команда docker attach используется в основном тогда, когда мы хотим напрямую отправлять команды первичному процессу.

5. Заключение

В этом руководстве мы узнали, что команда docker exec и команда docker attach – это совершенно разные команды для взаимодействия с процессом в запущенном контейнере.

см. также:

 

You may also like

Leave a Comment