Docker exec is a useful way to debug container problems and perform one-off maintenance tasks. In this article, we’ll go in-depth on these scenarios and show how to use docker exec with common options. Let’s get started.
We will cover:
docker exec
is a Docker CLI feature that runs a command inside a running container. It launches an additional process that’s independent of the main process running in the container.
You must identify the container by ID or name, then specify the command to invoke:
$ docker exec <container-id-or-name> <command>
Your <command>
can be any command that exists in the container. To pass arguments or flags, simply write them after the command’s name:
$ docker exec <container-id-or-name> echo -n demo
The command you use must be a valid executable within the container’s filesystem. It will be interpreted relative to the container’s default working directory. You must specify the exact path to the command if it’s situated in a different directory that’s outside the container’s PATH
.
Check out other Docker commands in the Docker CLI cheat sheet.
Docker containers usually run a single long-lived process, typically a server application. But sometimes, you might need to run another command inside a container. This is where docker exec
steps in.
One of the docker exec
‘s best use cases concerns debugging and troubleshooting container problems. The command allows you to easily inspect a container filesystem and make any changes you require, without having to launch a new container or refer to the source Dockerfile
.
Here are a few more situations where you could use docker exec
:
- Run maintenance commands: Some container images include additional utility commands to handle maintenance operations. For example, the official MySQL image bundles the mysqldump backup utility, but you’ll need to use
docker exec
to start it. - Run a one-off task in a container:
docker exec
also facilitates other types of one-off tasks, such as viewing log files that are stored within containers. You can also use the command in development scenarios, such as to apply changes to an application’s source code without having to rebuild its container image. - Inspect a container’s filesystem:
docker exec
allows you to directly interact with the target container’s filesystem. You can learn how the image is assembled, identify what components are included, and adjust configuration files. - Test container network connectivity: It’s not always obvious why a container is having network connectivity issues.
docker exec
lets you investigate these situations by running commands likecurl
andwget
to test which network endpoints the container can reach.
While docker exec
can be useful in these scenarios, it’s important to avoid relying on the command too often. It’s best reserved for debugging and troubleshooting problems when you’ve exhausted all other options.
Starting additional processes in a container risks breaking containerization principles, as containers should usually run one service each. Using docker exec
to apply “permanent” changes to a container—such as by installing extra packages—will introduce discrepancies compared to the Dockerfile, causing configuration drift. Therefore, docker exec
must be used with caution: starting another container that reuses the same volumes and networks is often a better choice for running maintenance commands, for example, as this won’t cause any side effects in your existing container’s configuration.
Now you’re aware of the use cases and pitfalls of docker exec
, let’s see how to actually use it to run commands in your own containers.
To begin with, you should create a new container to follow along with this guide. We’ll call our container demo
and refer to it by name in the following steps.
$ docker run -d --name demo nginx:latest
752e081c8ebf6abdb7b3f4832d159a4cdc80ad7cd1033d139d80e737883d46ba
docker ps
should now show that the container is up:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
752e081c8ebf nginx:latest "/docker-entrypoint.…" 32 seconds ago Up 30 seconds 80/tcp demo
The container is now running its default command, which in this case is a script that starts the NGINX web server.
Now you can use docker exec
to start another command in the container. The following example executes ls /
to list the contents of the container’s filesystem root:
$ docker exec demo ls /
bin
boot
dev
...
The docker exec
syntax means “run the ls /
command in the container called demo
“.
The output from the command that’s run in the container is displayed in your terminal.
Interactive commands
docker exec
can be used to launch an interactive shell session inside your container. For this to work correctly, two optional flags must be used:
-i
(--interactive
): Attaches your terminal’s standard input (STDIN) stream to the container, allowing it to receive input.-t
(--tty
): Allocates a pseudo-TTY terminal to the session.
Then you should use the shell’s name (such as sh
or bash
) as your docker exec
command:
$ docker exec -it demo bash
root@752e081c8ebf:/#
Now you have a shell running inside your container, ready to run additional commands:
root@752e081c8ebf:/# ls
bin boot dev ...
You can end the session by running the exit
command inside the container’s shell.
Docker exec options
The Docker exec command supports a few other options too. Here’s how to use them.
1. Detach from the container command
docker exec
automatically attaches your terminal to the command that’s run in the container. This lets you monitor the command’s output in your existing terminal session. However, if you’re running a time-consuming command or launching another background service, you might prefer to detach from it using the -d
(--detach
) flag:
$ docker exec -d demo /my-process
The docker exec
command will appear to complete immediately, but the process started in the container will keep running until it naturally exits.
2. Set environment variables
docker exec
allows you to set additional environment variables inside the container that will apply when your command is run. Similarly to other Docker commands, two different flags are supported:
--env
: Sets a specific environment variable inkey=value
format.--env-file
: Injects all thekey=value
environment variable pairs found in a named file.
You can repeat each of these flags to set multiple variables.
This demo shows how the environment variables you define are successfully set inside the container:
$ docker exec --env key=value --env foo=bar demo env
...
key=value
foo=bar
3. Set the user
Container processes created by docker exec
run as the container’s default user. This is normally root
unless you changed it in your Dockerfile or when starting the container with docker run
.
You can run your command as a different user by setting the -u
(--user
) flag. This supports user_name:group_name
and uid:gid
syntax. The group portion is optional in both cases.
$ docker exec --user 1234:100 demo whoami
uid=1234 gid=100(users) groups=100(users)
Running all commands as a non-root user is a best practice to improve Docker security.
4. Change the container’s working drectory
You can change the effective working directory inside the container by setting the --workdir
flag. The path to your command’s executable will then be resolved relative to the specified directory instead of the container’s default working directory.
$ docker exec --workdir /app/bin demo demo-cli
Now you’ve learned the options for using docker exec
, here are a few tips and gotchas to ensure your commands run smoothly.
How to run multiple commands in a container with docker exec
Each docker exec
invocation runs a single command in your container. Directly chaining commands, as in the following example, won’t produce the desired result:
$ docker exec demo echo "Hello" && ls
The echo "Hello"
command will run in the container, but the &&
will be interpreted by your system’s shell. As a result, the ls
command will run on your host, not in the container.
If you need to chain multiple commands together, you can repeat docker exec
:
$ docker exec demo echo "Hello" && docker exec demo echo ls
Alternatively, you can use docker exec
to launch a shell process in your container, then pass through your entire command chain as a quoted string:
$ docker exec demo bash -c "echo 'Hello' && ls"
Check your command syntax
The syntax of both your docker exec
command and the command you pass to your container must be error-free to ensure correct operation. Notably, the flags you pass to docker exec
must come before the container ID/name and your command. Otherwise, they’ll be interpreted as part of the command to run in the container.
- Incorrect:
docker exec demo bash -it
- Correct:
docker exec -it demo bash
Ensure your container is running
docker exec
only works with containers that are actively running. You’ll see an error message similar to the following if you try to run a command in a a stopped or paused container:
Error response from daemon: Container is not running
To solve this problem, start or unpause the container (using the docker start
or docker unpause
command, respectively), then repeat the docker exec
command.
Use a non-root user
You should avoid running commands as root unless absolutely necessary. Otherwise, the command you run in the container could potentially perform sensitive actions on your host, if it’s been compromised or replaced with a malicious version. Setting the --user
flag to ensure your new process runs as a specific user helps to lower your risk.
$ docker exec --user 1000 demo ls
Here are four common docker exec
errors and how you can solve them.
1. Error: No such container
This means Docker couldn’t run your command because you’ve referenced an invalid container. You should check the container name for typos. If it’s correct, then make sure you’ve already started the container using docker run
.
2. Error response from daemon: Container is not running
This error occurs when you try to run a command in a stopped container. Use docker start
to restart the container, then repeat your
docker exec
command.
3. Error response from daemon: Container is paused
This error is similar to the previous one but it happens when you interact with a paused container. You must docker unpause
the container, then repeat the docker exec
command.
4. OCI runtime exec failed: unable to start container process: executable file not found
An error message similar to this one means docker exec
failed to start the command you requested in the container. You should look for typos in the executable name you specified and check that it exists within the container’s filesystem.
A common source of confusion about docker exec
is how it differs from docker run
. These commands both ultimately run commands in containers, but they have different purposes and effects.
docker run
creates a new container and optionally sets the initial command to run inside it. When no command is specified, then the default given by the container image’s Dockerfile will be used.
docker exec
is used for running additional commands inside existing containers. The original command stays running and a new process is launched in the container.
Another related command to docker exec
is docker attach
. This attaches your terminal to a running container process, allowing you to monitor its output and provide input when required. It’s not possible to attach to commands that have already completed their execution and exited.
This article has explored docker exec
, a Docker CLI command that’s used to run new commands in existing containers. It’s useful for debugging, troubleshooting, and learning purposes; it also allows you to run one-off tasks inside containers, such as creating a backup using a utility provided by the container image.
It’s unlikely that you’ll use docker exec
often in production. Manual interactions with containers are best avoided to prevent consistency issues and maintain automation. However, understanding how to use the command will make it easier to diagnose problems with your containers.
We encourage you also to explore how Spacelift offers full flexibility when it comes to customizing your workflow. You have the possibility of bringing your own Docker image and using it as a runner to speed up the deployments that leverage third party tools. Spacelift’s official runner image can be found here.
The Most Flexible CI/CD Automation Tool
Spacelift is an alternative to using homegrown solutions on top of a generic CI. It helps overcome common state management issues and adds several must-have capabilities for infrastructure management.