Як запустити контейнер Docker, що зупинився, за допомогою іншої команди?


251

Я хотів би запустити зупинений контейнер Docker з іншою командою, оскільки команда за замовчуванням виходить з ладу - це означає, що я не можу запустити контейнер, а потім використовувати "docker exec".

В основному я хотів би запустити оболонку, щоб я міг оглянути вміст контейнера.

На щастя, я створив контейнер з опцією -it!

Відповіді:


380

Знайдіть ідентифікатор зупиненого контейнера

docker ps -a

Введіть зупинений контейнер:

Ця команда зберігає змінене стан контейнера в новому зображенні user/test_image

docker commit $CONTAINER_ID user/test_image

Почати / запустити з іншої точки входу:

docker run -ti --entrypoint=sh user/test_image

Опис аргументу вступу: https://docs.docker.com/engine/reference/run/#/entrypoint-default-command-to-execute-at-runtime

Примітка:

Наведені вище кроки просто запускають зупинений контейнер з тим же станом файлової системи. Це чудово для швидкого розслідування. Але змінні середовища, конфігурація мережі, додані обсяги та інший персонал не успадковуються, ви повинні чітко вказати всі ці аргументи.

Кроки для запуску зупиненого контейнера були запозичені тут: (останній коментар) https://github.com/docker/docker/isissue/18078


1
ні, зображення лише для читання. Це зберігає модифікований стан контейнера в новому зображенні test_image
Dmitriusan

4
тут пропущено майже всю конфігурацію про env, томи, UID, ... Все, що вона має спільне із зупиненим контейнером, - це файлова система (що для деяких може бути достатньо)
Флоріан Кляйн

4
Було б чудово, якби я міг якось отримати одне середовище, конфігурацію мережі, додані томи. Чи можливо перетворити inspectвихід у конфігурацію, яка використовується з наступним запуском?
Отей

2
@Webman, так, але це неправда для томів, які були встановлені перед зупинкою контейнера.
Такі

1
@ EmreTapcı, я думаю, що робити це проти ідеології Докера. Контейнери призначені для суцільного використання, що працює під час викиду та викидання, на відміну від віртуальних машин. Ви можете спробувати дотримуватися відповіді aaa90210 , але це було б хаком .
Дмитріусан

126

Відредагуйте цей файл (відповідає зупиненому контейнеру):

vi /var/lib/docker/containers/923...4f6/config.json

Змініть параметр "Шлях", щоб вказати на нову команду, наприклад / bin / bash. Ви також можете встановити параметр "Args" для передачі аргументів команді.

Перезапустіть службу докера (зверніть увагу, що це зупинить усі запущені контейнери):

service docker restart

Перерахуйте свої контейнери та переконайтесь, що команда змінилась:

docker ps -a

Запустіть контейнер і прикладіть до нього, тепер ви повинні бути в своїй оболонці!

docker start -ai mad_brattain

Працював над Fedora 22 за допомогою Docker 1.7.1.

ПРИМІТКА: Якщо ваша оболонка не є інтерактивною (наприклад, ви не створили оригінальний контейнер з опцією -it), замість цього можете змінити команду на "/ bin / sleep 600" або "/ bin / tail -f / dev / null" щоб дати вам достатньо часу, щоб зробити "docker exec - це CONTID / bin / bash" як інший спосіб отримання оболонки.

ПРИМІТКА2. Новіші версії докера мають config.v2.json, де вам потрібно буде змінити або Entrypoint, або Cmd (спасибі user60561).


44
мої очі. мої очі. Я сподіваюся, що це запит на особливості, щоб правильно впоратись із цим в Docker.
gertvdijk

2
@AlexeyStrakh ви можете спробувати запустити "/ usr / bin / sleep 600", а потім зробити "docker exec -it / bin / bash", щоб отримати оболонку. Хоча я не впевнений, як розмістити параметри на цій змінній Path. В іншому випадку спробуйте знайти іншу команду, яка залишиться в живих досить довго, щоб ви виконали виконання або побачили відповідь від Дмитріусана.
aaa90210

3
це єдина справді точна відповідь на питання: всі інші пропозиції запускають «майже такий самий» контейнер, але вони забувають про обсяги, env, UID,…
Флоріан Кляйн

3
У моєму випадку / usr / bin / сон був недоступний. У мене був успіх..."Path":"tail","Args":["-f","/dev/null"]...
невром

4
Новіші версії docker мають config.v2.json, де вам потрібно буде змінити Entrypointабо Cmd.
user60561

20

Додайте чек у верхній частині сценарію Entrypoint

Докер дійсно повинен реалізувати це як нову функцію, але ось ще один варіант вирішення ситуацій, коли у вас є Entrypoint, який припиняється після успіху чи невдачі, що може ускладнити налагодження.

Якщо у вас ще немає сценарію Entrypoint, створіть той, який виконує всі необхідні для вашого контейнера команди. Потім вгорі цього файлу додайте ці рядки до entrypoint.sh:

# Run once, hold otherwise
if [ -f "already_ran" ]; then
    echo "Already ran the Entrypoint once. Holding indefinitely for debugging."
    cat
fi
touch already_ran

# Do your main things down here

Щоб переконатися, що catз'єднання утримується, вам може знадобитися надати TTY. Я запускаю контейнер зі своїм скриптом Entrypoint так:

docker run -t --entrypoint entrypoint.sh image_name

Це призведе до запуску сценарію один раз, створивши файл, який вказує на те, що він вже запущений (у віртуальній файловій системі контейнера). Потім можна перезапустити контейнер, щоб виконати налагодження:

docker start container_name

Після перезавантаження контейнера already_ranфайл буде знайдений, що спричинить затримку сценарію Entrypoint cat(який просто вічно чекає на введення, яке ніколи не надійде, але зберігає контейнер живим). Потім можна виконати bashсесію налагодження :

docker exec -i container_name bash

Поки контейнер працює, ви також можете видалити already_ranта вручну виконати entrypoint.shсценарій для його повторного використання, якщо вам доведеться налагоджувати цей спосіб.


3
Крім того, ви можете зробити точку входу /bin/shзамість cat- тоді ви завжди можете ввійти просто перезапуститись. Ваше рішення гойдається!
Денні Дулай

4

Моя проблема:

  • Я розпочав контейнер з docker run <IMAGE_NAME>
  • А потім додав кілька файлів до цього контейнера
  • Потім я закрив контейнер і спробував запустити його знову тією ж командою, що і вище.
  • Але коли я перевірив нові файли, вони відсутні
  • коли я біжу docker ps -a я міг побачити два контейнери.
  • Це означає, що кожного разу, коли я виконував docker run <IMAGE_NAME>команду, створювався новий образ

Рішення. Щоб працювати над тим же контейнером, який ви створили, виконайте такі дії

  • docker ps щоб отримати контейнер вашого контейнера
  • docker container start <CONTAINER_ID> для запуску існуючого контейнера
  • Потім ви можете продовжити звідки ви поїхали. напрdocker exec -it <CONTAINER_ID> /bin/bash
  • Потім можна вирішити створити з нього нове зображення

Це не відповідає на запитання. ОП хоче знати, як перезапустити контейнер, але з іншими аргументами, ніж ті, що використовуютьсяdocker run <containerID>
CodeBlooded

2

Я взяв відповідь @ Дмитріусана і перетворив її на псевдонім:

псевдонім docker-run-prev-container = 'prev_container_id = "$ (docker ps -aq | head -n1)" && docker commit "$ prev_container_id" "prev_container / $ prev_container_id" && docker run -it --entrypoint = bash "prev_container / $ prev_container_id "'

Додайте це у ~/.bashrcфайл псевдонімів, і ви отримаєте чудовий новийdocker-run-prev-container псевдонім, який перекине вас у оболонку попереднього контейнера.

Корисно для налагодження помилок docker builds.


2

Це не саме те, що ви просите, але ви можете використовувати docker exportна зупиненому контейнері, якщо все, що вам потрібно, - це перевірити файли.

mkdir $TARGET_DIR
docker export $CONTAINER_ID | tar -x -C $TARGET_DIR

1

Не було вказано, чи не є контейнер, тільки що ваш код виходить з ладу, і вам потрібно побачити, що відбувається в контейнері. Якщо він не виходить, ось ще одне потенційне рішення.

Отримайте ідентифікатор контейнера за допомогою docker ps

docker exec -it 665b4a1e17b6 /bin/sh

Якщо вхідну точку встановлено на щось проблематичне, її також можна буде відмінити, як це запропоновано у відповіді Дмитріусана. Слід також зазначити, що ви можете приєднати до будь-якого запущеного контейнераdocker attach . Так багато рішень різних рішень. Я просто не бачу необхідності робити зображення. Це здається непотрібним.

Документи для Docker exec - https://docs.docker.com/engine/reference/commandline/exec/

Документи для вкладення Docker - https://docs.docker.com/engine/reference/commandline/attach/


-12

Я фактично не згоден з обома цими відповідями. Якщо ви просто хочете побачити, що знаходиться в контейнері, тоді ви можете запустити цю команду, щоб отримати оболонку. Не потрібно змінювати точку входу взагалі або будь-які конфігурації.

docker run -it <image_name> bash

12
Це не працює, оскільки оператор запитує про контейнер, а не про зображення.
Петро Врабель

Я думаю, що ви маєте право, але не бачите причин для цього. Ви можете подати колоди до stdout і docker logs <container_id> --followдасть вам те, що вам потрібно. Іншою альтернативою є використання команди вище, а потім запустити службу збоїв на цьому зображенні з тією ж командою в dockerfile та налагодження звідти.
deadbabykitten

4
Команда run створює новий контейнер із зображення. Він не запускає зупинений контейнер.
Уелід Абдулла

2
Уммм, .. чи не в цьому справа докера в тому, що кожне зображення можна розкручувати точно однаково? Це заперечує ваш аргумент. Йому НЕ ПОТРІБНО запускати зупинений контейнер. Будь-який контейнер точно такий же, тож насправді не має значення, який він запускає чи зупиняє. Він просто намагається оглянути вміст. Найпростіший спосіб зробити це - вбити і запустити команду або виведення команди команди в журнали. Ви, хлопці, інколи придумуєте найскладніші рішення для простих проблем.
deadbabykitten

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