Introduction

In the dynamic landscape of containerization and application deployment, effective management of complex architectures is crucial. Docker Compose emerges as a powerful tool in the field of container orchestration, simplifying the process of defining, configuring, and deploying multi-container applications. This article serves as a fundamental guide, shedding light on the essential aspects of Docker Compose.

The YouTube Channels in both English (En) and French (Fr) are now accessible, feel free to subscribe by clicking here.

What is Docker Compose

Docker Compose stands as an indispensable tool. This extension of Docker offers the ability to define and manage multi-container applications using simple configuration files written in YAML. Instead of manually managing each container individually, Docker Compose allows the declaration of services, networks, and volumes within a single file, significantly simplifying the deployment process.

Why use Docker Compose

Docker Compose presents several significant advantages in the deployment and management of multi-container applications. Here are some of these benefits:

  • Simplicity of Configuration: Docker Compose uses simple YAML configuration files to define the structure of applications. This approach makes the configuration and management of services, networks, and volumes easier.
  • Facilitated Orchestration: With Docker Compose, it becomes easy to declare and coordinate multiple services and containers within a single application. This simplifies the orchestration of interconnected components.
  • Rapid Deployment: Using a single configuration file, Docker Compose provides an efficient method to quickly deploy applications with all their necessary components. This speeds up the development and testing process.
  • Environment Isolation: Docker Compose configuration files can be tailored for different environments such as development, production, or testing. This allows effective isolation of settings and configurations specific to each phase of an application’s lifecycle.

Docker Compose YML File

Basic Structure

To understand Docker Compose, one must first grasp its blueprint, the docker-compose.yml file. This section dissects its fundamental structure, providing a foundation for configuring services, networks, volumes, and dependencies.

Let’s follow the next part with the following example in mind, it’s a sample multi-container Docker Compose definition that we showcased in the previous article:

version: '3.7'
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - 3000:3000
    depends_on:
      mysqldb:
        condition: service_healthy
    environment:
      - DB_HOST=mysqldb
      - DB_PORT=3306
      - DB_NAME=${MYSQL_DATABASE}
      - DB_USERNAME=root
      - DB_PASSWORD=${MYSQL_PASSWORD}
    networks:
      - nodejs-mysql-network
  mysqldb:
    image: mysql:8.0.33
    ports:
      - 3306:3306
    environment:
      - MYSQL_DATABASE=${MYSQL_DATABASE}
      - MYSQL_ROOT_PASSWORD=${MYSQL_PASSWORD}
    volumes:
      - mysql-data:/var/lib/mysql
    networks:
      - nodejs-mysql-network
    healthcheck:
      test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]
      retries: 10
      interval: 3s
      timeout: 30s
volumes:
  mysql-data:
networks:
  nodejs-mysql-network:
    name: nodejs-mysql-network

Services

Services, the true masters of ceremonies in the Docker Compose universe, define the elements that compose your environment. For the example above, we have a NodeJS backend application called app and a MySQL database instance called mysqldb. Each service specifies a Docker image to use, the ports to expose, environment variables, possible dependencies, and many other crucial parameters. Understanding the configuration of services is the key to orchestrating your containers harmoniously.

Networks

Networks, acting like invisible threads, facilitate communication between services within your architecture. Docker Compose distinguishes itself with remarkable flexibility in network management. It generates default networks, promoting seamless communication between your services. In the example above, both services are in the same network (nodejs-mysql-network), so the database is addressable via the mysqldb service name which is its host.

Volumes

Volumes, true guardians of persistent data, are crucial to ensure the continuity of information beyond the ephemeral lifespan of containers. Through the use of volumes, it becomes possible to retain the data of your applications even after the destruction of containers, ensuring the stability and availability of crucial data for the proper functioning of your application. In this case, our data are saved in the mysql-data volume, so a restart will bootstrap the App with its normal state.

Dependencies

In Docker Compose, the property depends_on is used to specify the dependencies between the services included in our infrastructure. This flag helps to define the order of execution of our components. But, it doesn’t make sure that the database service is properly accessible before running the app one, that’s why it’s coupled with a healthcheck in the example above. Meaning, the app service starts only if the database is up and running and can respond to queries.

Docker Compose Commands

Docker Compose commands are essential tools to steer and manage your orchestrated environments. Here are some fundamental commands to help you navigate the world of Docker Compose:

docker compose up

The docker-compose up command is the opening note of the Docker Compose symphony. It builds, (re)creates, and starts all services defined in the docker-compose.yml file. Whether for initial deployment or an update, docker-compose up is the starting point to kick-start your infrastructure.

docker compose up

docker compose down

When the show is over, the "docker-compose down" command takes the stage to stop and/or clean everything. By supplying the “–rmi all” option, it stops and removes the containers, networks, and volumes created by docker-compose up, ensuring a clean halt to your environment.

docker compose down --rmi all

docker compose ps

To monitor the real-time status of your services, use the docker-compose ps command. It displays a dynamic table indicating the current state of each service, allowing you to keep a vigilant eye on the execution of your orchestration.

docker compose ps

docker compose logs

The docker-compose logs command provides immediate access to the logs of all services. Useful for debugging or understanding the internal activities of containers, it immerses you in the world of logs seamlessly.

docker compose logs

docker compose exec

To access a shell or execute commands inside a running container, docker-compose exec is your ally. It opens a door into the container, facilitating troubleshooting or specific actions as needed.

docker compose exec service_name command

Environment Variables in Docker Compose

Working with environment variables with Docker Compose is as easy as doing it within any backend project. Let’s consider the following MySQL service definition that contains two environment variables:

  mysqldb:
    image: mysql:8.0.33
    ports:
      - 3306:3306
    environment:
      - MYSQL_DATABASE=${MYSQL_DATABASE}
      - MYSQL_ROOT_PASSWORD=${MYSQL_PASSWORD}
    volumes:
      - mysql-data:/var/lib/mysql
    networks:
      - nodejs-mysql-network

There are two ways to provide them, using the dynamic way (not writing sensitive information in the source code).

  • The command line
    We can supply the environment variables while running the composed services using the command:
    MYSQL_DATABASE=mydatabase MYSQL_PASSWORD=rootpassword docker compose up
  • The .env file
    In case you would like to provide the environment variables from a hidden .env file, feel free to create it close to the docker-compose.yml file within the project. In case these files are in different locations, you must use the env_file field in the targeted service to specify the folder to access the .env file.

Docker Compose Examples

Take a look at the following examples of deployment we put in place using Docker Compose, Spring Boot, NodeJS, and MySQL:

———————

We have just started our journey to build a network of professionals to grow even more our free knowledge-sharing community that’ll give you a chance to learn interesting things about topics like cloud computing, software development, and software architectures while keeping the door open to more opportunities.

Does this speak to you? If YES, feel free to Join our Discord Server to stay in touch with the community and be part of independently organized events.

———————

Conclusion

In conclusion, Docker Compose proves to be a powerful tool for orchestrating and deploying containerized applications efficiently and consistently. Through the dissection of the docker-compose.yml file, we have understood how to configure services, networks, and volumes, establishing the foundations for successful orchestration.

Thanks for reading this article. Like, recommend, and share if you enjoyed it. Follow us on FacebookTwitter, and LinkedIn for more content.

author-avatar

About Kemane Donfack

Hello, I am a passionate IT professional specializing in Cloud, DevOps, and technical writing. My blog is dedicated to sharing my knowledge and experiences to simplify and optimize development processes. Welcome to the world of Cloud and DevOps collaboration!. Follow me on Twitter & LinkedIn & Website.