Как использовать 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».