Come entrare con SSH in un container Docker

Quasi mai serve. Esegui docker exec -it web sh sulla macchina dove gira il container, oppure ssh -t user@server docker exec -it web sh da un'altra macchina. Di norma un container non ha un server SSH, e aggiungerlo raramente vale la pena. Per controllare un Docker remoto dal tuo portatile usa DOCKER_HOST=ssh://user@server.

Aggiornata il . Le opzioni di docker exec, i messaggi di errore, la shell sidecar e il Dockerfile con sshd sono stati eseguiti con Docker su Linux. Gli errori di exec, il container di appoggio e docker cp sono stati ricontrollati con Docker 29.5.

Aprire una shell: docker exec

docker ps
docker exec -it web sh

-i tiene aperto l'input e -t ti dà un terminale. Sostituisci web con il nome che vedi in docker ps. Usa bash se l'immagine ce l'ha. Opzioni utili:

docker exec -it -u root web sh              # as another user
docker exec -it -w /app web sh              # in another folder
docker exec -e DEBUG=1 web env              # with an extra variable
docker compose exec web sh                  # with Compose: no -it needed

Con Podman gli stessi comandi funzionano scrivendo podman al posto di docker.

Su un server remoto

Entra con SSH nell'host, non nel container. Per farlo in un solo passaggio, chiedi un terminale con -t:

ssh -t user@server docker exec -it web sh

Senza -t, le versioni recenti di Docker si fermano con cannot attach stdin to a TTY-enabled container because stdin is not a terminal, quelle più vecchie con the input device is not a TTY. Se devi eseguire più di un comando, accedi prima al server.

Un nome breve per il server fa risparmiare battute: vedi esempi del file config di SSH.

Errori comuni

Nessuna shell nell'immagine:

OCI runtime exec failed: exec failed: unable to start container process: exec: "bash": executable file not found in $PATH

Prova sh. Le immagini Alpine hanno sh e non bash. Se anche sh dà lo stesso errore, l'immagine non ha nessuna shell, cosa comune nelle immagini minimali. Avvia un container di appoggio che condivide la vista dei processi e della rete:

docker run --rm -it --pid=container:web --network=container:web alpine sh

Da lì, ps mostra i processi dell'altro container.

Container fermo:

Error response from daemon: container 962d0cc0707e... is not running

Non puoi usare exec in un container fermo. Leggi perché si è fermato e copia fuori i file che ti servono. docker cp funziona anche su un container fermo:

docker logs web
docker cp web:/etc/hostname .

Controllare un Docker remoto dal portatile

Il client Docker può parlare con un demone remoto tramite SSH, quindi docker ps e docker exec sul tuo portatile agiscono sul server. Non viene aperta nessuna porta Docker e si usa solo SSH:

DOCKER_HOST=ssh://user@server docker ps
DOCKER_HOST=ssh://user@server docker exec -it web sh

Per rendere stabile la configurazione, crea un contesto:

docker context create --docker host=ssh://user@server remote
docker --context remote ps

Ti servono un accesso con chiave funzionante al server, un client Docker sul portatile e un utente del server autorizzato a usare il socket di Docker. Tieni presente che l'accesso al demone Docker è quasi equivalente a root su quella macchina: la documentazione di Docker dice che dovrebbero averlo solo utenti fidati.

Ogni comando apre una nuova connessione, quindi Docker consiglia di riutilizzarne una in ~/.ssh/config. Vedi il multiplexing SSH.

Quando ha senso sshd in un container

Solo quando SSH è proprio lo scopo:

  • Un server di prova per client SSH, script o Ansible.
  • Uno strumento che raggiunge le cose solo via SSH o SFTP e che non puoi modificare.
  • Un jump host o una cartella di consegna SFTP che fai girare di proposito come container.

Per entrare a fare debug, aggiunge un servizio, una chiave e una porta aperta, e docker exec fa già quel lavoro. Se ti serve davvero, questo si avvia e accetta l'accesso con chiave:

FROM debian:13-slim
RUN apt-get update && apt-get install -y --no-install-recommends openssh-server \
 && rm -f /etc/ssh/ssh_host_* \
 && useradd -m -s /bin/bash app && mkdir -p /run/sshd \
 && install -d -m 700 -o app -g app /home/app/.ssh
COPY authorized_keys /home/app/.ssh/authorized_keys
RUN chown app:app /home/app/.ssh/authorized_keys && chmod 600 /home/app/.ssh/authorized_keys
CMD ["sh", "-c", "ssh-keygen -A && exec /usr/sbin/sshd -D -e -o PasswordAuthentication=no"]
docker build -t sshd-demo .
docker run -d --name sshd-demo -p 127.0.0.1:2222:22 sshd-demo
ssh -p 2222 app@127.0.0.1

Qui contano tre dettagli:

  • Le chiavi dell'host vengono create all'avvio, non nell'immagine. Altrimenti ogni container creato dall'immagine condivide la stessa chiave privata dell'host. Lo svantaggio è una chiave nuova ogni volta che il container viene ricreato, il che fa comparire l'avviso sulla chiave dell'host. Se ti importa, tieni /etc/ssh in un volume.
  • La porta è legata a 127.0.0.1. Le porte pubblicate aggirano ufw. La documentazione di Docker dice che il traffico viene deviato prima di raggiungere le regole di ufw, quindi -p 2222:22 può essere aperta al mondo anche con ufw attivo.
  • Questa immagine non contiene segreti. authorized_keys contiene solo chiavi pubbliche. Non copiare mai una chiave privata in un'immagine.

Domande

docker exec richiede SSH?

No. Il comando docker parla con il demone Docker, che avvia il processo dentro il container.

Come apro una shell in un container come root?

Aggiungi -u root: docker exec -it -u root web sh. Funziona anche se l'immagine gira con un altro utente.

Come entro in un container su un server remoto?

Accedi via SSH al server che lo esegue, poi usa docker exec. In un solo passo: ssh -t user@server docker exec -it web sh.

Una shell avviata con docker exec sopravvive al riavvio del container?

No. Esiste solo finché gira il processo principale del container e non viene riavviata quando il container riparte.

Fonti

Altro in SSH su ogni sistema

Tutte le guide