Learn Docker With My Newest Course

Dive into Docker takes you from "What is Docker?" to confidently applying Docker to your own projects. It's packed with best practices and examples. Start Learning Docker →

Docker Tip #82: Using YAML Anchors and X Properties in Docker Compose

blog/cards/docker-tips-and-tricks.jpg

YAML anchors let you reuse parts of your YAML file like functions. You can use them to share default settings between services.

This is quite handy when you want to DRY out some bits of your docker-compose.yml file.

Example web + worker set up without using this strategy:

Keep in mind this isn’t a full docker-compose.yml file. I’ve only extracted out a couple of services and fields to show case this feature specifically.

version: "3.4"

services:
  web:
    build:
      context: "."
      args:
        - "APP_ENV=${APP_ENV:-prod}"
    depends_on:
      - "postgres"
      - "redis"
    env_file:
      - ".env"
    image: "nickjj/myapp"
    ports:
      - "8000:8000"
    restart: "unless-stopped"
    stop_grace_period: "3s"
    volumes:
      - ".:/app"

  worker:
    build:
      context: "."
      args:
        - "APP_ENV=${APP_ENV:-prod}"
    depends_on:
      - "postgres"
      - "redis"
    env_file:
      - ".env"
    image: "nickjj/myapp"
    restart: "unless-stopped"
    stop_grace_period: "3s"
    volumes:
      - ".:/app"

So much duplication! Everything is the same except the ports property on the web service.

The same example using YAML Anchors and the X prefix to set defaults:
version: "3.4"

x-app: &default-app
  build:
    context: "."
    args:
      - "APP_ENV=${APP_ENV:-prod}"
  depends_on:
    - "postgres"
    - "redis"
  env_file:
    - ".env"
  image: "nickjj/myapp"
  restart: "unless-stopped"
  stop_grace_period: "3s"
  volumes:
    - ".:/app"

services:
  web:
    <<: *default-app 
    ports:
      - "8000:8000"

  worker:
    <<: *default-app

Now we only need to write the common bits once, and multiple services can benefit from it. It’s very handy for setting up common things like logging or various other Docker properties.

You can name the x- properties anything you want as long as it’s valid YAML syntax. These x- properties are called “Extension fields” in Docker Compose’s documentation.

The basic idea is the extension field just acts as a “place” to define the YAML anchor. The extension field’s name doesn’t need to match the anchor, but it’s a reasonable idea to keep them the same for consistency.

Overriding default anchor values on a per service basis:

For example, if you wanted to set a different stop_grace_period for the worker service you would end up doing:

  worker:
    <<: *default-app
    stop_grace_period: "10s"

This takes advantage of YAML’s “merge” feature.

Overall this is definitely a handy feature, but like all abstractions, sometimes it’s easy to get carried away. In other words, it’s probably not worth it to DRY out 2 properties like this.

Fun fact! I opened a pull request on Docker Compose’s documentation back in Feb. 2015 to talk about the value of YAML anchors but it never got merged. Thankfully Docker now recognizes the value of this feature.

Free Intro to Docker Email Course

Over 5 days you'll get 1 email per day that includes video and text from the premium Dive Into Docker course. By the end of the 5 days you'll have hands on experience using Docker to serve a website.


Comments