Skip to main content

Image Release Pipeline Template

The image-release.yml pipeline template provides a complete CI/CD workflow for releasing multiple Docker images from a structured directory.

Overview

This template orchestrates the Docker image release process for projects that maintain multiple Docker images in a structured images/ directory, including:

  • Semantic versioning validation
  • Multi-image Docker builds
  • Image tagging with release versions
  • Release management and GitLab release creation

Usage

include:
- project: 'welance/platform/pipelines/templates/pipeline/git-flow'
ref: release/1.0.0
file: 'image-release.yml'
variables:
PRODUCTION_TARGET: 'welance'

Pipeline Stages

The Image Release pipeline template includes the following stages:

  1. init - Version validation and preparation
  2. build - Multi-image Docker building
  3. release - Release tagging and GitLab release creation

Included Job Templates

The template includes the following job templates from the ci-jobs repository:

Build Jobs

  • build/docker-build.yml - Docker image building (includes docker-build-multi)

Release Jobs

  • release/merge-and-tag.yml - Merge request handling and tagging

Default Variables

variables:
CI_ARTIFACT_TOKEN: $CI_ARTIFACT_PULL_TOKEN
REGISTRY_ID: 4495833

Variable Details

  • CI_ARTIFACT_TOKEN: Token for pulling artifacts from other jobs
  • REGISTRY_ID: Container registry project ID
  • PRODUCTION_TARGET: Must be set to 'welance' for release jobs to run

Version Validation

check_test

  • Stage: init
  • Purpose: Validates semantic versioning for staging deployments
  • Runs on: release/* and hotfix/* branches
  • Output: Sets VERSION={RELEASE}.rc{CI_PIPELINE_IID} (e.g., 1.0.0.rc42)
  • Validates: Semantic versioning format from branch name

check_prod

  • Stage: init
  • Purpose: Validates semantic versioning for production deployments
  • Runs on: MRs targeting main branch
  • Output: Sets VERSION={RELEASE}, TAG=v{VERSION}, EXTRA_DESCRIPTION
  • Validates: Semantic versioning format from MR source branch name

Build Jobs

build_images_staging

  • Stage: build
  • Extends: .docker-build-multi
  • Needs: check_test
  • Environment: staging
  • Runs on: release/* and hotfix/* branches
  • Builds: All images in ./images/ directory (or specified subset)
  • Tags: Images with `{RELEASE}.rc{CI_PIPELINE_IID}` version

build_images_production

  • Stage: build
  • Extends: .docker-build-multi
  • Needs: check_prod
  • Environment: production
  • Runs on: MRs targeting main branch
  • Builds: All images in ./images/ directory (or specified subset)
  • Tags: Images with `{RELEASE}` version

Multi-Image Build

The pipeline uses .docker-build-multi which:

  1. Scans Directory: Looks for subdirectories in images/ (or IMAGES_ROOT)
  2. Builds Each Image: Builds a Docker image for each subdirectory containing a Dockerfile
  3. Tags Images: Tags each image with the version (staging: `{RELEASE}.rc{CI_PIPELINE_IID}`, production: `{RELEASE}`)
  4. Pushes Images: Pushes all built images to the container registry

Image Directory Structure

Expected structure:

.
├── images/
│ ├── image1/
│ │ └── Dockerfile
│ ├── image2/
│ │ └── Dockerfile
│ └── image3/
│ └── Dockerfile
└── .gitlab-ci.yml

Optional Configuration

You can configure which images to build:

build_images_staging:
extends: .docker-build-multi
variables:
APP_ENVIRONMENT: "staging"
IMAGES_ROOT: "images" # optional, defaults to "images"
IMAGES: "image1 image2" # optional: build only specific images

Release Jobs

merge_and_tag

  • Stage: release
  • Extends: .merge_and_tag_job
  • Runs on: MRs targeting main (when PRODUCTION_TARGET == "welance")
  • When: manual
  • Merges MR, creates realign branch, creates alignment MR

release_job

  • Stage: release
  • Image: registry.gitlab.com/gitlab-org/release-cli:latest
  • Needs: merge_and_tag
  • Runs on: MRs targeting main (when PRODUCTION_TARGET == "welance")
  • Creates GitLab release with tag and description

Required Variables

  • PRODUCTION_TARGET - Must be set to 'welance' for release jobs to execute

Optional Variables

  • IMAGES_ROOT - Root directory containing image subdirectories (default: images)
  • IMAGES - Space-separated list of specific images to build (default: all images in IMAGES_ROOT)

Example Configuration

Basic Configuration

include:
- project: 'welance/platform/pipelines/templates/pipeline/git-flow'
ref: release/1.0.0
file: 'image-release.yml'
variables:
PRODUCTION_TARGET: 'welance'

Build Specific Images Only

include:
- project: 'welance/platform/pipelines/templates/pipeline/git-flow'
ref: release/1.0.0
file: 'image-release.yml'
variables:
PRODUCTION_TARGET: 'welance'

build_images_staging:
extends: .docker-build-multi
variables:
APP_ENVIRONMENT: "staging"
IMAGES: "mysql-backup redis-cache" # Build only these images

Custom Images Directory

include:
- project: 'welance/platform/pipelines/templates/pipeline/git-flow'
ref: release/1.0.0
file: 'image-release.yml'
variables:
PRODUCTION_TARGET: 'welance'

build_images_staging:
extends: .docker-build-multi
variables:
APP_ENVIRONMENT: "staging"
IMAGES_ROOT: "docker-images" # Use custom directory

Branch Strategy

  • release/{version} - Builds and tags images with staging version ({version}.rc{CI_PIPELINE_IID})
  • hotfix/{version} - Builds and tags images with staging version ({version}.rc{CI_PIPELINE_IID})
  • main (via MR) - Builds and tags images with production version ({version}), creates release (manual)

Version Tagging

  • Staging: `{RELEASE}.rc{CI_PIPELINE_IID}` (e.g., 1.0.0.rc42)
  • Production: `{RELEASE}` (e.g., 1.0.0)

Each image is tagged as: {CI_REGISTRY_IMAGE}/{image-name}:{VERSION}

Image Naming Convention

Images are named based on their subdirectory name:

  • Directory: images/mysql-backup/ → Image: {CI_REGISTRY_IMAGE}/mysql-backup:{VERSION}
  • Directory: images/redis-cache/ → Image: {CI_REGISTRY_IMAGE}/redis-cache:{VERSION}

Workflow

Staging Workflow (release/* or hotfix/* branches)

  1. Version Validation: check_test validates SemVer and sets `VERSION={RELEASE}.rc{CI_PIPELINE_IID}`
  2. Build Images: build_images_staging builds all images in images/ directory
  3. Tag & Push: Each image is tagged and pushed to registry

Production Workflow (MR → main)

  1. Version Validation: check_prod validates SemVer and sets VERSION={RELEASE}, TAG=v{VERSION}
  2. Build Images: build_images_production builds all images in images/ directory
  3. Tag & Push: Each image is tagged and pushed to registry
  4. Merge & Tag: merge_and_tag merges MR and creates Git tags (manual)
  5. Release: release_job creates GitLab release (automatic after merge_and_tag)

Prerequisites

  • Images Directory: Project must have an images/ directory (or custom IMAGES_ROOT)
  • Dockerfiles: Each image subdirectory must contain a Dockerfile
  • Semantic Versioning: Branch names must follow release/{version} or hotfix/{version} format
  • Container Registry: GitLab Container Registry must be enabled
  • PRODUCTION_TARGET: Must be set to 'welance' for release jobs

Example Project Structure

.
├── images/
│ ├── mysql-backup/
│ │ ├── Dockerfile
│ │ └── backup.sh
│ ├── redis-cache/
│ │ ├── Dockerfile
│ │ └── cache-config.conf
│ └── nginx-proxy/
│ ├── Dockerfile
│ └── nginx.conf
├── .gitlab-ci.yml
└── CHANGELOG.md

Notes

  • The pipeline builds all images in the images/ directory by default
  • Use IMAGES variable to build only specific images
  • Staging builds use release candidate versions (`.rc{CI_PIPELINE_IID}`)
  • Production builds use exact version from branch name
  • Release jobs only run when PRODUCTION_TARGET == "welance"
  • The pipeline targets main branch (not master)
  • Each image is built independently and can be deployed separately
  • The pipeline validates semantic versioning before building
  • Release jobs create GitLab releases with links to container images
  • The merge_and_tag job creates realign branches for keeping develop in sync