È possibile avviare una sessione di shell in un contenitore in esecuzione (senza SSH)


341

Mi aspettavo ingenuamente che questo comando eseguisse una shell bash in un container in esecuzione:

docker run "id of running container" /bin/bash

sembra che non sia possibile, ricevo l'errore:

2013/07/27 20:00:24 Internal server error: 404 trying to fetch remote history for 27d757283842

Quindi, se voglio eseguire bash shell in un container in esecuzione (ad es. A scopo di diagnosi)

devo eseguire un server SSH in esso e accedere tramite ssh?


1
docker run CONTAINERè previsto per 1.0
kolypto

7
Dal docker 1.3 dovresti davvero fare come descritto in questa risposta
Thomasleveil,

1
solodocker attach container_name
maxbellec

1
Sembra che la seconda risposta sia molto meglio al giorno d'oggi di quella accettata - potresti riconsiderare di cambiare la risposta accettata?
jsbueno,

Risposte:


285

EDIT: ora puoi usare docker exec -it "id of running container" bash( doc )

In precedenza, la risposta a questa domanda era:

Se è davvero necessario e ci si trova in un ambiente di debug, è possibile farlo: sudo lxc-attach -n <ID> tenere presente che l'id deve essere completo (docker ps -notrunc ).

Tuttavia, lo consiglio vivamente contro questo.

avviso: -notruncè deprecato, sarà presto sostituito --no-trunc.


1
perché mi sconsigli?
Max L.

7
Lo sconsiglio perché 1) richiede un kernel molto recente, 2) Stai facendo cose al di fuori della finestra mobile in modo da non poterlo rintracciare (registri, allegati, ecc.). Inoltre, la finestra mobile potrebbe usare lxc in questo momento, ma non esiste alcuna garanzia che lo farà per sempre.
scricchiolio

1
Prova l'aggiornamento a 0.7.6. Docker sta ancora usando lxc in questo momento e lxc-attachdovrebbe funzionare bene. Ho appena raddoppiato il controllo e funziona per me. (Nota che non funzionerà con il kernel precedente al 3.8).
scricchiolio

2
dalla finestra mobile 0.9 non funziona più con LXC per impostazione predefinita. Dovresti lanciare il docker -d -e lxc
docker deamon

2
Max L., il tuo caso d'uso può essere risolto con volumi di dati . Esempio Non testato: 1) eseguire contenitore con tronchi nginx in volume di dati: docker run -v /var/log/nginx -name somename imagename command; 2) eseguire un altro contenitore per visualizzare il contenuto del volume di dati: docker run -volumes-from somename -i -t busybox /bin/sh.
ciastek,

615

Con la finestra mobile 1.3, c'è un nuovo comando docker exec. Ciò consente di inserire una finestra mobile in esecuzione:

docker exec -it "id of running container" bash

2
Questo ha funzionato alla grande per me. Aggiunta molto utile alla corsa docker.
Oraserrata,

Cosa succede se ho apportato modifiche mentre eseguivo un container in esecuzione e volevo riflettere le modifiche online? quali sono le migliori pratiche?
mediaroot,

Molto utile. Grazie
luongnv89,

utilizzare docker psper ottenere l'ID delle istanze in esecuzione
muon

Nota: il contenitore potrebbe non avere bash (»exec:" bash ": file eseguibile non trovato«). Utilizzare docker inspect <image>per vedere quale shell è disponibile. Ad esempio, corri docker exec -it <container id> /bin/shinvece.
pixelbrackets,

14

Basta fare

docker attach container_name

Come menzionato nei commenti, per staccare dal contenitore senza fermarlo, digitare Ctrlpquindi Ctrlq.


5
Grazie!! Ha aiutato. E nel contesto della vera domanda, vorrei aggiungere qualcosa. Dopo aver eseguito il debug del nostro contenitore utilizzando, docker attach container_nameutilizzare ctrl pe ctrl qinvece di exit. exitcomando arresta il contenitore, dove, come ctrlpe ctrl qappena stacca quel contenitore e la mantiene in esecuzione
phoenix

10

Poiché le cose stanno cambiando, al momento sta usando il modo consigliato di accedere a un container in esecuzione nsenter .

Puoi trovare maggiori informazioni su questo repository github . Ma in generale puoi usare nsenter in questo modo:

PID=$(docker inspect --format {{.State.Pid}} <container_name_or_ID>)
nsenter --target $PID --mount --uts --ipc --net --pid

oppure puoi usare il wrapper docker-enter:

docker-enter <container_name_or_ID>

Una bella spiegazione sull'argomento può essere trovata nel blog di Jérôme Petazzoni: Perché non è necessario eseguire sshd nei contenitori della finestra mobile


sfortunatamente, le variabili env sono incasinate usando questo approccio (se si desidera controllare le variabili create dal collegamento). Suggerisco di fare source /proc/*/environ.
Tomas Tomecek,

8

La prima cosa che non puoi correre

docker run "existing container" command

Perché questo comando prevede un'immagine e non un contenitore e comporterebbe comunque la generazione di un nuovo contenitore (quindi non quello che si desidera guardare)

Sono d'accordo con il fatto che con la finestra mobile dovremmo spingerci a pensare in un modo diverso (quindi dovresti trovare modi in cui non devi accedere al contenitore), ma lo trovo ancora utile ed è così che lavoro intorno ad esso.

Eseguo i miei comandi tramite supervisore in modalità DEAMON.

Quindi eseguo quello che chiamo docker_loop.sh Il contenuto è praticamente questo:

#!/bin/bash
/usr/bin/supervisord
/usr/bin/supervisorctl
while ( true )
    do
    echo "Detach with Ctrl-p Ctrl-q. Dropping to shell"
    sleep 1
    /bin/bash
done

Quello che fa è che ti permette di "collegarti" al contenitore e ti viene presentata l' supervisorctlinterfaccia per fermare / avviare / riavviare e controllare i log. Se ciò non dovesse bastare, puoi farloCtrl+D e cadrai in una shell che ti permetterà di dare un'occhiata come se fosse un sistema normale.

SI PREGA DI ANCHE TENERE CONTO che questo sistema non è sicuro come avere il contenitore senza un guscio, quindi prendere tutte le misure necessarie per proteggere il contenitore.


5

Tieni d'occhio questa richiesta pull: https://github.com/docker/docker/pull/7409

Che implementa la prossima docker exec <container_id> <command>utilità. Quando è disponibile, dovrebbe essere possibile, ad esempio, avviare e arrestare il servizio ssh all'interno di un container in esecuzione.

C'è anche nsinitda fare: "nsinit fornisce un modo pratico per accedere a una shell all'interno dello spazio dei nomi di un container in esecuzione" , ma sembra difficile farlo funzionare. https://gist.github.com/ubergarm/ed42ebbea293350c30a6


docker execatterrato in Docker 1.3, quindi ora è possibile creare e partecipare a una nuova sessione di shell in un container in esecuzione
foz,


1

Esiste effettivamente un modo per avere una shell nel contenitore.

Supponiamo che /root/run.shavvii il processo, il gestore del processo (supervisore) o qualsiasi altra cosa.

Crea /root/runme.shcon alcuni trucchi per lo schermo gnu:

# Spawn a screen with two tabs
screen -AdmS 'main' /root/run.sh
screen -S 'main' -X screen bash -l
screen -r 'main'

Ora, hai i tuoi demoni nella scheda 0 e una shell interattiva nella scheda 1. docker attachin qualsiasi momento per vedere cosa sta succedendo all'interno del contenitore.

Un altro consiglio è quello di creare un'immagine "bundle di sviluppo" sopra l'immagine di produzione con tutti gli strumenti necessari, incluso questo trucco dello schermo.


1

ecco la mia soluzione

parte di DOckerfile:

...
RUN mkdir -p /opt
ADD initd.sh /opt/
RUN chmod +x /opt/initd.sh
ENTRYPOINT ["/opt/initd.sh"]

parte di "initd.sh"

#!/bin/bash
...
/etc/init.d/gearman-job-server start
/etc/init.d/supervisor start
#very important!!!
/bin/bash

dopo che l'immagine è stata creata hai due opzioni usando exec e attach:

  1. con exec (che io uso), esegui:

esecuzione docker - nome $ CONTAINER_NAME -dt $ IMAGE_NAME

poi

docker exec -it $ CONTAINER_NAME / bin / bash

e usare

CTRL + D da staccare

  1. con attach, esegui:

docker run --name $ CONTAINER_NAME -dit $ IMAGE_NAME

poi

finestra mobile allegare $ CONTAINER_NAME

e usare

CTRL + P e CTRL + Q da staccare

la differenza tra le opzioni è nel parametro -i


1

Ci sono due modi.

Con allegato

$ sudo docker attach 665b4a1e17b6 #by ID

Con exec

$ sudo docker exec - -t 665b4a1e17b6 #by ID


0

È utile assegnare il nome quando si esegue il contenitore. Non è necessario fare riferimento a container_id.

docker run --name container_name yourimage docker exec -it container_name bash


0

per prima cosa, procurati l'ID contenitore del contenitore desiderato

docker ps

otterrai qualcosa del genere:

CONTAINER ID        IMAGE                  COMMAND             CREATED             STATUS                          PORTS                    NAMES
3ac548b6b315        frontend_react-web     "npm run start"     48 seconds ago      Up 47 seconds                   0.0.0.0:3000->3000/tcp   frontend_react-web_1

ora copia questo ID contenitore ed esegui il seguente comando:

docker exec -it container_id sh

docker exec -it 3ac548b6b315 sh


-2

Forse sei stato indotto in errore come me a pensare in termini di macchine virtuali durante lo sviluppo di container. Il mio consiglio: cerca di non farlo.

I contenitori sono come qualsiasi altro processo. In effetti potresti voler "collegarli" per scopi di debug (pensa a / proc // env o strace -p) ma questo è un caso molto speciale.

Normalmente basta "eseguire" il processo, quindi se si desidera modificare la configurazione o leggere i registri, è sufficiente creare un nuovo contenitore e assicurarsi di scrivere i registri al di fuori di esso condividendo le directory, scrivendo su stdout (quindi i registri della finestra mobile funzionano) o qualcosa di simile.

Per scopi di debug potresti voler avviare una shell, quindi il tuo codice, quindi premere CTRL-p + CTRL-q per lasciare intatta la shell. In questo modo è possibile ricollegare utilizzando:

docker attach <container_id>

Se vuoi eseguire il debug del contenitore perché sta facendo qualcosa che non ti aspetti che faccia, prova a eseguire il debug: /server/596994/how-can-i-debug-a-docker-container -inizializzazione


Questo è completamente sbagliato. Essere in grado di introspettare lo spazio dei nomi LXC in cui è in esecuzione l'applicazione non è un "caso molto speciale", è un'attività comune / giornaliera per qualsiasi sviluppatore.
sleepycal,

@sleepycal "qualsiasi sviluppatore" sembra un po 'distorto. In ogni caso utilizzo l'introspezione dei processi, quindi la stessa cosa vale per i contenitori. Questa è l'idea alla base del debug. Si allega un debugger al processo (che potrebbe avere un cli). Pensare che tu sia "loggato" nel contenitore mi sembra ancora fuorviante.
estani,

-4

No, non è possibile. Usa qualcosa di simile supervisordper ottenere un server SSH se è necessario. Anche se, sicuramente metto in dubbio la necessità.

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.