Запуск команд в контейнере Docker

Docker — это утилита контейнеризации, которая позволяет разработчикам создавать и управлять портативными, согласованными контейнерами Linux.

При разработке или развертывании контейнеров часто возникает необходимость заглянуть в запущенный контейнер, чтобы проверить его текущее состояние или устранить проблему. Для этого в Docker есть команда docker exec.

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

Требования

В этом туториале предполагается, что у вас уже установлен Docker и у вашего пользователя есть разрешение на запуск команды docker. Если вам нужно запустить docker от пользователя root, не забудьте добавить sudo перед командой.

Читайте также: Установка и использование Docker в Ubuntu 20.04

Запуск тестового контейнера

Для работы с docker exec вам понадобится работающий контейнер. Если у вас еще нет его, запустите тестовый с помощью следующей команды docker run:

docker run -d --name container-name alpine watch "date >> /var/log/date.log"

Эта команда создаст новый контейнер Docker из официального образа alpine. Это популярный образ контейнера Linux, который использует Alpine Linux — легкий, минимальный дистрибутив Linux.

С помощью флага -d отсоединим контейнер от терминала и запустим его в фоновом режиме. –name container-name присвоит контейнеру название container-name. Вы можете выбрать любое имя или вообще не указывать его, чтобы Docker автоматически сгенерировал уникальное название для нового контейнера.

Далее у нас есть alpine, который указывает на образ, с помощью которого мы создаем контейнер.

watch “date >> /var/log/date.log” — это команда, которую мы хотим выполнить в контейнере. watch будет повторять команду, которую вы укажете, каждые две секунды по умолчанию. В данном случае будет запущена команда watch: date >> /var/log/date.log. Команда date выводит текущую дату и время, например:

OutputFri Jul 23 14:57:05 UTC 2021

Часть команды >> /var/log/date.log перенаправляет вывод из date и добавляет его в файл /var/log/date.log. Каждые две секунды в файл будет добавляться новая строка, и через несколько секунд он будет выглядеть примерно так:

Fri Jul 23 15:00:26 UTC 2021
Fri Jul 23 15:00:28 UTC 2021
Fri Jul 23 15:00:30 UTC 2021
Fri Jul 23 15:00:32 UTC 2021
Fri Jul 23 15:00:34 UTC 2021

На следующем этапе мы рассмотрим, как узнать имена контейнеров Docker. Это поможет, если у вас уже есть контейнер, с которым вы хотите работать, но вы не знаете, как он называется.

Поиск имени контейнера Docker

Как правило, нам нужно сообщить docker exec название (или ID) контейнера, с которым мы хотим работать. Мы можем найти эту информацию с помощью команды docker ps:

docker ps

Эта команда выводит список всех контейнеров Docker, которые запущены на сервере, и предоставляет высокоуровневую информацию о них:

CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS  NAMES
76aded7112d4   alpine    "watch 'date >> /var…"   11 seconds ago   Up 10 seconds             container-name

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

Переименовать контейнер можно с помощью команды docker rename:

docker rename container-name new-name

Далее мы рассмотрим несколько примеров использования docker exec для выполнения команд в запущенном контейнере Docker.

Запуск интерактивной оболочки в контейнере Docker

Запустить интерактивную оболочку в контейнере Docker (возможно, для изучения файловой системы или отладки запущенных процессов) можно с помощью docker exec с флагами -i и -t.

Флаг -i открывает ввод для контейнера, а -t создает псевдо-терминал, к которому может подключиться оболочка. Эти флаги можно комбинировать следующим образом:

docker exec -it container-name sh

Команда запустит базовую оболочку sh в указанном контейнере. Для выхода из контейнера введите exit и нажмите ENTER:

exit

Если образ контейнера включает более продвинутую оболочку, например bash, вы можете заменить sh на bash.

Запуск неинтерактивной команды в контейнере Docker

Если вам нужно выполнить неинтерактивную команду в работающем контейнере Docker, запустите docker exec без флагов:

docker exec container-name tail /var/log/date.log

Эта команда выполнит tail /var/log/date.log в контейнере container-name и выведет результаты. По умолчанию команда tail выводит последние десять строк файла. Если вы запускаете демо-контейнер, который мы установили на первом этапе, то вывод будет примерно следующим:

Mon Jul 26 14:39:33 UTC 2021
Mon Jul 26 14:39:35 UTC 2021
Mon Jul 26 14:39:37 UTC 2021
Mon Jul 26 14:39:39 UTC 2021
Mon Jul 26 14:39:41 UTC 2021
Mon Jul 26 14:39:43 UTC 2021
Mon Jul 26 14:39:45 UTC 2021
Mon Jul 26 14:39:47 UTC 2021
Mon Jul 26 14:39:49 UTC 2021
Mon Jul 26 14:39:51 UTC 2021

По сути, это то же самое, что и запуск интерактивной оболочки для контейнера Docker (как это было сделано на предыдущем этапе с помощью docker exec -it container-name sh) и выполнение команды tail /var/log/date.log. Но вместо того чтобы открывать оболочку, выполнять команду и затем закрывать ее, эта команда возвращает тот же вывод,не запуская псевдо-терминал.

Выполнение команд в альтернативном каталоге

Запустить команду в определенном каталоге контейнера можно с помощью флага –workdir:

docker exec --workdir /tmp container-name pwd

В этом примере команда устанавливает каталог /tmp в качестве рабочего, а затем запускает pwd, которая выводит текущий рабочий каталог:

/tmp

Команда pwd подтверждает, что рабочий каталог — /tmp.

Выполнение команд от имени другого пользователя 

Добавьте флаг –user, чтобы запустить команду от имени другого пользователя внутри контейнера:

docker exec --user guest container-name whoami

Для выполнения команды whoami в контейнере будет использоваться пользователь guest. Команда whoami выводит имя текущего пользователя:

guest

whoami подтверждает, что текущий пользователь контейнера — guest.

Передача переменных окружения

Иногда вместе с выполняемой командой в контейнер нужно передать переменные окружения. Флаг -e позволяет указать переменную окружения:

docker exec -e TEST=8host container-name env

Эта команда устанавливает для переменной окружения TEST значение 8host, а затем запускает команду env в контейнере. Потом env выводит все переменные окружения:

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=76aded7112d4
TEST=8host
HOME=/root

Для переменной TEST устанавливается значение 8host.

Чтобы установить несколько переменных, повторите флаг -e для каждой:

docker exec -e TEST=8host -e ENVIRONMENT=prod container-name env

Если вы хотите передать файл со значениями переменных окружения, вы можете сделать это с помощью флага –env-file.

Сначала создайте файл с помощью текстового редактора. Мы откроем новый файл через nano, но вы можете использовать любой другой редактор:

nano .env

Назовем файл .env, так как это популярный стандарт для использования файлов такого типа (для управления информацией вне системы контроля версий).

Запишите переменные KEY=value в файл, по одной в строке:

TEST=8host
ENVIRONMENT=prod

Сохраните и закройте файл. В nano для этого нажмите CTRL+O, ENTER и CTRL+X.

Теперь запустите команду docker exec, указав правильное имя файла после –env-file:

docker exec --env-file .env container-name env

Вывод будет таким:

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=76aded7112d4
TEST=8host
ENVIRONMENT=prod
HOME=/root

Теперь в файле установлены две переменные.

Вы можете указать больше файлов с помощью нескольких флагов –env-file. Если переменные в файлах пересекаются, то файл, который был указан последним в команде, перезапишет предыдущие.

Частые ошибки

При работе с командой docker exec вы можете столкнуться с такими ошибками:

Error: No such container: container-name

Ошибка No such container означает, что указанный контейнер не существует, а также может указывать на неправильное написание имени контейнера. Выполните docker ps, чтобы вывести список запущенных контейнеров и проверить его название.

Error response from daemon: Container 2a94aae70ea5dc92a12e30b13d0613dd6ca5919174d73e62e29cb0f79db6e4ab is not running

Сообщение not running означает, что контейнер существует, но он остановлен. Вы можете запустить контейнер с помощью docker start container-name.

Error response from daemon: Container container-name is paused, unpause the container before exec

Ошибка Container is paused достаточно понятно объясняет проблему. Нужно разблокировать контейнер с помощью docker unpause container-name, прежде чем приступать к дальнейшей работе.

Заключение

В этом мануале мы рассмотрели выполнение команд в запущенном контейнере Docker, а также некоторые опции командной строки.

Tags:

Добавить комментарий