Introduction
Troubleshooting Docker workloads often requires you to run a command in the container. Or run multiple commands in a Docker container. For example you may need to run a command and pipe the output to another command for processing. Or you might want to run multiple commands sequentially. How do you do that? Well luckily it is not too hard. But there are some things to be aware of.
How to run a command in a Docker container
Most docker containers are light weight by design and only run a single service. As a result you can’t just SSH into the container like you can with a server or VM. So how do you run a command in a Docker container? With the docker exec
command. Note that we will start all docker
commands with the sudo
command. Running docker commands requires read/write access to the docker daemon’s socket, you can use sudo or add your user to the docker group.
For example to run the directory listing command ls
inside a running container you can do the following:
sudo docker exec $container ls
Where $container
is the id of name of the container. For example if my container name is epic_driscoll
I can run:
sudo docker exec epic_driscoll ls
Using a container with the id of 2a5e32051da8
:
sudo docker exec 2a5e32051da8 ls
On my docker host I have a single docker container running. Here is the output of docker ps
which shows the running containers:
ubuntu@dev-linuxhit-com:/home/ubuntu# sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2a5e32051da8 nginx "/docker-entrypoint.…" 4 hours ago Up 4 hours 80/tcp epic_driscoll
The container ID is 2a5e32051da8 and the image running is a stock NGINX image from Dockerhub. When I run ls
via docker exec
on this host I get the following output show the contents of the containers root directory:
root@dev-linuxhit-com:/home/ubuntu# docker exec 2a5e32051da8 ls
bin
boot
dev
docker-entrypoint.d
docker-entrypoint.sh
etc
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
Run multiple commands in a Docker container
How about running multiple commands? For example, what if I want a directory listing and to create a new file using the touch
command? I can run two docker execs, docker exec $container ls
and docker exec $container touch newfile.txt
. But there is a more efficient way to do it. We can run both commands in a single docker exec
by spawning a shell in the docker container and passing a string with our commands.
sudo docker exec -it $container bash -c "ls -l; touch newfile.txt"
Notice we added quite a bit to this command. Let’s dive into that. First we added -it
, these two flags tell docker to take STDIN from our terminal and also allocate a pseudo TTY. Essentially this makes command session behave like a terminal. After the $container
we changed to the command to run a bash shell and pass our commands in via bash’s -c flag: bash -c "ls -l; touch newfile.txt"
. And we encapsulate our commands in quotes and put a semicolon in between them. Putting them quotes prevents them from getting interpreted by our current shell and the semi-colon tells the container that we are starting a new command.
Important note: In a minimal linux container you might not have the bash shell installed. If that is the case you try replacing bash with /bin/sh
:
sudo docker exec -it $container /bin/bash -c "ls -l; touch newfile.txt"
To prove our touch command works let’s add a third command. Another ls
so we can see if our file was created:
ubuntu@dev-linuxhit-com:~$ sudo docker exec -it 2a5e32051da8 bash -c "ls; touch newfile.txt; ls "
bin docker-entrypoint.d home media proc sbin tmp
boot docker-entrypoint.sh lib mnt root srv usr
dev etc lib64 opt run sys var
bin docker-entrypoint.d home media opt run sys var
boot docker-entrypoint.sh lib mnt proc sbin tmp
dev etc lib64 newfile.txt root srv usr
Our file was created. Bravo!
Learn more about Docker
Docker is a powerful tool but there can be a learning curve if you are new to containers. Docker up and Running is a great book to get you familiar with the Docker tool chain so you can reap the productivity benefits of Docker.
Conclusion
You are now ready to string together commands and run them in your container. As I mentioned earlier, running commands in containers is great for troubleshooting. However its important to design and build your containers with the idea that you never login to them. Containers are best when ephemeral, easy destroyed and recreated.