Linuxhit

Run multiple commands in Docker

Docker Logo

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.

References