How to use docker compose exec command to interact with services

DockerDockerBeginner
Practice Now

Introduction

In this lab, you will learn how to effectively use the docker compose exec command to interact with running services. You will explore executing commands within a service container, running commands in detached mode, executing commands as a different user, and running commands with a specific working directory. This hands-on experience will equip you with essential skills for debugging and managing your Dockerized applications.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL docker(("Docker")) -.-> docker/ContainerOperationsGroup(["Container Operations"]) docker(("Docker")) -.-> docker/ImageOperationsGroup(["Image Operations"]) docker/ContainerOperationsGroup -.-> docker/run("Run a Container") docker/ContainerOperationsGroup -.-> docker/exec("Execute Command in Container") docker/ImageOperationsGroup -.-> docker/pull("Pull Image from Repository") subgraph Lab Skills docker/run -.-> lab-555079{{"How to use docker compose exec command to interact with services"}} docker/exec -.-> lab-555079{{"How to use docker compose exec command to interact with services"}} docker/pull -.-> lab-555079{{"How to use docker compose exec command to interact with services"}} end

Execute a command in a running service container

In this step, you will learn how to execute a command inside a running Docker container. This is a very useful technique for debugging or interacting with a service running within a container without needing to stop and restart it.

First, let's pull a simple Nginx image to use for this demonstration. We will use the nginx:alpine image as it is small and quick to download.

docker pull nginx:alpine

You should see output indicating that the image is being pulled and extracted.

Next, we will run this Nginx image in detached mode, which means the container will run in the background and not tie up your terminal. We will also give it a name so it's easier to refer to later.

docker run -d --name my-nginx nginx:alpine

The output will be the container ID of the newly created and running container.

Now that the container is running, we can execute a command inside it using the docker exec command. The basic syntax is docker exec [options] container command [args...]. Let's try to list the files in the root directory of the container.

docker exec my-nginx ls /

You should see a list of directories and files present in the root filesystem of the Nginx container, such as bin, etc, usr, etc. This confirms that you have successfully executed a command inside the running container.

Let's try another command. We can check the version of Nginx running inside the container.

docker exec my-nginx nginx -v

The output will show the version of Nginx installed in the container, for example, nginx version: nginx/1.24.0.

This demonstrates how you can interact with a running container and execute arbitrary commands within its environment.

Run a command in detached mode

In the previous step, we ran a container in detached mode using the -d flag. This is a common practice when you want a container to run in the background without occupying your terminal. In this step, we will further explore running commands in detached mode, specifically using docker exec.

While docker exec is typically used for interactive sessions or running short commands in a running container, you can also run a command in detached mode using the -d flag with docker exec. This is useful for starting a background process within an already running container.

Let's use the my-nginx container we started in the previous step. We will execute a simple command in detached mode. For example, let's run a command that writes the current date and time to a file inside the container every 5 seconds.

docker exec -d my-nginx sh -c 'while true; do date >> /usr/share/nginx/html/date.txt; sleep 5; done'

In this command:

  • docker exec -d my-nginx: Executes the following command in detached mode within the my-nginx container.
  • sh -c '...': Runs the subsequent command string using the sh shell.
  • while true; do date >> /usr/share/nginx/html/date.txt; sleep 5; done: This is the command being executed. It's a simple loop that continuously appends the current date and time to the file /usr/share/nginx/html/date.txt and then waits for 5 seconds before repeating.

After running the command, you will see the container ID printed to your terminal, indicating that the command has been started in the background within the container.

To verify that the command is running and writing to the file, we can execute another command to view the content of the date.txt file. Since the command is running in the background, it might take a few seconds for the file to be created and populated.

docker exec my-nginx cat /usr/share/nginx/html/date.txt

You should see the date and time being printed in the output, and if you run the cat command again after a few seconds, you should see new entries added to the file. This confirms that the background process started with docker exec -d is running as expected.

Execute a command as a different user

In this step, you will learn how to execute a command inside a running container as a specific user. By default, docker exec runs commands as the root user inside the container, but you can specify a different user using the -u or --user flag. This is important for security and adhering to the principle of least privilege.

Let's continue using the my-nginx container. First, let's see what user the ls / command runs as by default.

docker exec my-nginx whoami

The output will likely be root, as this is the default user for docker exec.

Now, let's try to execute a command as a different user. The Nginx image typically runs the Nginx process as a non-root user, often named nginx. Let's try to execute the whoami command as the nginx user.

docker exec -u nginx my-nginx whoami

You should see the output nginx, confirming that the command was executed as the nginx user.

You can also specify a user ID (UID) instead of a username. To find the UID of the nginx user inside the container, we can look at the /etc/passwd file.

docker exec my-nginx cat /etc/passwd | grep nginx

The output will show the entry for the nginx user, including their UID and GID (Group ID). For example, it might look something like nginx:x:101:101:nginx user,,,:/nonexistent:/bin/false. In this example, the UID is 101.

Now, let's execute the whoami command using the UID. Replace 101 with the actual UID you found in the previous step if it's different.

docker exec -u 101 my-nginx whoami

The output should again be nginx, demonstrating that you can use either the username or the UID to specify the user for docker exec.

Executing commands as a non-root user is a good security practice, especially when interacting with sensitive files or performing operations that don't require root privileges.

Run a command with a specific working directory

In this final step, you will learn how to execute a command inside a running container with a specific working directory. By default, docker exec runs commands in the working directory defined in the container image's Dockerfile (often /). However, you can change this using the -w or --workdir flag. This is useful when you need to execute commands relative to a specific path within the container's filesystem.

Let's continue using the my-nginx container. First, let's see the default working directory when we execute a command without specifying one. We can use the pwd command (print working directory) for this.

docker exec my-nginx pwd

The output will likely be /, which is the root directory.

Now, let's execute a command in a different working directory. The Nginx container has a directory /usr/share/nginx/html where the web server serves files from. Let's change the working directory to this path and then list the files within it.

docker exec -w /usr/share/nginx/html my-nginx ls

In this command:

  • docker exec -w /usr/share/nginx/html my-nginx: Executes the following command within the my-nginx container, setting the working directory to /usr/share/nginx/html.
  • ls: The command to execute, which lists the files in the current working directory.

You should see the files present in the /usr/share/nginx/html directory, such as index.html and date.txt (which we created in a previous step).

Let's try another example. We can create a new directory within /usr/share/nginx/html and then change our working directory to the newly created directory before executing a command.

docker exec my-nginx mkdir /usr/share/nginx/html/new_dir
docker exec -w /usr/share/nginx/html/new_dir my-nginx pwd

The first command creates a directory named new_dir inside /usr/share/nginx/html. The second command then changes the working directory to /usr/share/nginx/html/new_dir and prints the current working directory.

The output of the second command should be /usr/share/nginx/html/new_dir, confirming that the working directory was successfully changed for the execution of the pwd command.

Using the -w flag with docker exec allows you to execute commands in the context of a specific directory within the container, which is very helpful for navigating and interacting with the container's filesystem more efficiently.

Summary

In this lab, you learned how to use the docker exec command to interact with a running Docker container. You practiced executing commands inside a container, specifically listing files and checking the Nginx version, demonstrating the ability to debug and interact with services without stopping them.

You also briefly touched upon running containers in detached mode using the -d flag, a fundamental concept for background container execution. While the subsequent steps were not fully detailed, the initial steps provided a solid foundation for understanding how to execute commands within a running container environment.