Run Commands Inside a Running Docker Container with docker exec
You will use docker exec to inspect a running container, run a command in a known directory, and open a temporary shell when a shell is actually available. The command adds a process to an existing container. It does not create a new container and it does not change the image.
The route
Jump straight to the step you need, or tick off Done means at the end.
Before you start
You need Docker access and the name or ID of a running container. On this machine the installed package is docker-ce-cli 5:29.8.1-1~ubuntu.24.04~noble, and the client reports Docker 29.8.1. Allow about five minutes for the basic checks. A shell session or troubleshooting work may take longer.
Most examples are ordinary Docker commands. They can still expose application data or change state inside the container, so check the target name before pressing Enter. You may need sudo if your account cannot access the Docker daemon. That is host-level access to Docker, not a requirement of docker exec itself.
Checkpoint: confirm the target is running
- List running containers and identify the exact name or ID.
docker ps --format 'table {{.ID}}\t{{.Image}}\t{{.Names}}\t{{.Status}}'
Expected output has one row per running container, for example:
CONTAINER ID IMAGE NAMES STATUS
abc123def456 alpine:3.20 demo-shell Up 2 minutes
Use demo-shell below only if that is your container name. A stopped container is not a valid target for docker exec. A paused container also fails until it is unpaused. If the target is absent, stop here and check the spelling with docker ps -a; do not start or remove a container just to make an example fit.
Run one command
- Pass the container followed by an executable and its arguments.
docker exec demo-shell pwd
The command runs in the container's default working directory. Its output is returned to your terminal, such as:
/
The syntax is docker exec [OPTIONS] CONTAINER COMMAND [ARG...]. The command must be an executable. Docker does not interpret a quoted string as a shell command, so this is a common trap:
# Do not use this when you mean shell syntax.
docker exec demo-shell "echo one && echo two"
For shell operators, invoke a shell explicitly. The shell and its syntax must exist in the image:
docker exec demo-shell sh -c 'echo one && echo two'
Use a direct executable where possible. It avoids depending on a shell and makes argument boundaries clear.
Checkpoint: inspect without opening a shell
- Read a small, known path or query the process environment.
docker exec demo-shell env | sed -n '1,12p'
This prints the environment inherited by the process started when the container was created. It may contain sensitive values. Treat terminal output and saved logs accordingly. The command does not alter the container, but commands such as rm, database clients, package managers or application administration tools can.
Open an interactive shell
- Allocate a terminal and keep standard input open for the duration of the session.
docker exec --interactive --tty demo-shell sh
The short form is docker exec -it demo-shell sh. Exit with exit or press Ctrl-D. This ends the extra shell process; it does not stop the container's primary process. Images often omit sh, and some omit both sh and bash. Check the image documentation or run a known executable instead of guessing.
Do not confuse this with entering the container's original process. docker exec starts a new process while the container's PID 1 is running. The extra process is not restarted automatically if the container restarts.
Set a temporary environment value or directory
- Override the environment for one exec process when a command needs a value.
docker exec --env MODE=diagnostic demo-shell env | grep '^MODE='
Expected output is:
MODE=diagnostic
The value applies to that process and its children. It is not added to the container configuration and is not available to other processes already running in the container. For several values, repeat --env or use --env-file. Keep secrets out of shell history; use an environment file with suitable permissions only when the receiving program genuinely requires it.
- Choose an existing working directory inside the container.
docker exec --workdir /tmp demo-shell pwd
Expected output is /tmp. With -w, Docker starts the process there. The directory must exist in the container or the command fails. Without this option, Docker uses the working directory configured for the container, which may not be /.
Background work and privilege boundaries
Use detached mode only when you do not need command output in the terminal:
docker exec --detach demo-shell touch /tmp/exec-check
That changes the container filesystem. Verify it with docker exec demo-shell test -f /tmp/exec-check and remove the test file when it is no longer needed:
docker exec demo-shell rm /tmp/exec-check
Warning: --privileged gives the exec process extended privileges inside the container. Treat it as a security-sensitive exception, not as a routine fix for a failed command. It does not turn the process into an unrestricted host administrator, but a privileged container process can weaken isolation and may access more devices or kernel interfaces. Prefer the least privilege that works, and record who authorised any use.
Common failures
- No such container: re-run
docker ps -aand copy the exact name or ID. - Container is not running: inspect its logs and intended lifecycle before starting it. Starting a service can have operational consequences.
- Executable not found: the program is absent or not on the container's
PATH. Use its absolute path or a tool supplied by the image. - Interactive output is broken: use
-itfor a terminal session, or omit both options for a non-interactive command. Do not use-tin scripts that need clean, line-oriented output. - Permission denied: the command is running as the container's configured user. Use
--useronly when you know the required UID, name and group; changing it can bypass application-level expectations.
Done means
- You confirmed the target container is running.
- You used an explicit executable, or explicitly invoked a shell for shell syntax.
- You verified the working directory and any temporary environment override.
- You removed any test file or other temporary state you created.
- You avoided
--privilegedunless its security impact was understood and authorised.