DEV Community

Cover image for Discover the hidden gems of multi-container applications ( part 5 )
Prasenjeet Kumar
Prasenjeet Kumar

Posted on • Edited on

Discover the hidden gems of multi-container applications ( part 5 )

What is multi-container Docker applications ?

https://media0.giphy.com/media/Ky53ckyw4Y6JnZeMXP/giphy.gif?cid=7941fdc6micms70mdi8ae5o6fc5ardny87wbbsajjl7v7czp&ep=v1_gifs_search&rid=giphy.gif&ct=g

Multi-container Docker applications are composed of multiple containers that are designed to work together to provide the complete functionality of an application. The containers within a multi-container application are typically interconnected and work in concert to accomplish a specific task or set of tasks.

For example, a web application might consist of a front-end container that serves HTML pages and a back-end container that handles database queries. Both of these containers would be part of the same multi-container application and would work together to provide a fully functional web application.

Where do we use multi-container applications?

Multi-container Docker applications are used in several scenarios, including:

  1. Microservices architecture: A microservices architecture breaks down complex applications into smaller, independent services that can be developed, deployed, and scaled separately. Each microservice can be run in its own container, and multiple containers can communicate with each other using Docker networking or other mechanisms.
  2. Development and testing environments: Docker Compose allows developers to define the entire stack for their applications, including databases, message queues, and other services. This allows them to quickly spin up the environment on their local machine and test their code changes before deploying to production.
  3. High availability and scaling: By running multiple containers for a single application, Docker Swarm or Kubernetes can manage the containers and provide load balancing, high availability, and scaling features. This helps to ensure that the application is always available and can handle varying levels of traffic.
  4. Separation of concerns: Separating the application into multiple containers allows each container to have a specific role or responsibility. For example, one container may handle the application logic, while another container may handle the database. This separation of concerns can help with maintainability and scalability.

Why should we use multi-container applications?

There are several benefits to using multi-container Docker applications:

  1. Scalability: With multi-container Docker applications, you can easily scale individual parts of your application independently. For example, if one part of your application is experiencing high traffic, you can scale that part of the application without having to scale the entire application.
  2. Isolation: By using multiple containers, you can isolate different parts of your application from each other. This can help to prevent issues in one part of the application from affecting other parts.
  3. Resource utilization: By using multiple containers, you can optimize your resource utilization. For example, if one part of your application requires more CPU or memory than another part, you can allocate resources accordingly.
  4. Simplified deployment: With multi-container Docker applications, you can deploy all parts of your application together in a single deployment unit, making it easier to manage and deploy your application.
  5. Improved maintainability: With multiple containers, you can update and maintain different parts of your application separately, making it easier to keep your application up-to-date and secure.

Overall, multi-container Docker applications provide a flexible, scalable, and maintainable way to deploy complex applications.

Docker Compose

https://media4.giphy.com/media/QTxuZHy9wFzyM4Fjno/giphy.gif?cid=7941fdc6gv4tqbrzp18q5ruk51oyifm6yi9o47qcsv6nrgkh&ep=v1_gifs_search&rid=giphy.gif&ct=g

Docker Compose is a tool for defining and running multi-container Docker applications. With Compose, you can define a set of related services in a YAML file, then start and stop them all together with a single command.

Here are some of the most commonly used Docker Compose commands:

  • up: Create and start containers.
  • down: Stop and remove containers, networks, images, and volumes.
  • start: Start existing containers.
  • stop: Stop running containers.
  • restart: Restart running containers.
  • pause: Pause running containers.
  • unpause: Unpause paused containers.
  • ps: List containers.
  • logs: View output from containers.
  • build: Build or rebuild services.
  • config: Validate and view the Compose file.
  • exec: Execute a command in a running container.
  • pull: Pull service images.
  • push: Push service images.
  • rm: Remove stopped containers.
  • run: Run a one-time command against a service.

In this series on Docker, we will discuss each command in great detail so that you can become proficient in using Docker. However, in this particular article, we will only be covering 5 commands.

💡 I spent hours writing this article in a way that is easy to understand for those new to Docker. If you found it helpful, please like and save it for future reference.

docker-compose up

https://media4.giphy.com/media/RbDKaczqWovIugyJmW/giphy.gif?cid=7941fdc6mx5t5ts83mwa370myy8ck6cn8jzd1qicips2o69p&ep=v1_gifs_search&rid=giphy.gif&ct=g

The docker-compose up command is used to build, create, start, and attach to containers for a set of services defined in a docker-compose.yml file.

Here is an example docker-compose.yml file :

version: '3.9'  # specify the Compose file version

services:  # define the services/containers

  db:  # define the MySQL service
    image: mysql:latest  # specify the MySQL image to use
    restart: always  # restart the container automatically if it crashes
    environment:  # set environment variables
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: db_name
      MYSQL_USER: db_user
      MYSQL_PASSWORD: db_password
    ports:  # map container port to host port
      - "3306:3306"
    volumes:  # mount a host directory or named volume to the container
      - db_data:/var/lib/mysql

  app:  # define the Node.js/Express service
    build: ./app  # build the Docker image using the Dockerfile in the app directory
    restart: always  # restart the container automatically if it crashes
    environment:  # set environment variables
      NODE_ENV: development
      DB_HOST: db
      DB_USER: db_user
      DB_PASSWORD: db_password
      DB_NAME: db_name
    ports:  # map container port to host port
      - "8080:8080"
    volumes:  # mount a host directory or named volume to the container
      - ./app:/app

  client:  # define the React service
    build: ./client  # build the Docker image using the Dockerfile in the client directory
    restart: always  # restart the container automatically if it crashes
    ports:  # map container port to host port
      - "3000:3000"
    volumes:  # mount a host directory or named volume to the container
      - ./client:/client

volumes:  # define named volumes to be used in the services
  db_data:
Enter fullscreen mode Exit fullscreen mode

To start these services, we can use the docker-compose up command from the same directory as the docker-compose.yml file:

$ docker-compose up
Enter fullscreen mode Exit fullscreen mode

This will build and start the db, client, and appservices. The containers will be started in the foreground, and we'll see the logs from all containers in the console.

💡 When you run docker-compose up, a default network is created. For example, if your project is named myapp, a network called myapp_default is created. Each container for a service joins the network under the service’s name. For example, a container created using a service named web would join the network under the name web

When running docker-compose up, there are a few options that can be used to modify the behavior of the command. Here are some of the most common options:

--detach

The -d or --detach option is used with the docker-compose up command to run the containers in the background and print the container IDs.

By default, docker-compose up runs the containers in the foreground and logs their output to the terminal. However, with the -d option, the command returns immediately, and the containers continue to run in the background.

For example, to start the containers defined in the docker-compose.yml file in the background, you can use the following command:

docker-compose up -d
Enter fullscreen mode Exit fullscreen mode

This will start the containers in the background and print their IDs.

--build

The docker-compose up --build command is used to build the images for the services defined in the docker-compose.yml file before starting the containers. This command is useful when changes are made to the application code or Dockerfile of a service, and you want to rebuild the image to include those changes.

When you run docker-compose up --build, it will first build the images for any services that have a Dockerfile in their build context or use a custom build command specified in the build section of the docker-compose.yml file. Then it will start the containers for all services defined in the docker-compose.yml file.

Here is an example command to run docker-compose up --build:

docker-compose up --build
Enter fullscreen mode Exit fullscreen mode

This will build the images for all services defined in the docker-compose.yml file before starting the containers.

--force-recreate

The --force-recreate option for the docker-compose up command recreates all containers defined in the docker-compose.yml file, even if they are already running, and forces them to be built again. This option can be used to rebuild containers with updated configurations or to recover from a corrupted state.

By default, Docker Compose will try to reuse existing containers if possible, which can be useful for faster development and testing. However, in some cases, it may be necessary to rebuild and recreate all containers from scratch, such as when changing the Dockerfile or updating dependencies.

Here is an example of using --force-recreate with docker-compose up:

docker-compose up --force-recreate
Enter fullscreen mode Exit fullscreen mode

This command will stop and remove all containers defined in the docker-compose.yml file, and then recreate them with the latest configurations and images. It can be useful when deploying changes to a production environment or when troubleshooting issues with containers.

💡If a service is already running, the docker-compose up command will not start another instance of that service. Instead, it will leave the running instance as it is and continue to start up any other services that are defined in the docker-compose.yml file.

If you want to force a restart of the running service, you can use the docker-compose up --force-recreate command. This will stop the running service and start a new instance of it with the latest configuration defined in the docker-compose.yml file.

If you want to recreate a specific service, you can use the docker-compose up --force-recreate <service> command. This will recreate only the specified service and not the others.

For example, if you have a web and a db service defined in your docker-compose.yml file, and you want to recreate only the db service, you can run the following command:

docker-compose up --force-recreate db
Enter fullscreen mode Exit fullscreen mode

This will recreate the db service and leave the web service running as is.

-no-recreate

If containers already exist, don't recreate them. This option is useful when you don't want to recreate the containers each time you run the command.

-no-build

Don't build an image, even if it's outdated or missing. This option is useful when you don't want to build the image each time you run the command.

--remove-orphans

The --remove-orphans option is used with the docker-compose up command to remove any containers that were created by the current project but are no longer defined in the Compose file. Orphaned containers can occur when a container is created but its service definition is later removed from the Compose file.

Here is an example of using the --remove-orphans option with docker-compose up command:

docker-compose up --remove-orphans
Enter fullscreen mode Exit fullscreen mode

This will start all the services defined in the Compose file and remove any orphaned containers.

💡 If a container is running that is not defined in the Compose file, it will not be affected by the --remove-orphans option. This option is only used to remove containers that were created as part of the Compose service definition, but are no longer defined in the Compose file.

-timeout

Specify a shutdown timeout in seconds. This option is used to specify how long Compose should wait for containers to shut down before killing them.

--scale

The --scale option in docker-compose is used to scale a service up or down by increasing or decreasing the number of containers running for that service. It allows you to run multiple instances of the same service, with the same configuration, simultaneously.The syntax of using the --scale option is as follows:

docker-compose up --scale service_name=num_instances
Enter fullscreen mode Exit fullscreen mode

Here, service_name is the name of the service that you want to scale and num_instances is the number of instances you want to run for that service.

For example, if you have a web service in your docker-compose.yml file and you want to run three instances of that service, you can use the following command:

docker-compose up --scale web=3
Enter fullscreen mode Exit fullscreen mode

This will start three instances of the web service.

💡 Note that the --scale option only works for services that are defined in the docker-compose.yml file. If a service is not defined in the file, the --scale option will have no effect.

docker-compose down

https://media4.giphy.com/media/THuO7JQbmVdpEZnrMw/giphy.gif?cid=7941fdc6iwmbph6oq4u16m76g69zid0x33f2rm2e10oiqkf7&ep=v1_gifs_search&rid=giphy.gif&ct=g

docker-compose down is a command used to stop and remove the containers, networks, and volumes that were created by docker-compose up.

By default, docker-compose down will stop and remove the containers declared in the docker-compose.yml file, and remove the network, but will not remove volumes. To remove the volumes as well, you can use the -v or --volumes option.

Here is the basic syntax for docker-compose down:

docker-compose down [options]
Enter fullscreen mode Exit fullscreen mode

Here are some commonly used options:

  • v, --volumes: Remove named volumes declared in the volumes section of the docker-compose.yml file
  • -rmi <all|local>: Remove images. The all option removes all images used by any service defined in the docker-compose.yml file. The local option removes only images that don't have a custom tag or are not used by any other service.
  • t, --timeout <timeout> : Specify a shutdown timeout (default is 10 seconds).
  • -remove-orphans : Remove containers for services not defined in the docker-compose.yml file.

Here's an example command to stop and remove the containers and network defined in a docker-compose.yml file:

docker-compose down
Enter fullscreen mode Exit fullscreen mode

If you also want to remove the volumes, you can add the -v option:

docker-compose down -v
Enter fullscreen mode Exit fullscreen mode

The -rmi option is used to remove images created by docker-compose build. It accepts two values:

  • all: Remove all images used by any service defined in the docker-compose.yml file.
  • local: Remove only the images that are not associated with any container. This is the default option.

Here are some examples:

To remove all containers, networks, and volumes created by docker-compose up , and also remove all images used by the services:

docker-compose down --rmi all
Enter fullscreen mode Exit fullscreen mode

To remove all containers, networks, and volumes created by docker-compose up , and only remove the images that are not associated with any container:

docker-compose down --rmi local
Enter fullscreen mode Exit fullscreen mode

docker compose stop

https://media0.giphy.com/media/cKKXNlTYino7hWNXwl/giphy.gif?cid=7941fdc6pupw4p2l4v4ml5avyd2ih88tjmws27nnupouf3gj&ep=v1_gifs_search&rid=giphy.gif&ct=g

The docker-compose stop command stops the containers defined in the docker-compose.yml file. It sends a SIGTERM signal to the container processes, giving them a chance to stop gracefully. If the processes do not stop within the given timeout period (default is 10 seconds), then a SIGKILL signal is sent to forcefully terminate the processes.

The syntax of the command is:

docker-compose stop [options] [SERVICE...]
Enter fullscreen mode Exit fullscreen mode

Where options can include:

  • t, --timeout TIMEOUT : Specify a custom timeout value (in seconds) for stopping the containers.

And SERVICE... is an optional list of service names to stop. If no service name is provided, all services defined in the docker-compose.yml file will be stopped.

Here's an example of how to use the docker-compose stop command:

docker-compose stop
Enter fullscreen mode Exit fullscreen mode

This will stop all the containers defined in the docker-compose.yml file.

docker-compose stop mysql
Enter fullscreen mode Exit fullscreen mode

This will stop only the mysql service defined in the docker-compose.yml file.

💡 If we stop a service that is a dependency for another service, the dependent service will also stop. For example, if we have two services, dband web, and web depends on db, if we stop the dbservice, the webservice will also stop.

docker-compose start

https://media0.giphy.com/media/ZWbeEcbeo0cKI/giphy.gif?cid=7941fdc6kq9gst2juusi2wui8fa5sazdmi0gkrsmf6tvb5xp&ep=v1_gifs_search&rid=giphy.gif&ct=g

The docker-compose start command is used to start containers that are already created but are currently stopped. It does not recreate containers or rebuild images. This command is useful when you have stopped a container using docker-compose stop and want to start it again.

Here's an example of using docker-compose start command:

Suppose you have a docker-compose.yml file that defines two services app and db. If you start the services using the following command:

docker-compose up -d
Enter fullscreen mode Exit fullscreen mode

It will create and start the containers in detached mode. Now, if you want to stop the containers, you can use the following command:

docker-compose stop
Enter fullscreen mode Exit fullscreen mode

This will stop the running containers. If you want to start the containers again, you can use the docker-compose start command:

docker-compose start
Enter fullscreen mode Exit fullscreen mode

This will start the stopped containers.

You can start a specific service using the docker-compose start command followed by the service name. For example, if you have a service called web defined in your docker-compose.yml
file, you can start it using the following command:

docker-compose start web
Enter fullscreen mode Exit fullscreen mode

This will start only the web service and any services that it depends on. If the service is already running, it will not be restarted.

docker-compose restart

https://media0.giphy.com/media/26G3J4n04974Q/giphy.gif?cid=7941fdc61u0ywlr2dnekmlsn32fn30zikpue0kyzs8td5abe&ep=v1_gifs_search&rid=giphy.gif&ct=g

The docker-compose restart command is used to restart one or more services defined in the docker-compose.yml file.

Here is the basic syntax of the command:

docker-compose restart [options] [SERVICE...]
Enter fullscreen mode Exit fullscreen mode

Some important options that can be used with this command are:

  • -timeout TIMEOUT : This option sets the timeout for stopping the containers. The default value is 10 seconds.

Here is an example command that restarts the web service defined in the docker-compose.yml file:

docker-compose restart web
Enter fullscreen mode Exit fullscreen mode

This command will stop and then start the web service.

In conclusion, Docker Compose is a powerful tool for managing multi-container applications. It allows you to define and run complex applications with ease, and provides a range of options for managing containers and services. In this article, we covered some of the most common Docker Compose commands and options, including docker-compose up, docker-compose down, docker-compose start, and docker-compose restart. We also looked at options for managing container builds, scaling services, and removing orphaned containers.

If you found this article helpful, please give it a thumbs up and save it for future reference. If you have any questions or comments, feel free to leave them below.Thank you for reading! I'll see you in the next article.

Top comments (0)