Як запустити команду на вже існуючому контейнері Docker?


492

Я створив контейнер, -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. Я не можу перемогти.


як ти дізнався, що контейнер докера вийшов? яку команду ти виконував?
Туфір

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

Якщо вам просто потрібна файлова система: Як запустити зупинений контейнер Docker за допомогою іншої команди? (Зауважте, що змінні середовища та інші речі в пам'яті вже втрачаються, коли контейнер зупиняється.)
Franklin Yu

Відповіді:


548

У жовтні 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
omg, чому це так складно? Здається, це найголовніше, що вам потрібно буде зробити. Ми не повинні використовувати його так, як вони планують.
судо

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). Що я пропускаю?
жовтий01

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

1
Але якщо я використовую докер-композицію, то -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>

Остерігайтеся, це зупинить контейнер при виході. Але загалом контейнер потрібно запустити, приєднати та зупинити його після того, як ви закінчите.


docker attach <ім'я контейнера / ідентифікатора>, який працює
KunMing Xie

9
@ Peter T. Насправді я знайшов вашу відповідь набагато більш стислим, ніж те, що надали інші. Я не розумію, чому люди вважають за краще ускладнювати дуже просте запитання. Дякую Петру за цю відповідь.
Хелен Нілі

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

1
@Peter Найбільш відповідна відповідь
Ніланджан Саркар

1
Це найточніша відповідь!
nagendra547

91

Щоб розширити відповідь katrmr, якщо контейнер зупинений і не може бути запущений через помилку, вам знадобиться commitйого до зображення. Тоді ви можете запустити bash у новому зображенні:

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

1
FYI, я роблю це настільки, що я склав команду, закликану dshellробити це автоматично в різних ситуаціях - github.com/avirshup/docker-cli-sugar
Aaron V

41

Деякі відповіді тут є оманливими, оскільки стосуються контейнерів, які працюють, а не зупиняються.

Свен Дошироліт пояснив на форумі Docker, що контейнери пов'язані зі своїм процесом (і Docker не може змінити процес зупиненого контейнера, здавалося б, щонайменше, через його внутрішню структуру: https://github.com/docker/docker/isissue / 1437 р.). Отже, в основному єдиним варіантом є commitконтейнер до зображення і runце з іншою командою.

Дивіться https://forums.docker.com/t/run-command-in-stopped-container/343
(я вважаю, що ENTRYPOINTпідхід " з аргументами" також не буде працювати, оскільки ви все одно не зможете змінити аргументи для зупиненого контейнера.)


2
Зауважте: запуск bin/bashбез -itнічого не змінить контейнер, тому виконувати його не дуже потрібно, і CDR LDN дає правильну відповідь для конкретної ситуації з ОП. Все-таки,commit є відповідь на технічну проблему, як змінити процес контейнера.
katrmr

Коментар candlerb на команді run-command-in-stop-контейнер пропонує використовувати зображення, що викидається, з об’ємом з неактивного контейнера, який працював для мене: docker run --rm - volumes - від 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
-c працював на мене. цікаво, чому один баш не буде працювати (не отримує підказки)
André Werlang

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.
joanlofe

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

Трубопровід команди для stdin

Потрібно видалити, -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 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 entrypoint, щоб отримати командний рядок, що працює всередині контейнера або приєднати до контейнера.

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

Це допомогло мені як в командному рядку приєднати до контейнера, так і зберегти контейнер в прямому ефірі. :)


0

Швидкий спосіб відновити та отримати доступ до останнього контейнера:

docker start -a -i `docker ps -q -l`

0

Я зазвичай використовую це:

    docker exec -it my-container-name bash

постійно взаємодіяти з запущеним контейнером.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.