Featured image of post GitLab Anchors

GitLab Anchors

Master GitLab CI/CD templates with YAML anchors and components. Create reusable Docker build configurations and eliminate configuration duplication across projects.

One Template to Rule Them All

Why bother reading this

The Copy-Paste Nightmare

You’ve been there: copying that working CI/CD config from Project A to Project B. Then to Project C. Now you need to update the Docker version across all of them. You spend your afternoon hunting down 15 different .gitlab-ci.yml files, praying you didn’t miss one. And every new project multiplies the debt.

Sound familiar? You’re not alone, and there’s a better way.

What You’ll Gain

Imagine updating your entire organization’s Docker build configuration by editing a single file. One change, deployed everywhere, instantly. No copy-pasting, no inconsistencies, no missed repositories.

That’s what GitLab anchors and components give you:

  • Build once, use everywhere: Define your Docker setup and build command in one place
  • Update in seconds: Change Docker versions and build args for all projects with one commit
  • Onboard developers faster: New team members just include your template - no PhD in CI/CD required
  • Sleep better: Know every pipeline follows your security standards by default

How It Works (The 2-Minute Version)

GitLab gives you two powerful tools for not repeating yourself. Both allow you to reuse existing code snippets to be defined once and reused in as many jobs or configuration sections as necessary. It’s the ultimate single source of truth for your configuration:

YAML Anchors (Internal Reuse)

The YAML spec lets you define something once (&) and reuse it (*):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Define script to set up SSH keys
.deploy-setup: &setup-ssh-keys
  - echo "Setting up SSH keys for deployment"
  - mkdir -p ~/.ssh
  - echo "${SSH_DEPLOY_KEY}" | base64 -d > ~/.ssh/deploy-key 
  - chmod 600 ~/.ssh/deploy-key

deploy-job-1:
  before_script:
    # Run predefined setup of SSH keys
    - *setup-ssh-keys

GitLab Components & References (Global Reuse)

While anchors are limited to one file, GitLab’s .extends, !reference and include: keywords allow you to pull logic from centralized repositories. You can now reuse configuration blocks even across different files, making templating much more efficient. This is Gitlab’s “Steroid Version” of anchors, which tackles the 15-file hunt.

1
2
3
4
5
6
include:
  - component: gitlab.com/project/templates/deploy@main

deploy-job-1:
  before_script:
    - !reference [.deploy_setup, setup-ssh-keys]

Real-World Examples

Docker Builds That Scale

Every project needs a DinD setup, every project needs the same variables and every project breaks when you forget one setting. It also saves your colleagues a lot of hassles.

Template project - gitlab.com/gion-io/templates/docker

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# templates/docker-build.yml
.dind_base:
  image: docker:28
  services:
    - name: docker:28-dind
      alias: docker
      command: ["--tls=false"]
  variables:
    DOCKER_HOST: tcp://docker:2375
    DOCKER_TLS_CERTDIR: ""
    DOCKER_BUILDKIT: 1

Standardized Build Logic with Anchors

Now we create the actual logic. By using YAML anchors (& and *), we create reusable “building blocks” for logging into the registry and executing the build command.

Template project - gitlab.com/gion-io/templates/docker

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# templates/docker-build.yml
.docker_helpers:
  # YAML anchor for Gitlab Container Registry login
  login_gitlab: &login_gitlab
    - echo "$CI_REGISTRY_PASSWORD" | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin

  # YAML anchor for docker buildx
  docker_build: &docker_build
    - docker buildx build --push -t $TAG .

.docker_builds:
  default_build: &default_build
    - TAG=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    - *login_gitlab
    - *docker_build

Application Pipeline

This is where the architecture pays off. Your application project becomes incredibly clean. You simply include the GitLab Component and reference the pre-defined logic.

Application project - gitlab.com/gion-io/examples/anchors

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
include:
  # Including the component from the template library
  - component: gitlab.com/gion-io/templates/docker/docker-build@main

build-job:
  # Include our DinD setup from the template 
  extends: .dind_base
  stage: build
  # Run our centralized build from the template
  script:
    - !reference [.docker_builds, default_build]

Take-Away

Why this is a Game Changer

By adopting this structure, you can move from “Copy-Paste” to a managed platform:

  1. Single Source of Truth: Need to upgrade to Docker 29 or change security flags? Update one file in the templates repository, and every project using the template inherits the change.
  2. Developer Experience: Application developers don’t need to understand the nuances of DinD or buildx flags. They just “include and run.”
  3. Consistency: Every build across the organization follows the exact same hardened process, ensuring reliability across all environments.

Start Using This Today

Full working examples on my Gitlab Repo: https://gitlab.com/gion-io

Licensed under BSD Zero Clause License
Last updated on 17 Jan 2026 03:27 +0100
Built with Hugo
Theme Stack designed by Jimmy