Run a command without starting linked services
In this step, we will learn how to run a command in a Docker container that is part of a multi-container application, without starting the other linked services. This is particularly useful for running database migrations, setup scripts, or debugging commands in one service without needing to bring up the entire application stack.
While Docker Compose is the standard tool for managing multi-container applications and has features for running one-off commands on specific services, we will demonstrate the underlying Docker concepts here. Since Docker Compose is not pre-installed in this environment, we will focus on using the docker run
command with networking.
Let's simulate a simple scenario with two containers: a web application and a database. We'll use a generic ubuntu
image to represent our web application and a postgres
image for the database.
First, pull the postgres
image:
docker pull postgres:latest
You should see output indicating the image is being pulled.
Using default tag: latest
latest: Pulling from library/postgres
...
Status: Downloaded newer image for postgres:latest
docker.io/library/postgres:latest
Now, let's create a Docker network so our containers can communicate with each other by name.
docker network create my-app-network
You should see the network ID printed.
<network_id>
Next, let's run the postgres
container and connect it to our network. We'll also set a password for the PostgreSQL user.
docker run -d --network my-app-network --name my-database -e POSTGRES_PASSWORD=mypassword postgres
You should see the container ID printed, indicating the database container is running in the background.
<container_id>
Now, imagine our "web application" container needs to run a command that interacts with the database, like a database migration script. Normally, if we were using Docker Compose, we could run a command on the web service and Docker Compose would handle the network setup and linking.
Using just docker run
, if we were to run the web application container and it tried to connect to my-database
, it would typically need to be on the same network.
Let's run a command in an ubuntu
container connected to the same network, simulating a command that might interact with the database. We'll just try to ping the database container by its name (my-database
).
docker run --network my-app-network ubuntu ping -c 4 my-database
This command will:
- Create a new container from the
ubuntu
image.
- Connect it to the
my-app-network
.
- Run the
ping -c 4 my-database
command inside the container.
Because the ubuntu
container is on the same network as the my-database
container, it can resolve the name my-database
to the database container's IP address and ping it.
You should see output showing the ping requests and responses:
PING my-database (172.18.0.2) 56(84) bytes of data.
64 bytes from my-database.my-app-network (172.18.0.2): icmp_seq=1 ttl=64 time=0.050 ms
64 bytes from my-database.my-app-network (172.18.0.2): icmp_seq=2 ttl=64 time=0.054 ms
64 bytes from my-database.my-app-network (172.18.0.2): icmp_seq=3 ttl=64 time=0.054 ms
64 bytes from my-database.my-app-network (172.18.0.2): icmp_seq=4 ttl=64 time=0.054 ms
--- my-database ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3060ms
rtt min/avg/max/mdev = 0.050/0.053/0.054/0.001 ms
This demonstrates that you can run a one-off command in a container and have it interact with other containers on the same network, without needing to start the default service of the container running the command (in this case, the ubuntu
container doesn't have a typical "service"). The key is connecting the container running the command to the same network as the services it needs to interact with.
Finally, let's clean up the running database container and the network.
docker stop my-database
my-database
docker rm my-database
my-database
docker network rm my-app-network
my-app-network