A Quick Guide to Using Docker Compose
Docker Compose is a Docker-native tool that makes multi-container application management a breeze.
Docker Compose is a tool that natively integrates with Docker, and makes managing multi-container applications a breeze.
The benefits Docker Compose provides are numerous, some of which include:
- Manage Container Networks Easily: Connecting two containers via a Docker network is super simple in Docker Compose, being as simple as defining a network and telling the containers to connect to it. In addition, Docker Compose can automatically create and destroy networks as you create and destroy the containers themselves.
- Container Dependencies: You have a Docker container that needs another Docker container to be up and running, say, a database. Docker Compose allows you to define dependencies for a container, requiring the dependencies to be up and running before anything else will start.
- Reproducible Setups: Since the container setup will be defined before anything is even created, this allows for reproducibility of setups, making it easier to transfer them to other systems. While you could theoretically do such in something like Bash, it can make things less flexible and harder to adapt to change.
Installing Docker Compose on Linux
Docker Compose is readily available in most distributions repositories.
You can install Docker Compose on Ubuntu and Debian-based distributions using the following command:
sudo apt install docker-compose
On Arch and Manjaro, you may use:
sudo pacman -S docker-compose
On Fedora, you can use the dnf command:
sudo dnf install docker-compose
You may need to put a bit more effort in installing Docker Compose on CentOS.
For any other distributions, you can always look at the installation docs for information on obtaining the needed packages.
Creating Our First Docker Compose File
Docker Compose files are stored under the name
docker-compose.yml, and are automatically found when you run
docker-compose commands in the same directory. Its syntax takes the form of, you guessed it, YAML.
We have a dedicated tutorial on YAML basics if you are interested in learning about it.
We're going to start with a file that creates a Nextcloud instance, then go over how it actually did what it did.
First things first, you need to create the compose file. Create an empty directory on your system, and create the
Next, fill the file with the following content:
version: '3.5' services: nextcloud_app: container_name: nextcloud_app image: nextcloud restart: unless-stopped networks: - nextcloud ports: - 80:80 volumes: - ./data/app:/var/www/html depends_on: - nextcloud_mariadb nextcloud_mariadb: container_name: nextcloud_mariadb image: mariadb restart: unless-stopped networks: - nextcloud volumes: - ./data/mariadb:/var/lib/mysql environment: MARIADB_ROOT_PASSWORD: 'mariadb' networks: nextcloud: name: nextcloud_docker_network
Now all you have to run is
docker-compose up -d, and you would have successfully deployed Nextcloud with Docker.
Here's the login page of Nextcloud.
Understanding our Docker Compose File
Now that you have seen that the file actually works, let's go over the contents of the file so that you can actually understand what exactly it's doing.
The 'version' Tag
First things first, the
version tag. This is just specifying the version of the Docker Compose file format, as different versions will have different syntax. You generally want to keep this to the latest version, but it doesn't have to, which can be helpful if you have some legacy files.
The 'services' Tag
services: nextcloud_app: container_name: nextcloud_app image: nextcloud restart: unless-stopped networks: - nextcloud ports: - 80:80 volumes: - ./data/app:/var/www/html depends_on: - nextcloud_mariadb nextcloud_mariadb: container_name: nextcloud_mariadb image: mariadb restart: unless-stopped networks: - nextcloud volumes: - ./data/mariadb:/var/lib/mysql environment: MARIADB_ROOT_PASSWORD: 'mariadb'
Next, you see the
services tag. This starts the list for all the applications that are created when
docker-compose up -d is ran.
Followed by this we start the listing for our first container,
nextcloud_app. This serves as the identifier for the app, which can be used by other Docker Compose commands. Note that this is not the name of the container itself - that's specified in the next part.
Now, you start defining everything about your container. Here is a brush-up on what all the fields mean, though most should be self-explanatory if you already know your way around Docker:
container_name- Defines the name of the container. Equivalent to the
image- Defines what image to pull from for the container.
restart- Defines the restart policy for the container. Equivalent to
networks- Defines a network that the container connects to. This network can be created or can already exist. This value serves as an identifier for
docker-composeand is not the actual name of the network (that's defined in the
ports- Defines host ports that the container can connect to. Equivalent to
volumes- Defines volumes for the container. Equivalent to
environment- Defines environment variables for the container. Equivalent to
--env. This option supports two syntax types. The first is
variable: value, which is what is used here. The other option, which may be more familiar if you are used to the
dockerCLI syntax, is
depends_on- Specifies container dependencies. This is used to require a container to not start until its dependencies have. This accepts values from the container listings. (Not
The 'networks' Tag
networks: nextcloud: name: nextcloud_docker_network
Now you get to the
networks tag. This is used to define the networks we listed under
networks for our containers.
networks section, you first list the identifier that you gave to the network under
services. Here, that was
Next, you define the name of the network that can be seen with
docker network ls. Here, we named it
If you wanted the containers to join a network that already existed, you would use the following syntax, replacing
network_name with the name of the Docker network:
networks: nextcloud: external: true name: network_name
And there you go. That sums up the whole file!
Now you know the basics to using Docker Compose, and the benefits you can get through its use. You're also now on your way to understanding what people are doing when they distribute their containers through Compose files.
Something not working, or got some lingering questions? You are welcome to leave them in the comment section below.