Obtener un shell: docker exec
docker ps
docker exec -it web sh
-i mantiene abierta la entrada y -t te da un terminal. Cambia web por el nombre que muestra docker ps. Usa bash si la imagen lo tiene. Opciones útiles:
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, los mismos comandos funcionan escribiendo podman en lugar de docker.
En un servidor remoto
Entra por SSH en el host, no en el contenedor. Para hacerlo en un solo paso, pide un terminal con -t:
ssh -t user@server docker exec -it web sh
Sin -t, las versiones recientes de Docker se detienen con cannot attach stdin to a TTY-enabled container because stdin is not a terminal, y las antiguas con the input device is not a TTY. Si vas a ejecutar más de un comando, lo más sencillo es entrar antes en el servidor.
Un nombre corto para el servidor ahorra escribir: consulta ejemplos del archivo de configuración de SSH.
Errores comunes
No hay shell en la imagen:
OCI runtime exec failed: exec failed: unable to start container process: exec: "bash": executable file not found in $PATH
Prueba con sh. Las imágenes Alpine tienen sh y no tienen bash. Si sh da el mismo error, la imagen no tiene ningún shell, algo habitual en imágenes mínimas. Inicia un contenedor auxiliar que comparta su vista de procesos y de red:
docker run --rm -it --pid=container:web --network=container:web alpine sh
Desde ahí, ps muestra los procesos del otro contenedor.
Contenedor detenido:
Error response from daemon: container 962d0cc0707e... is not running
No se puede hacer exec en un contenedor detenido. Lee por qué se detuvo y saca los archivos que necesites. docker cp también funciona con un contenedor detenido:
docker logs web
docker cp web:/etc/hostname .
Controlar un Docker remoto desde tu portátil
El cliente de Docker puede hablar con un daemon remoto a través de SSH, de modo que docker ps y docker exec en tu portátil actúan sobre el servidor. No se abre ningún puerto de Docker, solo se usa SSH:
DOCKER_HOST=ssh://user@server docker ps
DOCKER_HOST=ssh://user@server docker exec -it web sh
Para dejarlo fijo, crea un contexto:
docker context create --docker host=ssh://user@server remote
docker --context remote ps
Necesitas un acceso con clave que funcione al servidor, un cliente de Docker en tu portátil y un usuario del servidor con permiso para usar el socket de Docker. Ten en cuenta que el acceso al daemon de Docker equivale casi a ser root en esa máquina: la documentación de Docker dice que solo los usuarios de confianza deben tenerlo.
Cada comando abre una conexión nueva, así que Docker sugiere reutilizar una en ~/.ssh/config. Mira la multiplexación SSH.
Cuándo tiene sentido un sshd en un contenedor
Solo cuando SSH es el objetivo en sí:
- Un servidor de pruebas para clientes SSH, scripts o Ansible.
- Una herramienta que solo puede llegar a las cosas por SSH o SFTP, y que no puedes cambiar.
- Un jump host o un buzón SFTP que ejecutas a propósito como contenedor.
Para entrar a depurar algo, añade un servicio, una clave y un puerto abierto, y docker exec ya hace ese trabajo. Si de verdad lo necesitas, esto arranca y permite entrar con una clave:
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
Aquí importan tres detalles:
- Las claves del host se crean al arrancar, no en la imagen. Si no, todos los contenedores de la imagen comparten la misma clave privada del host. El inconveniente es una clave nueva cada vez que se recrea un contenedor, lo que provoca el aviso de clave del host. Guarda
/etc/sshen un volumen si eso te importa. - El puerto está enlazado a 127.0.0.1. Los puertos publicados se saltan ufw. La documentación de Docker dice que el tráfico se desvía antes de llegar a las reglas de ufw, así que
-p 2222:22puede quedar abierto al mundo aunque ufw esté activo. - Esta imagen no guarda secretos.
authorized_keyssolo tiene claves públicas. Nunca copies una clave privada en una imagen.
Preguntas
¿docker exec necesita SSH?
No. El comando docker habla con el daemon de Docker, que inicia el proceso dentro del contenedor.
¿Cómo abro un shell en un contenedor como root?
Añade -u root: docker exec -it -u root web sh. Funciona aunque la imagen se ejecute con otro usuario.
¿Cómo entro en un contenedor de un servidor remoto?
Entra por SSH en el servidor que lo ejecuta y usa docker exec. En un solo paso: ssh -t user@server docker exec -it web sh.
¿Un shell iniciado con docker exec sobrevive al reinicio del contenedor?
No. Solo funciona mientras el proceso principal del contenedor está en marcha, y no se vuelve a iniciar cuando el contenedor se reinicia.
Fuentes
- docker container exec, Docker Docs
- Protect the Docker daemon socket, Docker Docs
- Docker security, Docker Docs
- Packet filtering and firewalls, Docker Docs