Get a shell: docker exec
docker ps
docker exec -it web sh
-i keeps input open and -t gives you a terminal. Replace web with the name from docker ps. Use bash if the image has it. Useful options:
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
With Podman, the same commands work with podman in place of docker.
On a remote server
SSH into the host, not the container. To do it in one step, ask for a terminal with -t:
ssh -t user@server docker exec -it web sh
Without -t, recent Docker versions stop with cannot attach stdin to a TTY-enabled container because stdin is not a terminal, and older ones with the input device is not a TTY. For more than one command, just log in to the server first.
A short name for the server saves typing here: see SSH config file examples.
Common errors
No shell in the image:
OCI runtime exec failed: exec failed: unable to start container process: exec: "bash": executable file not found in $PATH
Try sh. Alpine images have sh and no bash. If sh gives the same error, the image has no shell at all, which is common for minimal images. Start a helper container that shares its process and network view:
docker run --rm -it --pid=container:web --network=container:web alpine sh
From there, ps shows the other container's processes.
Container stopped:
Error response from daemon: container 962d0cc0707e... is not running
You cannot exec into a stopped container. Read why it stopped, and copy files out if you need them. docker cp also works on a stopped container:
docker logs web
docker cp web:/etc/hostname .
Control a remote Docker from your laptop
The Docker client can talk to a remote daemon through SSH, so docker ps and docker exec on your laptop act on the server. No Docker port is opened, and only SSH is used:
DOCKER_HOST=ssh://user@server docker ps
DOCKER_HOST=ssh://user@server docker exec -it web sh
To keep it, create a context:
docker context create --docker host=ssh://user@server remote
docker --context remote ps
You need a working key login to the server, a Docker client on your laptop, and a server user allowed to use the Docker socket. Be aware that access to the Docker daemon is close to root on that machine: Docker's documentation says only trusted users should have it.
Each command opens a new connection, so Docker suggests reusing one in ~/.ssh/config. See SSH multiplexing.
When sshd in a container makes sense
Only when SSH itself is the point:
- A test server for SSH clients, scripts or Ansible.
- A tool that can only reach things over SSH or SFTP, and that you cannot change.
- A jump host or SFTP drop box that you deliberately run as a container.
For getting in to debug something, it adds a service, a key and an open port, and docker exec already does that job. If you do need it, this runs and logs in with a key:
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
Three details matter here:
- Host keys are created at start, not in the image. Otherwise every container from the image shares the same private host key. The downside is a new key each time a container is recreated, which triggers the host key warning. Keep
/etc/sshin a volume if that matters. - The port is bound to 127.0.0.1. Published ports skip ufw. Docker's documentation says traffic is diverted before it reaches ufw's rules, so
-p 2222:22can be open to the world even with ufw on. - This image holds no secrets.
authorized_keyshas only public keys. Never copy a private key into an image.
Questions
Does docker exec need SSH?
No. The docker command talks to the Docker daemon, which starts the process inside the container.
How do I open a shell in a container as root?
Add -u root: docker exec -it -u root web sh. It works even when the image runs as another user.
How do I enter a container on a remote server?
SSH into the server that runs it, then use docker exec. In one step: ssh -t user@server docker exec -it web sh.
Does a shell started with docker exec survive a container restart?
No. It only runs while the container's main process is running, and it is not started again when the container restarts.
Sources
- docker container exec, Docker Docs
- Protect the Docker daemon socket, Docker Docs
- Docker security, Docker Docs
- Packet filtering and firewalls, Docker Docs