Как запустить команду для уже существующего контейнера Docker?


495

Я создал контейнер с -dтаким образом, чтобы он не был интерактивным.

docker run -d shykes/pybuilder bin/bash

Я вижу, что контейнер вышел:

CONTAINER ID        IMAGE                     COMMAND             CREATED             STATUS                      PORTS               NAMES
d6c45e8cc5f0        shykes/pybuilder:latest   "bin/bash"          41 minutes ago      Exited (0) 2 seconds ago                        clever_bardeen

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

Я пытался запустить машину. Я пытался прикрепить. Я думал, что могу позвонить runс контейнером, но это, кажется, не разрешено. Использование startтолько кажется, что работает, а затем существует быстро.

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

Я старался:

docker attach d6c45e8cc5f0

Но я получаю:

2014/10/01 22:33:34 You cannot attach to a stopped container, start it first

Но если я начну, то все равно выйдет. Поймай 22. Я не могу победить.


как вы узнали, что контейнер докера вышел? какой командой ты управлял?
Thufir

docker container ls -a
Брэндон Манчестер

Если вам просто нужна файловая система: Как запустить остановленный контейнер Docker другой командой? (Обратите внимание, что переменные окружения и другие вещи в памяти уже теряются при остановке контейнера.)
Франклин Ю

Ответы:


550

В октябре 2014 года команда Docker представила docker execкоманду : https://docs.docker.com/engine/reference/commandline/exec/

Теперь вы можете запустить любую команду в работающем контейнере, просто зная его идентификатор (или имя):

docker exec -it <container_id_or_name> echo "Hello from container!"

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

docker run -it -d shykes/pybuilder /bin/bash

Самым важным здесь является -dвариант, который обозначает detached. Это означает, что команда, которую вы изначально предоставили контейнеру ( /bin/bash), будет выполняться в фоновом режиме, и контейнер не остановится немедленно .


120
Это не работает на остановленном контейнере, только на работающем. Так что, если у вас есть контейнер, который немедленно останавливается, как в вопросе, это на самом деле не будет работать, чтобы запустить что-то еще внутри него.
вмешиваться

4
@interfect прав, и у CDR LDN есть более полный ответ.
Доктор Ян-Филипп Герке

6
@ Jan-PhilipGehrcke Btw имя пользователя этого человека изменилось от CDR LDNдо cdrevответа ниже ( stackoverflow.com/a/26181666/149428 ).
Тейлор Эдмистон

3
Зачем проходить -it?
Юлиан

4
Боже, почему это так сложно? Похоже, самое основное, что вам нужно сделать. Мы не должны использовать это так, как они намерены.
Судо

287

Ваш контейнер будет выходить в качестве команды , вы дали это закончится. Используйте следующие параметры, чтобы сохранить его:

  • -i Держите STDIN открытым, даже если он не подключен.
  • -t Выделяют псевдо-TTY.

Итак, ваша новая runкоманда:

docker run -it -d shykes/pybuilder bin/bash

Если вы хотите присоединить к уже запущенному контейнеру:

docker exec -it CONTAINER_ID /bin/bash

В этих примерах /bin/bashиспользуется как команда.


2
Пробовал docker exec -it CONTAINER_ID /bin/bash -c "export VAR=1 && echo $VAR"и печатал пустую переменную (ожидается 1). Что мне не хватает?
yellow01

после запуска 'docker exec -it CONTAINER_ID / bin / bash' он корректно переходит в bash, но не может с ним взаимодействовать.
Синие облака

1
Но если я использую docker-compose, -itон недоступен.
adnanmuttaleb

120

Поэтому я думаю, что ответ проще, чем многие вводящие в заблуждение ответы выше.

Чтобы запустить существующий контейнер, который остановлен

docker start <container-name/ID>

Чтобы остановить работающий контейнер

docker stop <container-name/ID>

Затем войти в интерактивную оболочку контейнера

docker exec -it <container-name/ID> bash

Чтобы запустить существующий контейнер и присоединить к нему одной командой

docker start -ai <container-name/ID>

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



9
@ Питер Т. На самом деле, я нашел ваш ответ гораздо более кратким, чем то, что предоставили другие. Я не понимаю, почему люди предпочитают усложнять очень простой вопрос. Спасибо Петру за этот ответ.
Хелен Нили,

1
для этого необходимо, чтобы при создании docker вы делали это с -it stackoverflow.com/questions/45216612/… в противном случае он не запустится .. поэтому вы должны запустить docker <container-id>, а затем docker ps -l и вы увидите, что это не после начала. и тогда присоединение потерпит неудачу. Так что надо создавать с -it тоже.
Бароп

1
@Peter Самый актуальный ответ
Ниланджан Саркар,

1
Это самый точный ответ!
nagendra547

91

Чтобы расширить ответ katrmr, если контейнер остановлен и не может быть запущен из-за ошибки, вам нужно сделать commitэто с изображением. Затем вы можете запустить bash в новом образе:

docker commit [CONTAINER_ID] temporary_image
docker run --entrypoint=bash -it temporary_image

1
К вашему сведению, я делаю это так много, что собрал команду, вызываемую dshellдля ее автоматического выполнения в различных ситуациях - github.com/avirshup/docker-cli-sugar
Aaron V

41

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

Свен Давидейт объяснил на форуме Docker, что контейнеры связаны с их процессом (и Docker не может изменить процесс остановленного контейнера, по-видимому, по крайней мере, из-за его внутренней структуры: https://github.com/docker/docker/issues / 1437 ). Таким образом, в основном, единственная опция - commitэто контейнер с изображением и runдругой командой.

См. Https://forums.docker.com/t/run-command-in-stopped-container/343
(я считаю, что ENTRYPOINTподход « с аргументами» тоже не сработает, поскольку вы все равно не сможете изменить аргументы к остановленному контейнеру.)


2
Обратите внимание: выполнение bin/bashбез -itизменений ничего не изменит в контейнере, поэтому его фиксация на самом деле не нужна, и CDR LDN дает правильный ответ для конкретной ситуации OP. Тем не менее, commitэто ответ на техническую проблему, как изменить контейнерный процесс.
katrmr

Комментарий Candlerb в run-command-in-Stop-container, предлагающий использовать одноразовое изображение с томом из неактивного контейнера, сработал для меня: docker run --rm --volumes-from CONTAINER -i busybox tar cO / var / DIR | gzip -c> ~ / mydir_backup.tgz
угорь ghEEz

Это фактический ответ на заданный вопрос. Контейнеры связаны с их процессом, поэтому команда не может быть изменена.
cjsimon

21

Мне пришлось использовать bash -c для запуска моей команды: docker exec -it CONTAINER_ID bash -c "mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql mysql"


1
-с работал на меня. интересно, почему bash один не работает (не получает подсказку)
Андре Верланг

18

Создание контейнера и отправка ему команд, одна за другой:

docker create --name=my_new_container -it ubuntu
docker start my_new_container
// ps -a says 'Up X seconds'
docker exec my_new_container /path/to/my/command
// ps -a still says 'Up X+Y seconds'
docker exec my_new_container /path/to/another/command

Это хороший ответ на вопрос. Если вы хотите запустить контейнер после создания и иметь возможность вводить в него команды «docker exec», вы должны создать его с помощью флагов «-it» в команде docker create.
Джоанлоф

8

Это комбинированный ответ, который я составил, используя ответ CDR LDN выше и ответ, который я нашел здесь .

В следующем примере контейнер Arch Linux запускается из образа, а затем устанавливается gitв этот контейнер с помощью pacmanинструмента:

sudo docker run -it -d archlinux /bin/bash
sudo docker ps -l
sudo docker exec -it [container_ID] script /dev/null -c "pacman -S git --noconfirm"

Это все.


5

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

docker exec -it containerid bash -c /path/to/your/script.sh

4

Передайте команду на стандартный ввод

Необходимо удалить, -tчтобы это работало:

echo 'touch myfile' | sudo docker exec -i CONTAINER_NAME bash

Это может быть более удобным, чем использование параметров CLI.

Протестировано с:

sudo docker run --name ub16 -it ubuntu:16.04 bash

затем на другой оболочке:

echo 'touch myfile' | sudo docker exec -i ub16 bash

Затем на первой оболочке:

ls -l myfile

Протестировано на Docker 1.13.1, хост Ubuntu 16.04.


3

Предполагая, что образ использует точку входа по умолчанию /bin/sh -c, запуск /bin/bashнемедленно завершится в режиме демона ( -d). Если вы хотите, чтобы этот контейнер запускал интерактивную оболочку, используйте -itвместо -d. Если вы хотите выполнить произвольные команды в контейнере, обычно выполняющем другой процесс, вы можете попробовать nsenterили nsinit. Посмотрите https://blog.codecentric.de/en/2014/07/enter-docker-container/ для деталей.


3

К сожалению, невозможно переопределить ENTRYPOINTаргументы docker run --entrypointдля достижения этой цели.

Примечание: вы можете переопределить настройку ENTRYPOINT, используя --entrypoint, но это может только установить для двоичного файла значение exec (sh -c не будет использоваться).


3

Я хотел бы отметить, что верхний ответ немного вводит в заблуждение.

Проблема с выполнением docker runзаключается в том, что каждый раз создается новый контейнер. Однако есть случаи, когда мы хотели бы вернуться к старым контейнерам или не занять место с новыми контейнерами.

(Дано clever_bardeenимя созданного контейнера ...)

В случае OP убедитесь, что образ докера сначала запущен, выполнив следующую команду:

docker start clever_bardeen

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

docker exec -it clever_bardeen /bin/bash

2

Для Mac:

$ docker exec -it <container-name> sh

если вы хотите подключиться как пользователь root:

$ docker exec -u 0 -it <container-name> sh

1

Простой ответ: начать и прикрепить одновременно. В этом случае вы делаете именно то, что вы просили.

docker start <CONTAINER_ID/CONTAINER_NAME> && docker attach <CONTAINER_ID/CONTAINER_NAME> 

не забудьте изменить <CONTAINER_ID/CONTAINER_NAME>



1

Я использую контейнер Windows, и мне нужно искать в контейнере Docker файлы и папки, созданные и скопированные.

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

ENTRYPOINT ["C:\\Windows\\System32\\cmd.exe", "-D", "FOREGROUND"]

Это помогло мне как присоединить командную строку к контейнеру, так и сохранить контейнер в рабочем состоянии. :)


1

Я обычно использую это:

    docker exec -it my-container-name bash

постоянно взаимодействовать с работающим контейнером.


0

Быстрый способ возобновить и получить доступ к недавно вышедшему контейнеру:

docker start -a -i `docker ps -q -l`
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.