Come posso eseguire un comando su un contenitore Docker già esistente?


495

Ho creato un contenitore con -dquindi non interattivo.

docker run -d shykes/pybuilder bin/bash

Vedo che il contenitore è uscito:

CONTAINER ID        IMAGE                     COMMAND             CREATED             STATUS                      PORTS               NAMES
d6c45e8cc5f0        shykes/pybuilder:latest   "bin/bash"          41 minutes ago      Exited (0) 2 seconds ago                        clever_bardeen

Ora vorrei eseguire comandi occasionali sulla macchina ed uscire. Solo per ottenere la risposta.

Ho provato ad avviare la macchina. Ho provato ad attaccare. Pensavo di poter chiamare runcon un contenitore, ma questo non sembra essere permesso. L'utilizzo startsembra funzionare e quindi esistere rapidamente.

Vorrei tornare in modalità interattiva dopo essere uscito.

Provai:

docker attach d6c45e8cc5f0

Ma ottengo:

2014/10/01 22:33:34 You cannot attach to a stopped container, start it first

Ma se lo avvio, esce comunque. Cattura 22. Non riesco a vincere.


come sapevi che il container docker era uscito? quale comando hai eseguito?
Giovedì

docker container ls -a
Brandon Manchester,

Se hai solo bisogno del file system: come avviare un container Docker arrestato con un comando diverso? (Si noti che le variabili di ambiente e altre cose in memoria sono già perse quando il contenitore si è arrestato.)
Franklin Yu,

Risposte:


550

Nell'ottobre 2014 il team Docker ha introdotto il docker execcomando : https://docs.docker.com/engine/reference/commandline/exec/

Quindi ora puoi eseguire qualsiasi comando in un container in esecuzione solo conoscendo il suo ID (o nome):

docker exec -it <container_id_or_name> echo "Hello from container!"

Si noti che il execcomando funziona solo sul contenitore già in esecuzione. Se il contenitore è attualmente arrestato, è necessario prima eseguirlo con il comando seguente:

docker run -it -d shykes/pybuilder /bin/bash

La cosa più importante qui è l' -dopzione, che sta per detached. Significa che il comando inizialmente fornito al container ( /bin/bash) verrà eseguito in background e il container non si fermerà immediatamente .


120
Questo non funziona su un container arrestato, ma solo su uno in esecuzione. Quindi, se hai un contenitore che si ferma immediatamente, come nella domanda, questo non funzionerà effettivamente per far funzionare qualcos'altro al suo interno.
interfaccia il

4
@interfect ha ragione e CDR LDN ha una risposta più completa.
Dr. Jan-Philip Gehrcke,

6
@ Jan-PhilipGehrcke Tra il nome utente di questa persona è cambiato da CDR LDNa cdrevper la risposta di seguito ( stackoverflow.com/a/26181666/149428 ).
Taylor Edmiston,

3
Perché passare -it?
Iulian Onofrei il

4
omg perché è così complicato? Sembra la cosa più semplice che dovresti fare. Non dobbiamo usarlo nel modo in cui intendono.
sudo,

287

Il vostro container esce come il comando che hai dato andrà a finire. Utilizzare le seguenti opzioni per mantenerlo attivo:

  • -i Tenere aperto STDIN anche se non collegato.
  • -t Assegna uno pseudo-TTY.

Quindi il tuo nuovo runcomando è:

docker run -it -d shykes/pybuilder bin/bash

Se si desidera collegare a un contenitore già in esecuzione:

docker exec -it CONTAINER_ID /bin/bash

In questi esempi /bin/bashviene utilizzato come comando.


2
docker exec -it CONTAINER_ID /bin/bash -c "export VAR=1 && echo $VAR"Variabile vuota provata e stampata (prevista 1). Cosa mi sto perdendo?
yellow01

dopo aver eseguito 'docker exec -it CONTAINER_ID / bin / bash' va correttamente alla bash ma non può interagire con essa.
Blue Clouds,

1
Ma se sto usando la finestra mobile-componi -itnon è disponibile.
adnanmuttaleb,

120

Quindi penso che la risposta sia più semplice di molte risposte fuorvianti sopra.

Per avviare un contenitore esistente che è stato arrestato

docker start <container-name/ID>

Per interrompere un contenitore in esecuzione

docker stop <container-name/ID>

Quindi accedere alla shell interattiva di un contenitore

docker exec -it <container-name/ID> bash

Per avviare un contenitore esistente e collegarlo ad esso con un comando

docker start -ai <container-name/ID>

Attenzione, questo fermerà il contenitore all'uscita. Ma in generale, è necessario avviare il contenitore, collegarlo e interromperlo dopo aver terminato.


docker attach <nome contenitore / ID> in esecuzione
KunMing Xie

9
@Peter T. In realtà, ho trovato la tua risposta molto più concisa di quello che gli altri hanno fornito. Non capisco perché le persone preferiscano complicare una domanda molto semplice. Grazie Peter questa risposta.
Helen Neely,

1
questo richiede che quando hai creato la finestra mobile, lo hai fatto con -it stackoverflow.com/questions/45216612/… altrimenti non si avvierà .. quindi faresti avviare la finestra mobile <contenuto-id> e quindi la finestra mobile ps -l e vedresti che non è attivo dopo l'inizio. e quindi il collegamento fallirebbe. Quindi devo creare anche con -it.
barlop

1
@Peter La risposta più pertinente
Nilanjan Sarkar,

1
Questa è la risposta più accurata!
nagendra547,

91

Per espandere la risposta di katrmr, se il contenitore viene arrestato e non può essere avviato a causa di un errore, dovrai commitfarlo su un'immagine. Quindi puoi avviare bash nella nuova immagine:

docker commit [CONTAINER_ID] temporary_image
docker run --entrypoint=bash -it temporary_image

1
Cordiali saluti, lo faccio così tanto che ho messo insieme un comando chiamato dshellper farlo automaticamente in una varietà di situazioni - github.com/avirshup/docker-cli-sugar
Aaron V

41

Alcune delle risposte qui sono fuorvianti perché riguardano contenitori in esecuzione, non fermati.

Sven Dowideit ha spiegato sul forum Docker che i contenitori sono vincolati al loro processo (e Docker non può cambiare il processo di un contenitore arrestato, apparentemente dovuto almeno alla sua struttura interna: https://github.com/docker/docker/issues / 1437 ). Quindi, in sostanza, l'unica opzione è commitil contenitore di un'immagine erun con un comando diverso.

Vedi https://forums.docker.com/t/run-command-in-stopped-container/343
(credo che l' ENTRYPOINTapproccio " con argomenti" non funzionerebbe neanche, dal momento che non saresti ancora in grado di cambiare il argomenti a un contenitore arrestato.)


2
Avviso: l'esecuzione bin/bashsenza -itmodificare nulla nel contenitore, quindi non è necessario impegnarlo e CDR LDN fornisce la risposta giusta per la situazione particolare del PO. Tuttavia, commitè la risposta al problema tecnico di come modificare il processo di contenitore.
Katrmr,

Il commento di candlerb a run-command-in-fermato-container che suggerisce di usare un'immagine usa e getta con il volume dal contenitore inattivo ha funzionato per me: docker run --rm --volumes-from CONTAINER -i busybox tar cO / var / DIR | gzip -c> ~ / mydir_backup.tgz
eel ghEEz

Questa è la risposta effettiva alla domanda posta. I contenitori sono associati al loro processo, quindi il comando non può essere modificato.
cjsimon,

21

Ho dovuto usare bash -c per eseguire il mio comando: docker exec -it CONTAINER_ID bash -c "mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql mysql"


1
-c ha funzionato per me. mi chiedo perché bash da solo non funzioni (non viene richiesto)
André Werlang il

18

Creazione di un contenitore e invio di comandi ad esso, uno per uno:

docker create --name=my_new_container -it ubuntu
docker start my_new_container
// ps -a says 'Up X seconds'
docker exec my_new_container /path/to/my/command
// ps -a still says 'Up X+Y seconds'
docker exec my_new_container /path/to/another/command

Questa è la buona risposta alla domanda. Se si desidera avviare il contenitore dopo la creazione ed essere in grado di eseguire i comandi "docker exec", è necessario crearlo con i flag "-it" nel comando docker create.
joanlofe,

8

Questa è una risposta combinata che ho creato usando la risposta LDN CDR sopra e la risposta che ho trovato qui .

L'esempio seguente avvia un contenitore Arch Linux da un'immagine e quindi si installa gitsu quel contenitore usando lo pacmanstrumento:

sudo docker run -it -d archlinux /bin/bash
sudo docker ps -l
sudo docker exec -it [container_ID] script /dev/null -c "pacman -S git --noconfirm"

Questo è tutto.


5

Se si sta tentando di eseguire lo script di shell, è necessario eseguirlo come bash.

docker exec -it containerid bash -c /path/to/your/script.sh

4

Inoltra un comando a stdin

Deve rimuovere il -tper farlo funzionare:

echo 'touch myfile' | sudo docker exec -i CONTAINER_NAME bash

Questo può essere più conveniente che l'uso delle opzioni della CLI a volte.

Testato con:

sudo docker run --name ub16 -it ubuntu:16.04 bash

quindi su un'altra shell:

echo 'touch myfile' | sudo docker exec -i ub16 bash

Quindi sulla prima shell:

ls -l myfile

Testato su Docker 1.13.1, host Ubuntu 16.04.


3

Supponendo che l'immagine stia utilizzando il punto di accesso predefinito /bin/sh -c, l'esecuzione /bin/bashverrà chiusa immediatamente in modalità demone ( -d). Se si desidera che questo contenitore esegua una shell interattiva, utilizzare -itinvece di -d. Se si desidera eseguire comandi arbitrari in un contenitore che di solito esegue un altro processo, è possibile provare nsentero nsinit. Dai un'occhiata a https://blog.codecentric.de/en/2014/07/enter-docker-container/ per i dettagli.


3

Sfortunatamente è impossibile scavalcare gli ENTRYPOINTargomenti docker run --entrypointper raggiungere questo obiettivo.

Nota: è possibile ignorare l'impostazione ENTRYPOINT usando --entrypoint, ma questo può solo impostare il binario su exec (non verrà usato sh -c).


3

Vorrei sottolineare che la risposta migliore è un po 'fuorviante.

Il problema con l'esecuzione docker runè che ogni volta viene creato un nuovo contenitore. Tuttavia, ci sono casi in cui vorremmo rivisitare vecchi contenitori o non occupare spazio con nuovi contenitori.

(Dato clever_bardeenè il nome del contenitore creato ...)

Nel caso di OP, assicurarsi che l'immagine docker sia in primo luogo in esecuzione eseguendo il comando seguente:

docker start clever_bardeen

Quindi, eseguire il contenitore finestra mobile utilizzando il comando seguente:

docker exec -it clever_bardeen /bin/bash

2

Per Mac:

$ docker exec -it <container-name> sh

se vuoi connetterti come utente root:

$ docker exec -u 0 -it <container-name> sh

1

Risposta semplice: avvia e allega contemporaneamente. In questo caso stai facendo esattamente quello che hai chiesto.

docker start <CONTAINER_ID/CONTAINER_NAME> && docker attach <CONTAINER_ID/CONTAINER_NAME> 

assicurati di cambiare <CONTAINER_ID/CONTAINER_NAME>


1
# docker exec -d container_id command 

Ex:

# docker exec -d xcdefrdtt service jira stop 

1

Sto eseguendo il contenitore di Windows e ho bisogno di cercare all'interno del contenitore della finestra mobile i file e le cartelle creati e copiati.

Per fare ciò ho usato il seguente comando entrypoint docker per far funzionare il prompt dei comandi all'interno del contenitore o collegarlo al contenitore.

ENTRYPOINT ["C:\\Windows\\System32\\cmd.exe", "-D", "FOREGROUND"]

Ciò mi ha aiutato sia al prompt dei comandi da collegare al contenitore sia a mantenere attivo il contenitore. :)


0

Un modo rapido per riprendere e accedere al contenitore uscito più di recente:

docker start -a -i `docker ps -q -l`

0

Di solito lo uso:

    docker exec -it my-container-name bash

per interagire continuamente con un container in esecuzione.

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.