Exec & Interact
Shell into running containers, execute one-off commands, copy files, and debug live services with docker exec and docker cp.
docker exec
docker exec lets you run any command inside an already-running container. It opens a new process alongside the main one, so your container keeps running normally.
# Basic syntax
docker exec [OPTIONS] CONTAINER COMMAND [ARGS...]
# Run a one-off command
docker exec my-nginx nginx -t # Test nginx config
docker exec my-db psql -U postgres -l # List postgres databases
docker exec my-app python manage.py check
# Open an interactive shell
docker exec -it my-nginx bash
docker exec -it my-db sh # Alpine containers use sh, not bash
docker exec -it my-redis redis-cli
The -it flags give you an interactive terminal: -i keeps stdin open, -t allocates a TTY so it behaves like a real shell.
How to Open a Shell in a Docker Container
The most common use of docker exec is getting a prompt inside a running container:
docker exec -it my-container bash # most Linux distros
docker exec -it my-container sh # Alpine and minimal images
docker exec -it my-container zsh # if zsh is installed
Once you're inside, you can explore freely without affecting the running app:
ls /app # browse the filesystem
cat /etc/nginx/nginx.conf # read config files
Useful docker exec Options
Run as a Different User
If your container runs as a non-root user but you need root access for debugging:
docker exec -u root -it my-app bash
docker exec -u appuser -it my-app sh
Pass Environment Variables
docker exec -e DEBUG=true -it my-app bash
Start in a Specific Directory
docker exec -w /app/logs -it my-app sh
docker cp
docker cp lets you move files between your host machine and a container, with this option you don't need shell, or mount the volume.
# Host → Container
docker cp ./config.json my-container:/app/config.json
# Container → Host
docker cp my-container:/app/logs/app.log ./app.log
# Works even on stopped containers
docker cp my-stopped-container:/var/log/app.log ./recovered.log
This is especially handy for recovering logs from a crashed container, injecting a config file without rebuilding the image, or pulling out compiled build artifacts.
docker attach
docker attach connects your terminal directly to the container's main process (PID 1), rather than spawning a new one like exec does.
docker attach my-container
Two important things to know before using it:
- Pressing
Ctrl+Csends a stop signal to the main process, and this will stop your container - To safely detach without stopping: press
Ctrl+PthenCtrl+Q
For most debugging situations, docker exec -it is the better choice. docker attach is only really useful when the main process itself is interactive, like a REPL.
docker inspect
docker inspect gives you a complete JSON dump of everything Docker knows about a container like its config, network settings, mounts, environment variables, and more.
# Full output
docker inspect my-container
# Just the IP address
docker inspect --format='{{.NetworkSettings.IPAddress}}' my-container
# Environment variables
docker inspect --format='{{range .Config.Env}}{{println .}}{{end}}' my-container
# PID of the main process
docker inspect --format='{{.State.Pid}}' my-container
docker top
It is used to view what's running inside a container directly from your host, without exec:
docker top my-container
docker top my-container aux # custom ps format
A Practical Debugging Workflow
Here's a step-by-step approach when a container is misbehaving:
# 1. Check if it's running and its status
docker ps -a --filter name=my-app
# 2. Stream the most recent logs
docker logs --tail 50 -f my-app
# 3. Check the container config
docker inspect my-app | grep -A5 '"Env"'
# 4. Exec in to investigate directly
docker exec -it my-app sh
# Inside the container:
ls -la /app # check the filesystem
curl localhost:3000/health # test the internal service
env # review environment variables
Quick Reference
| Command | What It Does |
|---|---|
docker exec -it <c> bash | Open an interactive shell |
docker exec -u root -it <c> bash | Open a shell as root |
docker exec -e KEY=val <c> <cmd> | Run a command with extra env var |
docker cp <c>:/path ./local | Copy file from container to host |
docker cp ./local <c>:/path | Copy file from host to container |
docker attach <c> | Attach to the main process |
docker inspect <c> | Full JSON metadata dump |
docker top <c> | View running processes |
Key Takeaways
docker exec -it <container> bashis a command for opening a shell inside a running container.- Use
-u rootto exec as root even if the container normally runs as a non-root user docker cpcopies files to and from containers without needing a shell or volume, and works on stopped containers too- Avoid
docker attachfor debugging because pressingCtrl+Cwill stop your container; useCtrl+P Ctrl+Qto detach safely docker inspectis your best tool for understanding a container's full configuration without entering itdocker topshows running processes inside a container directly from the host
Frequently Asked Questions
What's the difference between docker exec and docker attach?
docker exec creates a brand new process inside the container and your container keeps running normally when you exit. docker attach connects you to the container's main process (PID 1), so exiting or pressing Ctrl+C can stop the entire container.
What if bash isn't available in my container?
Many lightweight images (especially Alpine-based ones) don't include bash. Try sh instead: docker exec -it my-container sh. If even sh isn't available, your image is likely a distroless image with no shell at all, and in that case, copy files out with docker cp or add a debug sidecar container.
Can I docker cp from a stopped container?
Yes. docker cp works even when the container isn't running, which makes it useful for recovering logs or files from a crashed container.
How do I exit a container shell without stopping it?
Type exit or press Ctrl+D. Since you opened the shell with docker exec, exiting only closes that shell process; the container and its main process keep running.
Can I run multiple docker exec sessions at the same time?
Yes. Each docker exec call creates an independent process. You can have multiple terminal windows all exec'd into the same container simultaneously.
Why can't I see some files when I exec into my container?
The container only has access to its own filesystem layer. Files that live on your host (outside of mounted volumes) won't appear inside the container. If you need to get a file in, use docker cp or mount a volume when starting the container.