Maintenance

Site is under maintenance — quizzes are still available.

Go to quizzes

Execute Commands in Running Containers

Learn how to run commands inside active Docker containers without stopping them. This lesson covers `docker exec` with hands-on examples, troubleshooting tips, and best practices for debugging and managing running processes.

Focus: execute commands in running containers

Sponsored

Picture this: you've spun up a container to test a new API endpoint, but the logs show a puzzling 500 error. Your first instinct might be to kill the container and restart with a debug flag — but that wastes time and tears down your running state. Wouldn't it be better to just pop in and inspect what's happening right now? That's exactly what docker exec lets you do: execute commands in a running container without interrupting it, like leaning into a car window at a stoplight instead of making the driver pull over.

The problem this lesson solves

Containers are ephemeral — they start, run, and stop. But in real-world development, you rarely get everything right on the first try. A config file is missing, an environment variable isn't set, or a background process crashes unexpectedly. Stopping and restarting the container each time you want to test a fix is slow and disrupts your flow. Worse, if the container holds state (like an in-memory cache or an active database), restarting it destroys that state.

You need a way to interact with a running container* without killing it. The docker exec command gives you that power: it attaches to the container's namespaces (process, network, mount) and lets you run a new process inside it. This is essential for: - Debugging live issues in production-like environments. - Running ad-hoc commands (e.g., checking disk space, reading logs). - Injecting temporary changes to test behavior.

Core concept / mental model

Think of docker exec as a remote shell into a machine that already exists. When you run docker exec, you're not starting a new container — you're opening a channel to an existing one. The command executes inside the container's isolated world, with the same filesystem, environment variables, and network stack.

What exec does under the hood

When you run docker exec -it <container> bash, Docker: 1. Looks up the container by name or ID. 2. Verifies the container is running (exit if stopped). 3. Allocates a pseudo-TTY (terminal) if -t is passed. 4. Attaches STDIN (-i) to the container's STDIN so you can type. 5. Spawns the specified command (e.g., /bin/bash) as a new process inside the container's PID namespace. 6. Streams STDIN, STDOUT, and STDERR back to your host terminal.

Pro tip: The -it flags are your best friends. -i keeps STDIN open (so you can send input), -t allocates a pseudo-TTY (so you get a proper shell prompt). Omitting them is like muzzling yourself — you'll get one-shot output but no interactive session.

How it works step by step

Let's walk through the anatomy of a docker exec command. The general syntax is:

docker exec [OPTIONS] CONTAINER COMMAND [ARG...]

Step 1: Identify your container. You need the container name or ID. Use docker ps to list running containers.

Step 2: Choose your mode — interactive or detached. - Interactive (shell): docker exec -it <container> bash — opens a live shell. - Detached (one-shot): docker exec <container> ls /app — runs a command and returns output, then exits.

Step 3: Run with the right flags. Common options:

Flag Meaning Use case
-i Interactive (STDIN) Combine with -t for a shell
-t Allocate pseudo-TTY Essential for proper terminal behavior
-d Detached (run in background) For long-running processes (less common)
-e Set environment variable Override or inject vars on the fly
-w Working directory Start in a specific directory

Step 4: Inspect output. The command's stdout/stderr stream back to your terminal. If the process exits with a non-zero code, Bash displays it.

Hands-on walkthrough

Let's get our hands dirty. Start by pulling a simple Nginx image and running it in the background:

docker run -d --name my-nginx -p 8080:80 nginx:alpine

Expected output: A long container ID (e.g., a1b2c3d4e5f6...).

Example 1: Open an interactive shell

docker exec -it my-nginx /bin/sh

Now you're inside the container. Try:

/ # ls -la /etc/nginx
/ # cat /etc/nginx/conf.d/default.conf
/ # exit

Pro tip: Alpine-based images use sh, not bash. Use /bin/sh for maximum compatibility.

Example 2: Run a one-shot command

No shell required. Run a single diagnostic command from the host:

docker exec my-nginx cat /etc/nginx/nginx.conf

Expected output: The contents of the Nginx config file printed to your terminal.

Example 3: Write a file into the running container

You can even create files on the fly. This is great for hotfixes:

echo "Hello from host" | docker exec -i my-nginx tee /usr/share/nginx/html/test.txt

Then verify:

curl http://localhost:8080/test.txt
# Output: Hello from host

Example 4: Run a background process

Suppose you want to start a log tail inside the container without blocking your terminal:

docker exec -d my-nginx touch /var/log/nginx/custom.log
docker exec -d my-nginx tail -f /var/log/nginx/access.log

This runs the command in the background. Use docker logs my-nginx to check Nginx's own output.

Compare options / when to choose what

Not every situation calls for docker exec. Here's a quick comparison with alternatives:

Method Use case Pros Cons
docker exec -it Interactive debug, shell access Full control, state preserved Requires the container to be running
docker run --rm -it with network Point-and-shoot debugging Clean, isolated No access to existing processes
docker attach Reattach to a container's main process See live streaming output Can risk killing the main process if you Ctrl+C
docker cp Copy files into/out of container Quick file transfer No command execution

Choose docker exec when: - You need to inspect or modify an already running container. - You want to add a temporary diagnostic tool (e.g., apt-get install curl). - You're debugging a service that must stay up.

Avoid docker exec when: - You just want to check logs — use docker logs instead. - You need to run a one-time test in a fresh environment — use docker run. - You want to persist changes — use a Dockerfile.

Troubleshooting & edge cases

Problem 1: "Container is not running"

Error response from daemon: Container <id> is not running

Cause: The container exited or was stopped. docker exec only works on running containers.

Fix: Start the container first with docker start <container>, or use docker run --rm -it --entrypoint sh <image> to spin up a new interactive container.

Problem 2: Command not found (e.g., bash)

docker exec my-container bash
docker exec: "bash" executable file not found in $PATH

Cause: The image is minimal (Alpine, Distroless) and doesn't include Bash.

Fix: Use sh, ash, or ls instead. Check the image documentation.

Problem 3: Detached exec runs forever

If you use docker exec -d with a command like tail -f, it never exits. That's fine — it'll keep running in the background. But if you need to stop it, you'll have to docker stop the container (which stops everything) or kill the process from inside.

Problem 4: Forgetting -i for interactive input

Running docker exec my-container sh (without -i) opens a shell but closes STDIN immediately. You can't type any commands. You must use -it.

What you learned & what's next

You now know how to execute commands in running containers using docker exec. You can: - Open an interactive shell with docker exec -it <container> sh. - Run one-shot commands like docker exec <container> cat /etc/hosts. - Use flags like -d, -w, -e for advanced scenarios. - Troubleshoot common pitfalls like missing commands or stopped containers.

This skill is the gateway to debugging live containers. In the next lesson, you'll learn how to copy files between your host and containers using docker cp — perfect for hot-patching config files or extracting logs. You'll combine docker exec and docker cp to become a true container troubleshooter.

Practice recap: Start a Redis container (docker run -d --name my-redis redis:alpine). Use docker exec -it to open a shell and run redis-cli ping. Then run a one-shot docker exec my-redis redis-cli INFO memory to see memory stats. Finally, try docker exec -d my-redis redis-cli SET test "hello" to set a key in the background.

Practice recap

Practice recap: Start a Redis container (docker run -d --name my-redis redis:alpine). Use docker exec -it to open a shell and run redis-cli ping. Then run a one-shot docker exec my-redis redis-cli INFO memory to see memory stats. Finally, try docker exec -d my-redis redis-cli SET test "hello" to set a key in the background.

Common mistakes

  • Forgetting -i or -t flags when opening a shell — you'll get a non-interactive one-shot command that immediately exits.
  • Trying docker exec on a stopped container — always verify the container is running with docker ps first.
  • Assuming bash is available in minimal images — use sh or ash for Alpine-based containers.
  • Using docker exec to change configuration permanently — changes are lost on container restart; edit the Dockerfile instead.

Variations

  1. Use docker exec -u <user> to run commands as a specific user (e.g., www-data for web apps).
  2. Use docker exec -w /somedir to start in a working directory without cd-ing.
  3. Use docker exec -e FOO=bar to inject temporary environment variables for a single command.

Real-world use cases

  • Debugging a misconfigured Nginx container by inspecting the config files live.
  • Checking the health of a PostgreSQL database by running psql inside the container.
  • Installing curl on-the-fly to test an internal API endpoint during development.

Key takeaways

  • docker exec runs commands inside a running container without stopping it.
  • Use -it for an interactive shell session; omit flags for one-shot commands.
  • The container must be running — check with docker ps before exec-ing.
  • Minimal images like Alpine use sh instead of bash — know your base image.
  • Changes made via docker exec are temporary — lost on container restart.
  • Always consider docker logs and docker run as alternatives for specific tasks.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.