What is multi-container Docker applications ?
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:
- 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.
- 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.
- 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.
- 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:
- 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.
- 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.
- 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.
- 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.
- 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
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
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:
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
This will build and start the db
, client
, and app
services. 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
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
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
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
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
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
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
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
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]
Here are some commonly used options:
-
v, --volumes
: Remove named volumes declared in thevolumes
section of thedocker-compose.yml
file -
-rmi <all|local>
: Remove images. Theall
option removes all images used by any service defined in thedocker-compose.yml
file. Thelocal
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 thedocker-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
If you also want to remove the volumes, you can add the -v
option:
docker-compose down -v
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 thedocker-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
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
docker compose stop
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...]
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
This will stop all the containers defined in the docker-compose.yml
file.
docker-compose stop mysql
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, db
and web
, and web
depends on db
, if we stop the db
service, the web
service will also stop.
docker-compose start
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
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
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
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
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
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...]
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
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)