Come avviare un contenitore Docker arrestato con un comando diverso?


251

Vorrei avviare un contenitore Docker arrestato con un comando diverso, poiché il comando predefinito si arresta in modo anomalo, il che significa che non riesco ad avviare il contenitore e quindi utilizzare 'docker exec'.

Fondamentalmente vorrei avviare una shell in modo da poter ispezionare il contenuto del contenitore.

Fortunatamente ho creato il contenitore con l'opzione -it!

Risposte:


380

Trova il tuo ID contenitore arrestato

docker ps -a

Commettere il contenitore arrestato:

Questo comando salva lo stato del contenitore modificato in una nuova immagine user/test_image

docker commit $CONTAINER_ID user/test_image

Avvia / esegui con un punto di ingresso diverso:

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

Descrizione dell'argomento Entrypoint: https://docs.docker.com/engine/reference/run/#/entrypoint-default-command-to-execute-at-runtime

Nota:

I passaggi precedenti avviano solo un contenitore arrestato con lo stesso stato del file system. È fantastico per una rapida indagine. Ma le variabili di ambiente, la configurazione di rete, i volumi collegati e altro personale non vengono ereditati, è necessario specificare tutti questi argomenti in modo esplicito.

I passaggi per avviare un container arrestato sono stati presi in prestito da qui: (ultimo commento) https://github.com/docker/docker/issues/18078


1
no, le immagini sono di sola lettura. Salva lo stato del contenitore modificato in una nuova immagine test_image
Dmitriusan,

4
questo manca quasi tutta la configurazione di env, volumi, UID, ... Tutto ciò che ha in comune con il container arrestato è il filesystem (che forse è abbastanza per alcuni)
Florian Klein

4
Sarebbe bello se potessi in qualche modo ottenere lo stesso ambiente, la configurazione di rete, i volumi collegati. È possibile convertire l' inspectoutput in una configurazione utilizzata con l'esecuzione successiva?
Otheus

2
@Webman, sì, ma questo non è vero per i volumi che sono stati montati prima di arrestare un contenitore. Dovrai collegare gli stessi volumi in modo esplicito quando
avvierai

1
@ EmreTapcı, penso che farlo sia contro l'ideologia Docker. I contenitori sono intesi come entità run-and-throw-away monouso, al contrario delle macchine virtuali. Potresti provare a seguire la risposta aaa90210 , ma sarebbe un trucco.
Dmitriusan,

126

Modifica questo file (corrispondente al contenitore arrestato):

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

Modificare il parametro "Path" per puntare al nuovo comando, ad esempio / bin / bash. È inoltre possibile impostare il parametro "Args" per passare argomenti al comando.

Riavvia il servizio docker (nota che questo fermerà tutti i container in esecuzione):

service docker restart

Elenca i tuoi contenitori e assicurati che il comando sia cambiato:

docker ps -a

Avvia il contenitore e attaccalo, ora dovresti essere nella tua shell!

docker start -ai mad_brattain

Ha lavorato su Fedora 22 usando Docker 1.7.1.

NOTA: se la shell non è interattiva (ad es. Non è stato creato il contenitore originale con l'opzione -it), è possibile invece modificare il comando in "/ bin / sleep 600" o "/ bin / tail -f / dev / null" per darti abbastanza tempo per fare "docker exec -it CONTID / bin / bash" come un altro modo di ottenere una shell.

NOTA 2: le versioni più recenti della finestra mobile hanno config.v2.json, dove sarà necessario modificare Entrypoint o Cmd (grazie user60561).


44
i miei occhi. i miei occhi. Spero che questa sia una richiesta di funzionalità da qualche parte per gestirla correttamente in Docker.
Gertvdijk,

2
@AlexeyStrakh potresti provare a eseguire "/ usr / bin / sleep 600" e quindi fare "docker exec -it / bin / bash" per ottenere una shell. Anche se non sono sicuro di come mettere i parametri su quella variabile Path. Altrimenti prova a trovare un altro comando che rimarrà in vita abbastanza a lungo da permetterti di fare un dirigente, o vedi la risposta di Dmitriusan.
aaa90210,

3
questa è l'unica risposta davvero accurata alla domanda: tutte le altre proposizioni gestiscono un "quasi lo stesso" contenitore, ma dimenticano i volumi, l'inv, gli UID, ...
Florian Klein,

3
Nel mio caso / usr / bin / sleep non era disponibile. Ho avuto successo con..."Path":"tail","Args":["-f","/dev/null"]...
nevrome il

4
Le versioni più recenti della finestra mobile hanno config.v2.json, dove sarà necessario modificare Entrypointo Cmd.
user60561

20

Aggiungi un segno di spunta all'inizio dello script Entrypoint

Docker deve davvero implementarlo come una nuova funzionalità, ma ecco un'altra soluzione alternativa per le situazioni in cui si dispone di un Entrypoint che termina in caso di esito positivo o negativo, il che può rendere difficile il debug.

Se non si dispone già di uno script Entrypoint, crearne uno che esegua qualsiasi comando (i) necessario (i) per il proprio contenitore. Quindi, all'inizio di questo file, aggiungi queste righe a 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

Per assicurarsi che catmantenga la connessione, potrebbe essere necessario fornire un TTY. Sto eseguendo il container con il mio script Entrypoint in questo modo:

docker run -t --entrypoint entrypoint.sh image_name

Questo farà eseguire lo script una volta, creando un file che indica che è già stato eseguito (nel filesystem virtuale del contenitore). È quindi possibile riavviare il contenitore per eseguire il debug:

docker start container_name

Quando riavvii il contenitore, il already_ranfile verrà trovato, causando lo stallo dello script Entrypoint cat(che attende per sempre l'input che non arriverà mai, ma mantiene attivo il contenitore). È quindi possibile eseguire una bashsessione di debug :

docker exec -i container_name bash

Mentre il contenitore è in esecuzione, è anche possibile rimuovere already_raned eseguire manualmente lo entrypoint.shscript per eseguirlo nuovamente, se è necessario eseguire il debug in questo modo.


3
Inoltre, è possibile eseguire l'esecuzione del punto di accesso /bin/shanziché cat- quindi è sempre possibile riavviare. La tua soluzione è incredibile!
Danny Dulai,

4

Il mio problema:

  • Ho avviato un contenitore con docker run <IMAGE_NAME>
  • E poi aggiunto alcuni file a questo contenitore
  • Quindi ho chiuso il contenitore e ho provato a riavviarlo con lo stesso comando di cui sopra.
  • Ma quando ho controllato i nuovi file, mancavano
  • quando corro docker ps -avedevo due container.
  • Ciò significa che ogni volta che eseguivo il docker run <IMAGE_NAME>comando, veniva creata una nuova immagine

Soluzione: per lavorare sullo stesso contenitore creato in primo luogo, eseguire questi passaggi

  • docker ps per ottenere il contenitore del tuo contenitore
  • docker container start <CONTAINER_ID> per avviare il contenitore esistente
  • Quindi puoi continuare da dove sei partito. per esempiodocker exec -it <CONTAINER_ID> /bin/bash
  • Puoi quindi decidere di creare una nuova immagine da essa

Questo non risponde alla domanda. L'OP vuole sapere come riavviare il contenitore ma con argomenti diversi da quelli utilizzati indocker run <containerID>
CodeBlooded

2

Ho preso la risposta di Dmitriusan e l'ho trasformata in un 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 "'

Aggiungi questo nel tuo ~/.bashrcfile alias e avrai un nuovo docker-run-prev-containeralias elegante che ti farà cadere in una shell nel contenitore precedente.

Utile per il debug non riuscito docker build.


2

Questo non è esattamente quello che stai chiedendo, ma puoi usarlo docker exportsu un contenitore fermo se tutto ciò che vuoi è ispezionare i file.

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

1

Non è stato specificato se il contenitore sta uscendo, solo che il codice si arresta in modo anomalo e devi vedere cosa sta succedendo nel contenitore. Se non esce, ecco un'altra potenziale soluzione.

Ottieni l'ID contenitore con docker ps

docker exec -it 665b4a1e17b6 /bin/sh

Se entrypoint è impostato su qualcosa di problematico, può anche essere ignorato come suggerito nella risposta di Dmitriusan. Va inoltre notato che è possibile collegarsi a qualsiasi contenitore in esecuzione con docker attach. Tante soluzioni soluzioni diverse. Semplicemente non vedo la necessità di impegnarmi per l'immagine. Sembra inutile.

Documenti per Docker exec - https://docs.docker.com/engine/reference/commandline/exec/

Documenti per Docker attach - https://docs.docker.com/engine/reference/commandline/attach/


-12

In realtà non sono d'accordo con entrambe queste risposte. Se vuoi solo vedere cosa c'è nel contenitore, puoi eseguire questo comando per ottenere una shell. Non è necessario modificare affatto il punto di accesso o eventuali configurazioni.

docker run -it <image_name> bash

12
Questo non funziona poiché l'operazione richiede un contenitore, non un'immagine.
Peter Vrabel,

Suppongo che tu abbia ragione, ma non vedo un motivo per farlo. Puoi reindirizzare i log a stdout e docker logs <container_id> --followti darà ciò di cui hai bisogno. Un'altra alternativa è utilizzare il comando sopra riportato, quindi avviare il servizio di arresto anomalo sull'immagine con lo stesso comando nel file docker ed eseguire il debug da lì.
deadbabykitten,

4
Il comando Esegui crea un nuovo contenitore da un'immagine. Non avvia un contenitore arrestato.
Waleed Abdulla,

2
Ummm, .. non è che il punto della finestra mobile è che ogni immagine può essere girata esattamente nello stesso modo? Questo nega la tua discussione. Non ha BISOGNO di avviare un container fermo. Qualsiasi contenitore è esattamente lo stesso, quindi non importa quale avvia o arresta. Sta solo cercando di ispezionare il contenuto. Il modo più semplice è quello di eseguire il login ed eseguire l'output del comando o pipe del comando nei log. Ragazzi a volte trovate le soluzioni più complesse per problemi semplici.
deadbabykitten

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.