Jak uruchomić zatrzymany kontener Dockera za pomocą innego polecenia?

251

Chciałbym uruchomić zatrzymany kontener Dockera za pomocą innego polecenia, ponieważ polecenie domyślne ulega awarii - co oznacza, że ​​nie mogę uruchomić kontenera, a następnie użyć polecenia „docker exec”.

Zasadniczo chciałbym uruchomić powłokę, aby móc sprawdzić zawartość pojemnika.

Na szczęście utworzyłem kontener z opcją -it!

aaa90210
źródło

Odpowiedzi:

380

Znajdź zatrzymany identyfikator kontenera

docker ps -a

Zatwierdź zatrzymany kontener:

To polecenie zapisuje zmodyfikowany stan kontenera w nowym obrazie user/test_image

docker commit $CONTAINER_ID user/test_image

Rozpocznij / uruchom z innym punktem wejścia:

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

Opis argumentu punktu wejścia: https://docs.docker.com/engine/reference/run/#/entrypoint-default-command-to-execute-at-runtime

Uwaga:

Powyższe kroki po prostu uruchamiają zatrzymany kontener z tym samym stanem systemu plików. To świetnie nadaje się do szybkiego dochodzenia. Ale zmienne środowiskowe, konfiguracja sieci, dołączone woluminy i inni pracownicy nie są dziedziczone, należy jawnie podać wszystkie te argumenty.

Kroki, aby uruchomić zatrzymany pojemnik zostały pożyczone stąd: (ostatni komentarz) https://github.com/docker/docker/issues/18078

Dmitriusan
źródło
1
nie, obrazy są tylko do odczytu. Oszczędza zmodyfikowany stan kontenera do nowego obrazu test_image
Dmitriusan
4
pomija to prawie całą konfigurację dotyczącą env, woluminów, UID, ... To, co ma wspólnego z zatrzymanym kontenerem, to system plików (co może być dla niektórych wystarczające)
Florian Klein
4
Byłoby wspaniale, gdybym mógł w jakiś sposób uzyskać to samo środowisko, konfigurację sieci, dołączone woluminy. Czy można przekonwertować dane inspectwyjściowe na konfigurację używaną przy kolejnym uruchomieniu?
Otheus,
2
@ Webman, tak, ale nie dotyczy to woluminów, które zostały zamontowane przed zatrzymaniem kontenera. Przy następnym uruchomieniu kontenera będziesz musiał wyraźnie dołączyć te same tomy
Dmitriusan,
1
@ EmreTapcı, myślę, że jest to sprzeczne z ideologią Dockera. Kontenery mają być jednostką jednorazowego użytku, w przeciwieństwie do maszyn wirtualnych. Możesz spróbować zastosować się do odpowiedzi aaa90210 , ale byłby to hack.
Dmitriusan
126

Edytuj ten plik (odpowiadający zatrzymanemu kontenerowi):

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

Zmień parametr „Ścieżka”, aby wskazywał na nowe polecenie, np. / Bin / bash. Możesz także ustawić parametr „Args”, aby przekazywać argumenty do polecenia.

Uruchom ponownie usługę dokowania (pamiętaj, że spowoduje to zatrzymanie wszystkich działających kontenerów):

service docker restart

Wyświetl listę kontenerów i upewnij się, że polecenie uległo zmianie:

docker ps -a

Uruchom pojemnik i dołącz do niego, powinieneś być teraz w swojej skorupie!

docker start -ai mad_brattain

Pracował na Fedorze 22 przy użyciu Docker 1.7.1.

UWAGA: Jeśli twoja powłoka nie jest interaktywna (np. Nie utworzyłeś oryginalnego kontenera z opcją -it), możesz zamiast tego zmienić polecenie na „/ bin / sleep 600” lub „/ bin / tail -f / dev / null” aby dać ci wystarczająco dużo czasu na wykonanie polecenia „docker exec -it CONTID / bin / bash” jako innego sposobu uzyskania powłoki.

UWAGA 2: Nowsze wersje dokera mają config.v2.json, gdzie trzeba będzie zmienić Entrypoint lub Cmd (dzięki user60561).

aaa90210
źródło
44
moje oczy. moje oczy. Mam nadzieję, że jest to prośba o funkcję gdzieś, aby poprawnie obsłużyć to w Dockerze.
gertvdijk
2
@AlexeyStrakh możesz spróbować uruchomić „/ usr / bin / sleep 600”, a następnie wykonać polecenie „docker exec -it / bin / bash”, aby uzyskać powłokę. Chociaż nie jestem pewien, jak umieścić parametry w tej zmiennej Path. W przeciwnym razie spróbuj znaleźć inne polecenie, które pozostanie przy życiu wystarczająco długo, abyś mógł wykonać exec, lub zobacz odpowiedź Dmitriusana.
aaa90210
3
to jedyna naprawdę dokładna odpowiedź na pytanie: wszystkie inne propozycje działają w „prawie tym samym” pojemniku, ale zapominają o tomach, env, UID,…
Florian Klein
3
W moim przypadku / usr / bin / sleep nie był dostępny. ..."Path":"tail","Args":["-f","/dev/null"]...
Odniosłem
4
Nowsze wersje dokowanym mieć config.v2.json, gdzie będzie trzeba zmienić albo Entrypointalbo Cmd.
user60561,
20

Dodaj zaznaczenie u góry skryptu Entrypoint

Docker naprawdę musi zaimplementować to jako nową funkcję, ale oto kolejna opcja obejścia sytuacji, w których masz punkt wejścia, który kończy się po sukcesie lub niepowodzeniu, co może utrudnić debugowanie.

Jeśli nie masz jeszcze skryptu Entrypoint, utwórz taki, który uruchamia dowolne polecenia dla twojego kontenera. Następnie u góry tego pliku dodaj te wiersze do 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

Aby upewnić się, że catpołączenie jest utrzymywane, konieczne może być podanie TTY. Korzystam z kontenera za pomocą skryptu Entrypoint w następujący sposób:

docker run -t --entrypoint entrypoint.sh image_name

Spowoduje to, że skrypt uruchomi się raz, tworząc plik wskazujący, że już się uruchomił (w wirtualnym systemie plików kontenera). Następnie możesz ponownie uruchomić kontener, aby przeprowadzić debugowanie:

docker start container_name

Po ponownym uruchomieniu kontenera already_ranplik zostanie znaleziony, co spowoduje zatrzymanie skryptu Entrypoint cat(który po prostu czeka wiecznie na dane wejściowe, które nigdy nie nadejdą, ale utrzymują kontener przy życiu). Następnie możesz wykonać bashsesję debugowania :

docker exec -i container_name bash

Podczas działania kontenera możesz również usunąć already_rani ręcznie uruchomić entrypoint.shskrypt, aby go ponownie uruchomić, jeśli chcesz w ten sposób debugować.

Ethan T.
źródło
3
Dodatkowo możesz uruchomić punkt wejścia /bin/shzamiast cat- wtedy zawsze możesz się zrestartować. Twoje rozwiązanie rządzi!
Danny Dulai
4

Mój problem:

  • Zacząłem pojemnik z docker run <IMAGE_NAME>
  • A potem dodał kilka plików do tego kontenera
  • Następnie zamknąłem pojemnik i próbowałem uruchomić go ponownie za pomocą tego samego polecenia, co powyżej.
  • Ale kiedy sprawdziłem nowe pliki, ich brakowało
  • kiedy biegnę docker ps -a, widziałem dwa pojemniki.
  • Oznacza to, że za każdym razem, gdy uruchamiam docker run <IMAGE_NAME>polecenie, tworzony jest nowy obraz

Rozwiązanie: Aby pracować na tym samym kontenerze, który utworzyłeś w pierwszej kolejności, wykonaj następujące kroki

  • docker ps aby dostać pojemnik swojego pojemnika
  • docker container start <CONTAINER_ID> aby uruchomić istniejący kontener
  • Następnie możesz kontynuować od miejsca, w którym opuściłeś. na przykładdocker exec -it <CONTAINER_ID> /bin/bash
  • Następnie możesz zdecydować o utworzeniu z niego nowego obrazu
Amit Dudhbade
źródło
To nie odpowiada na pytanie. OP chce wiedzieć, jak zrestartować kontener, ale z innymi argumentami niż te użyte wdocker run <containerID>
CodeBlooded
2

Wziąłem odpowiedź @ Dmitriusana i przekształciłem ją w alias:

alias 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 "'

Dodaj to do ~/.bashrcpliku aliasów, a będziesz miał nowy, docker-run-prev-containersprytny alias, który przeniesie Cię do powłoki w poprzednim kontenerze.

Przydatne dla debugowania nieudane docker builds.

Dean Rather
źródło
2

Nie jest to dokładnie to, o co prosisz, ale możesz użyć docker exportzatrzymanego kontenera, jeśli wszystko, czego chcesz, to sprawdzić pliki.

mkdir $TARGET_DIR
docker export $CONTAINER_ID | tar -x -C $TARGET_DIR
Lars Christian Jensen
źródło
1

Nie określono, czy kontener się kończy, tylko że kod ulega awarii i musisz zobaczyć, co się dzieje w kontenerze. Jeśli nie wychodzi, oto inne potencjalne rozwiązanie.

Uzyskaj identyfikator kontenera za pomocą docker ps

docker exec -it 665b4a1e17b6 /bin/sh

Jeśli punkt wejścia jest ustawiony na coś problematycznego, można go również zastąpić, jak sugeruje odpowiedź Dmitriusan. Należy również zauważyć, że można dołączyć do dowolnego działającego kontenera za pomocą docker attach. Tak wiele rozwiązań, różne rozwiązania. Po prostu nie widzę potrzeby angażowania się w obraz. To wydaje się niepotrzebne.

Dokumenty dla Docker exec - https://docs.docker.com/engine/reference/commandline/exec/

Dołącz Dokumenty do Dockera - https://docs.docker.com/engine/reference/commandline/attach/

deadbabykitten
źródło
-12

Właściwie nie zgadzam się z obiema tymi odpowiedziami. Jeśli chcesz tylko zobaczyć, co jest w kontenerze, możesz uruchomić to polecenie, aby uzyskać powłokę. Nie ma potrzeby zmiany punktu wejścia ani żadnej konfiguracji.

docker run -it <image_name> bash
deadbabykitten
źródło
12
To nie działa, ponieważ operacja pyta o kontener, a nie obraz.
Peter Vrabel
Przypuszczam, że masz rację, ale nie widzę powodu, aby to zrobić. Możesz przesyłać logi do standardowego wyjścia, a docker logs <container_id> --followotrzymasz to, czego potrzebujesz. Inną alternatywą jest użycie powyższego polecenia, a następnie uruchomienie usługi awarii na tym obrazie za pomocą tego samego polecenia w pliku dokera i stamtąd debugowanie.
deadbabykitten
4
Polecenie Uruchom tworzy nowy kontener z obrazu. Nie uruchamia zatrzymanego kontenera.
Waleed Abdulla
2
Ummm ... czyż nie chodzi o to, że dokerowanie polega na tym, że każdy obraz można odwrócić dokładnie w ten sam sposób? To neguje twój argument. Nie musi uruchamiać zatrzymanego pojemnika. Każdy pojemnik jest dokładnie taki sam, więc tak naprawdę nie ma znaczenia, który z nich zacznie, a który zatrzyma. On tylko chce sprawdzić zawartość. Najłatwiej to zrobić za pomocą bash i uruchomić polecenie lub potok wyjściowy polecenia do dzienników. Czasami wymyślacie najbardziej złożone rozwiązania prostych problemów.
deadbabykitten
-12
docker container start <CONTAINER_ID>
Oscar Calderón
źródło