Как запустить остановленный контейнер 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 build
s.
Моя проблема:
- Я начал контейнер с
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 в качестве точки входа. В любом случае, если вы знаете файл, который вы взломали, простое решение, которое сработало для меня, было
Скопируйте файл, который вы вырезали из образа:
докер cp bt-php:/etc/apache2/apache2.conf .
Исправить это локально
Скопируйте его обратно в
докер cp apache2.conf bt-php:/etc/apache2/apache2.conf
Запустите резервную копию вашего контейнера
* Бонусные баллы — поскольку этот файл модифицируется, добавьте его в свои сценарии Compose или Build, чтобы, когда вы все сделаете правильно, он был запечен в образе!
У меня был док-контейнер, в котором контейнер MariaDB постоянно зависал при запуске из-за поврежденных таблиц InnoDB.
Что я сделал, чтобы решить мою проблему:
- скопируйте docker-entrypoint.sh из контейнера в локальную файловую систему (docker cp)
- отредактируйте его, включив в него необходимый параметр командной строки (в моем случае --innodb-force-recovery=1)
- скопируйте отредактированный файл обратно в контейнер докера, перезаписав существующий сценарий точки входа.
У меня Docker всегда оставляет впечатление, что он был создан для системы хобби, он отлично подходит для этого.
Если что-то не получается или не работает, не ждите профессионального решения.
Тем не менее: Docker не только НЕ поддерживает такие основные административные задачи, но и пытается их предотвратить.
Решение:
-
cd /var/lib/docker/overlay2/
-
find | grep somechangedfile # You now can see the changed file from your container in a hexcoded folder/diff
-
cd hexcoded-folder/diff
Создать
entrypoint.sh
(обязательно сделайте резервную копию существующего, если он есть)cat > entrypoint.sh #!/bin/bash while ((1)); do sleep 1; done;
Ctrl+C
chmod +x entrypoint.sh
-
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 run -it <image_name> bash