Как редактировать файлы в остановленном / не запускающемся докер-контейнере

94

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

  • либо я совсем ленив и устанавливаю nano и редактирую прямо в контейнере, либо

  • Я docker cp файл из контейнера, редактирую его, копирую обратно и перезапускаю контейнер

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

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

Есть ли способ спасти эти контейнеры? Поскольку они не запускаются, я не могу выполнить в них docker exec, и поэтому они потеряны для меня. Затем я перехожу по маршруту rm / rmi / build / run после исправления ошибочного файла во входных данных сборки.

Как я могу либо редактировать файлы в остановленном контейнере, либо копировать их, либо запускать оболочку в остановленном контейнере - все, что позволяет мне исправить этот контейнер?

(Это немного похоже на работу на удаленном компьютере и нарушение сетевой конфигурации - таким образом соединение теряется «навсегда», и нужно использовать запасной вариант, если он существует.)

Как редактировать файлы контейнера Docker с хоста? выглядит актуально, но устарело.

Андреас Рейфф
источник
Это также может быть обходным путем stackoverflow.com/a/32353134/586754 - в надежде на лучшее решение.
Андреас Рейфф,
1
возможно, вам стоит подумать о монтировании тома, чтобы вы могли редактировать файлы на своем хосте, а не внутри контейнера. После того, как ваш код будет доволен, вы можете свободно docker cp
размещать
Да, это было бы немного поздно, если бы я не настраивал такие вещи с самого начала. Думаю, это не работает для восстановления.
Андреас Рейфф
Многие читатели захотят только просматривать файлы, а не редактировать их. В этих случаях вы можете использовать docker commitкоманду для разрыва нового изображения. name=$(docker commit); docker run -it $name /bin/shбуду делать то, что ты хочешь.
Att Righ
так кажется, что файловые системы остановленных контейнеров относительно постоянны в конце?
Webwoman

Ответы:

139

У меня возникла проблема с контейнером, который не запускался из-за неправильного изменения конфигурации, которое я сделал. Мне удалось скопировать файл из остановленного контейнера и отредактировать его. что-то типа:

docker cp docker_web_1:/etc/apache2/sites-enabled/apache2.conf .

(поправьте файл)

docker cp apache.conf docker_web_1:/etc/apache2/sites-enabled/apache2.conf
Томьюри
источник
22
Это должен быть принятый ответ. По какой-то причине я не думал, что CP работает с остановленными контейнерами. Ницца!
Proximo 07
Отлично. Я скопировал файл из контейнера (я знал его путь), затем отредактировал его, а затем скопировал обратно в контейнер в то же место. Сработало у меня! Благодарность!
Наваз,
Есть ли способ удалить файл?
Кодлан
1
@kodlan Только если он появляется только в полученном UpperDirвами docker container inspect- вам придется поэкспериментировать, чтобы увидеть, как система наложения представляет файлы в базовой структуре, которые были удалены на верхнем уровне.
Тим Бэверсток,
Спасибо, это помогло мне исправить мой контейнер MySQL, работающий в докере на macOS.
mazedlx
60

Отвечая на свой вопрос ... все еще надеюсь на лучший ответ от более знающего человека !!

Есть 2 возможности.

1) Редактирование файловой системы непосредственно на хосте . Это несколько опасно и может полностью сломать контейнер, возможно, другие данные в зависимости от того, что пойдет не так.

2) Изменение сценария запуска на что-то, что никогда не дает сбоев, например запуск bash, выполнение исправлений / правок, а затем изменение программы запуска снова на желаемую (например, узел или что-то еще).

Подробнее:

1) Использование

docker ps

найти работающие контейнеры или

docker ps -a

найти все контейнеры (в том числе остановленные) и

docker inspect (containername)

ищите "Id", одно из первых значений.

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

Перейти к

/var/lib/docker/aufs/diff/9bc343a9..(long container id)/

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

Опять же, я бы не рекомендовал это.

2) Как описано на https://stackoverflow.com/a/32353134/586754, вы можете найти конфигурацию json config.json по пути вроде

/var/lib/docker/containers/9bc343a99..(long container id)/config.json

Там вы можете изменить аргументы, например, с «nodejs app.js» на «/ bin / bash». Теперь перезапустите службу докеров и запустите контейнер (вы должны увидеть, что теперь он правильно запускается). Вы должны использовать

docker start -i (containername)

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

docker exec -ti (containername) /bin/bash

Кроме того, docker cp весьма полезен для копирования файлов, которые редактировались вне контейнера.

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

Андреас Рейфф
источник
Все еще надеемся на лучший ответ - так что не стесняйтесь давать его, я также перенесу тег "ansered".
Андреас Рейфф
Я использовал второй способ, и мне пришлось перезапускать службу докеров, чтобы принудительно перезаписывать config.jsonфайлы каждый раз, когда я их редактировал,
Виталий Исаев
2
У меня есть config.v2.json, и каждый раз, когда я запускаю контейнер зомби, он отменяет обновление моего пути / точки входа и снова умирает. Использование "docker cp" для обновления скрипта entrypoint.sh, чтобы просто запустить bash, исправило его.
Curtis Yallop
@CurtisYallop Я испытываю то же самое. Как вы это решили?
Brett McLain
1
@BrettMcLain Я использовал docker cp, а не редактировал его на хосте. Примерно так: Найдите расположение сценария точки входа: «docker inspect имя_контейнера | grep Entry». Получить скрипт: "docker cp имя_контейнера: /entrypoint.sh ./". (Отредактируйте) Поместите сценарий обратно в контейнер: «docker cp entrypoint.sh имя_контейнера: /entrypoint.sh». Вы можете запустить bash в точке входа или запустить цикл сна, например, «while:; do sleep 10; done». Первая строка скрипта должна быть "#! / Bin / bash".
Curtis Yallop
9

Вы можете редактировать файловую систему контейнера напрямую, но я не знаю, хорошая ли это идея. Сначала вам нужно найти путь к каталогу, который используется как корень времени выполнения для контейнера. Беги docker container inspect id/name. Найдите ключ UpperDirв выводе JSON.

Это ваш каталог.

Теджас Сараде
источник
Нашел каталог, но он не содержит всех файлов.
aioobe
Это OverlayFS, поэтому ваши файлы должны находиться в одном из этих каталогов.
Tejas Sarade
Имя каталога может отличаться от «UpperDir», например, в моем случае это Source. Но это сработало!
Раджни Кевлани,
0

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

  1. Используйте docker inspect, чтобы найти точку входа (в некоторых версиях она называется Path)
  2. Создайте клон с помощью docker run
  3. Введите clone, используя docker exec -ti bash (если контейнер * nix)
  4. Найдите местоположение файла точки входа, просмотрев клон, чтобы найти
  5. Скопируйте старый скрипт точки входа с помощью docker cp: ./
  6. Измените или создайте, например, новый сценарий точки входа

    #!/bin/bash tail -f /etc/hosts

  7. убедитесь, что у сценария есть права на выполнение
  8. Замените старую точку входа с помощью docker cp ./:
  9. запустить старый контейнер, используя start
  10. повторить шаги 6-9 до начала
  11. Исправить проблемы в контейнере
  12. При необходимости восстановите точку входа и повторите шаги 6–9 при необходимости.
  13. При необходимости удалите клон
пользователь6830669
источник