Поиск по сайту:

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


Введение

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

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

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

Развертывайте свои приложения Docker из GitHub с помощью платформы приложений DigitalOcean. Позвольте DigitalOcean сосредоточиться на масштабировании вашего приложения.

Предварительные условия

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

Дополнительную информацию об использовании Docker без доступа к sudo см. в разделе «Выполнение команды Docker без Sudo» нашего руководства Как установить Docker.

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

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

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

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

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

Далее у нас есть alpine, который определяет изображение, которое мы хотим использовать для контейнера.

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

Fri Jul 23 14:57:05 UTC 2021

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

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 имя (или идентификатор контейнера) контейнера, с которым мы хотим работать. Мы можем найти эту информацию с помощью команды 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

В этом примере выделены идентификатор и имя контейнера. Вы можете использовать любой из них, чтобы указать 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. Однако вместо того, чтобы открывать оболочку, запускать команду и затем закрывать оболочку, эта команда возвращает тот же вывод в одной команде, не открывая псевдотерминал.

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

Чтобы запустить команду в определенном каталоге вашего контейнера, используйте флаг --workdir, чтобы указать каталог:

docker exec --workdir /tmp container-name pwd

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

/tmp

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

Запуск команд от имени другого пользователя в контейнере Docker

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

docker exec --user guest container-name whoami

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

guest

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

Передача переменных среды в Docker-контейнер

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

docker exec -e TEST=sammy container-name env

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

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

Переменная TEST имеет значение sammy.

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

docker exec -e TEST=sammy -e ENVIRONMENT=prod container-name env

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

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

nano .env

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

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

TEST=sammy
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=sammy
ENVIRONMENT=prod
HOME=/root

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

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

Распространенные ошибки

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

Error: No such container: container-name

Ошибка Нет такого контейнера означает, что указанный контейнер не существует, и может указывать на неправильное написание имени контейнера. Используйте docker ps, чтобы просмотреть список запущенных контейнеров, и дважды проверьте имя.

Error response from daemon: Container 2a94aae70ea5dc92a12e30b13d0613dd6ca5919174d73e62e29cb0f79db6e4ab is not running

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

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

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

Заключение

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

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

Для получения помощи по установке Docker ознакомьтесь со статьей «Как установить и использовать Docker в Ubuntu».