DEV Community

Cover image for Docker Compose Syntax: Volume or Bind Mount?
Maxim Orlov
Maxim Orlov

Posted on • Edited on • Originally published at maximorlov.com

3 1

Docker Compose Syntax: Volume or Bind Mount?

This article was originally published a day earlier at https://maximorlov.com/docker-compose-syntax-volume-or-bind-mount/

Docker Compose allows you to configure volumes and bind mounts using a short syntax. A few examples:

./public:/usr/share/nginx/html
/var/lib/postgresql/data
/some/content:/usr/share/nginx/html
~/configs:/etc/configs
postgresql:/var/lib/postgresql/data

Which of these are volumes and which are a bind mounts?

Whenever I had to read a docker-compose.yml file, I had to look up the official documentation or run a quick local experiment to figure out how Docker Compose would mount the directories into the container.

I wrote this article so that next time you read a Docker Compose file, you won't have to guess anymore. You'll simply know by looking at the syntax whether a volume or a bind mount is used behind the scenes.

The different variations are essentially three unique forms. I list and explain them in this article below.

Two volumes keys in docker-compose.yml

Before we talk about the different ways to specify volumes, let's first clarify which volumes key we're referring to. In docker-compose.yml, the volumes key can appear in two different places.

version: "3.7"

services:
  database:
    # ...
    volumes: # Nested key. Configures volumes for a particular service.

volumes: # Top-level key. Declares volumes which can be referenced from multiple services.
  # ...
Enter fullscreen mode Exit fullscreen mode

In this article, we'll talk about the nested volumes key. That's where you configure volumes for a specific service/container such as a database or web server. This configuration has a short (and a long) syntax format.

Short syntax format and its variations

The volume configuration has a short syntax format that is defined as:

[SOURCE:]TARGET[:MODE]

SOURCE can be a named volume or a (relative or absolute) path on the host system. TARGET is an absolute path in the container. MODE is a mount option which can be read-only or read-write. Brackets mean the argument is optional.

This optionality leads to three unique variations you can use to configure a container's volumes. Docker Compose is smart about recognising which variety is used and whether to use a volume or bind mount.

  1. No SOURCE - eg. /var/lib/postgresql/data

When only a target is specified, without a source, Docker Compose will create an anonymous directory and mount it as a volume to the target path inside the container.

The directory's path on the host system is by default /var/lib/docker/volumes/<uuid>/_data, where <uuid> is a random ID assigned to the volume as its name.

  1. A non-path SOURCE - eg. postgresql-data:/var/lib/postgresql/data

If a source is present and it's not a path, then Docker Compose assumes you're referring to a named volume. This volume needs to be declared in the same file in the top-level volumes key declaration.

Top-level volumes key always declares volumes, never bind mounts. Bind mounts don't have a name and they can't be named.

  1. A path SOURCE - eg. /some/content:/usr/share/nginx/html or ./public:/usr/share/nginx/html

If source is a path, absolute or relative, Docker Compose will bind mount the folder into the container. Relative paths starting with . or .. are relative to the location of docker-compose.yml.

Bind mounts are discouraged for database containers since that makes them less portable. Bind mounts are specific to the host system and Docker doesn't manage them. The official docs have a section about volumes vs bind mounts that explains the differences between the two in more detail.

Summing it up

Docker Compose allows you to configure volumes by using a short syntax string. Whether you end up with a volume or a bind mount, depends on which short syntax variation you use.

When you don't specify a source, Docker Compose will create an anonymous volume. If source is not a path, Docker Compose will assume source is a named volume. Sources that are relative or absolute paths are bind-mounted into the container.

If you liked this type of article that uncovers a primary feature, you might find my article about the EXPOSE instruction in Dockerfile interesting. I clarify a few misconceptions around exposing a port and explain what EXPOSE does, and doesn't do.

Write clean code. Stay ahead of the curve.

Every other Tuesday, I share tips on how to build robust Node.js applications. Join a community of developers committed to advancing their careers and gain the knowledge & skills you need to succeed.

Subscribe for success!

AWS Security LIVE!

Tune in for AWS Security LIVE!

Join AWS Security LIVE! for expert insights and actionable tips to protect your organization and keep security teams prepared.

Learn More

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay