1. Overview

In this tutorial, we’ll learn how to run multiple Docker containers with an interactive shell. First, we’ll run a Docker container using the simple docker run command. Later, we’ll run the same Docker container with the docker-compose command.

2. Docker and Docker Compose

Docker containers allow developers to package applications that work seamlessly across different environments. In fact, a typical deployment of a web application in a production environment may require several services:

  • database server
  • load balancing
  • webserver

In such situations, Docker Compose is a very handy tool.

Docker Compose is mainly used to run multiple containers as a single service while maintaining a smooth connection between the containers.

3. Understanding Docker Compose

To run a Docker container using the docker-compose command, we need to add all the configurations to the single docker-compose.yml configuration file. Importantly, one of the key benefits of using docker-compose over the normal docker run command is the configuration consolidation in a single file, which both machines and humans can read.

Let’s create a simple docker-compose.yml to show how to run Docker containers using the docker-compose up command:

version: "3"
services:
 server:
   image: tomcat:jre11-openjdk
   ports:
     - 8080:8080

Here, we used tomcat as the base image and exposed port 8080 on the host machine. To see it in action, let’s build and run this image using the docker-compose up command:

$ docker-compose up
Pulling server (tomcat:jre11-openjdk)...
jre11-openjdk: Pulling from library/tomcat
001c52e26ad5: Pull complete
...
704b1ae41f0e: Pull complete
Digest: sha256:85bfe38b723bc864ed594973a63c04b112e20d6d33eee57cd5303610d8e3dc77
Status: Downloaded newer image for tomcat:jre11-openjdk
Creating dockercontainers_server_1 ... done
Attaching to dockercontainers_server_1
server_1  | NOTE: Picked up JDK_JAVA_OPTIONS:  --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED
server_1  | 03-Aug-2022 06:22:17.259 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version name:   Apache Tomcat/10.0.23

Critically, we should run the above command from the directory containing the docker-compose.yml file.

In the above output, we can see that the dockercontainers_server_1 is up and running. However, an issue with this approach is that once we exit the above shell, the container will also stop.

To run the Docker container for the long run, we need to run it with an interactive shell.

4. Interactive Shell in Docker

The interactive mode in Docker allows us to execute commands while the container is in a running state. To run the Docker container in interactive mode, we use the -it option. Further, we attach both the STDIN and STDOUT channels to our terminal with the -it flags.

Docker Compose uses a single-host deployment that has multiple benefits:

  • quick and easy to configure
  • enables rapid deployment
  • reduces the amount of time needed to complete multiple tasks
  • all containers run independently, which reduces the risk of a breach

Let’s now run the tomcat container from earlier using docker-compose with an interactive shell:

version: "3"
services:
 server:
   image: tomcat:jre11-openjdk
   ports:
     - 8080:8080
   stdin_open: true 
   tty: true

In this case, we added the stdin_open and tty options in the docker-compose.yml file so that we can have an interactive shell with the docker-compose setup.

Of course, to access the Docker container, we need first to run the container using the below command:

$ docker-compose up --d

Now, we can get an interactive shell of the running docker-compose service:

$ docker-compose exec server bash

Note how we use the service name and not the container name.

Finally, we successfully log into the container with the above command.

5. Conclusion

In this article, we demonstrated how to get an interactive shell using the docker-compose command. First, we learned how to run a Docker container using docker-compose. After that, we explored the same with an interactive shell using the docker exec command and the docker-compose YAML configuration.

Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.