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

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

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

К счастью, я создал контейнер с опцией -it!

17 ответов

Решение

Найдите свой остановленный идентификатор контейнера

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/

Замечания:

Шаги выше просто запустить остановленный контейнер с тем же состоянием файловой системы. Это отлично подходит для быстрого расследования. Но переменные среды, конфигурация сети, подключенные тома и другие сотрудники не наследуются, все эти аргументы следует указывать явно.

Шаги для запуска остановленного контейнера заимствованы отсюда: (последний комментарий) https://github.com/docker/docker/issues/18078

Отредактируйте этот файл (соответствующий вашему остановленному контейнеру):

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

Измените параметр "Path", чтобы он указывал на вашу новую команду, например /bin/bash. Вы также можете установить параметр "Args" для передачи аргументов в команду.

Перезапустите службу Docker (обратите внимание, что это остановит все запущенные контейнеры):

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 -it CONTID /bin/bash" как еще один способ получения оболочки.

Добавьте проверку в начало вашего скрипта Entrypoint

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

Если у вас еще нет сценария 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 скрипт для его повторного запуска, если вам нужно отладить таким образом.

docker-compose run --entrypoint /bin/bash cont_id_or_name

(для conven поместите свои env, vol монтирует в docker-compose.yml)

или используйте docker run и вручную укажите все аргументы

Это не совсем то, о чем вы просите, но вы можете использовать docker export на остановленном контейнере, если все, что вам нужно, - это проверить файлы.

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

Я взял ответ @Dmitriusan и превратил его в псевдоним:

псевдоним 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.

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

  • Я начал контейнер с 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 --name c --entrypoint "/boot" -v "./boot":/boot $image

Вот точка входа в загрузку:

      #!/bin/bash
command_a

Когда вам нужно перезапустить c с другой командой, вы просто измените сценарий загрузки:

      #!/bin/bash
command_b

И перезапустите:

      docker restart c

Я нашел простую команду

      docker start -a [container_name]

Это поможет

Или же

      docker start [container_name]

тогда

      docker exec -it [container_name] bash

Похоже, что большую часть времени люди сталкиваются с этим при изменении файла конфигурации, что я и сделал. Я пытался обойти CORS для сервера PHP/Apache с Vue SPA в качестве точки входа. В любом случае, если вы знаете файл, который вы взломали, простое решение, которое сработало для меня, было

  1. Скопируйте файл, который вы вырезали из образа:

    докер cp bt-php:/etc/apache2/apache2.conf .

  2. Исправить это локально

  3. Скопируйте его обратно в

    докер cp apache2.conf bt-php:/etc/apache2/apache2.conf

  4. Запустите резервную копию вашего контейнера

  5. * Бонусные баллы — поскольку этот файл модифицируется, добавьте его в свои сценарии Compose или Build, чтобы, когда вы все сделаете правильно, он был запечен в образе!

У меня был док-контейнер, в котором контейнер MariaDB постоянно зависал при запуске из-за поврежденных таблиц InnoDB.

Что я сделал, чтобы решить мою проблему:

  • скопируйте docker-entrypoint.sh из контейнера в локальную файловую систему (docker cp)
  • отредактируйте его, включив в него необходимый параметр командной строки (в моем случае --innodb-force-recovery=1)
  • скопируйте отредактированный файл обратно в контейнер докера, перезаписав существующий сценарий точки входа.

У меня Docker всегда оставляет впечатление, что он был создан для системы хобби, он отлично подходит для этого.
Если что-то не получается или не работает, не ждите профессионального решения.

Тем не менее: Docker не только НЕ поддерживает такие основные административные задачи, но и пытается их предотвратить.

Решение:

  1.         cd /var/lib/docker/overlay2/
    
  2.         find | grep somechangedfile 
    # You now can see the changed file from your container in a hexcoded folder/diff
    
  3.         cd hexcoded-folder/diff
    
  4. Создать entrypoint.sh (обязательно сделайте резервную копию существующего, если он есть)

            cat > entrypoint.sh
    #!/bin/bash
    while ((1)); do sleep 1; done;
    

    Ctrl+C

             chmod +x entrypoint.sh
    
  5.         docker stop
    docker start
    

Теперь у вас есть ваш докер-контейнер с бесконечным циклом вместо исходной записи, вы можете выполнить в нем bash или делать все, что вам нужно. Когда закончите, остановите контейнер, удалите / переименуйте вашу пользовательскую точку входа.

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

Если полный путь к точке входа для контейнера известен (или может быть обнаружен с помощью проверки), его можно скопировать в остановленный контейнер и из него с помощью «docker cp». Это означает, что вы можете скопировать оригинал из контейнера, отредактировать его копию, чтобы запустить оболочку bash (или таймер длительного сна) вместо того, что он делал, а затем перезапустить контейнер. Работающий контейнер теперь можно редактировать с помощью оболочки bash, чтобы исправить любые проблемы. Когда закончите редактирование другого docker cp исходной точки входа обратно в контейнер, повторный перезапуск должен помочь.

Я использовал это один раз, чтобы исправить «быстрое исправление», которое я использовал, и больше не мог запускать контейнер с обычной точкой входа, пока это не было исправлено.

Я также согласен, что должен быть лучший способ сделать это через докер: может быть, вариант «перезапустить докер», который позволяет использовать альтернативную точку входа? Эй, может быть, это уже работает с «--entrypoint»? Не уверен, не пробовал, оставил в качестве упражнения для читателя, дайте мне знать, если это сработает. :)

Чтобы войти в оболочку (bash / sh) контейнера, который не может быть запущен (по какой-то причине вышел):

      docker start [CONTAINER] && docker exec -it [CONTAINER] bash

Это возможно из-за &&, что означает, что непосредственно перед тем, как контейнер не запустится, мы немедленно запускаем bash.

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

Получить идентификатор контейнера с 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/

docker container start <CONTAINER_ID>

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

docker run -it <image_name> bash
Другие вопросы по тегам