← Назад к вопросам
Как настроить Pipelines, чтобы один и тот же образ собирался с несколькими тегами
1.7 Middle🔥 211 комментариев
#CI/CD и автоматизация#Docker и контейнеризация
Комментарии (1)
🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Настройка тегирования образов в CI/CD пайплайнах
Настройка сборки Docker-образов с несколькими тегами — это стандартная практика в DevOps, которая обеспечивает гибкость управления версиями и удобство развертывания. Вот комплексный подход с примерами для популярных CI/CD систем.
Основные принципы тегирования
Перед реализацией определите стратегию тегирования:
- Стабильные теги:
latest,v1.2.3,production - Динамические теги: хеш коммита, ветка, timestamp
- Мета-теги:
v1.2,v1(semantic versioning)
Реализация в GitHub Actions
name: Build and Push Docker Image
on:
push:
branches: [ main, develop ]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
Реализация в GitLab CI
stages:
- build
variables:
DOCKER_TLS_CERTDIR: "/certs"
IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
docker-build:
stage: build
image: docker:24
services:
- docker:24-dind
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- |
# Определяем дополнительные теги
ADDITIONAL_TAGS=""
# Для main ветки добавляем latest
if [ "$CI_COMMIT_BRANCH" = "main" ]; then
ADDITIONAL_TAGS="$ADDITIONAL_TAGS,$CI_REGISTRY_IMAGE:latest"
fi
# Для тегов добавляем semantic versioning
if [ -n "$CI_COMMIT_TAG" ]; then
ADDITIONAL_TAGS="$ADDITIONAL_TAGS,$CI_REGISTRY_IMAGE:$CI_COMMIT_TAG"
# Извлекаем major и minor версии
VERSION=$(echo $CI_COMMIT_TAG | sed 's/^v//')
MAJOR=$(echo $VERSION | cut -d. -f1)
MINOR=$(echo $VERSION | cut -d. -f1-2)
ADDITIONAL_TAGS="$ADDITIONAL_TAGS,$CI_REGISTRY_IMAGE:$MAJOR,$CI_REGISTRY_IMAGE:$MINOR"
fi
# Собираем и пушим с несколькими тегами
docker build -t $IMAGE_TAG .
# Пушим основной тег
docker push $IMAGE_TAG
# Пушим дополнительные теги
if [ -n "$ADDITIONAL_TAGS" ]; then
for tag in $(echo $ADDITIONAL_TAGS | tr ',' ' '); do
docker tag $IMAGE_TAG $tag
docker push $tag
done
fi
rules:
- if: $CI_COMMIT_BRANCH || $CI_COMMIT_TAG
Реализация в Jenkins
pipeline {
agent any
environment {
DOCKER_REGISTRY = 'myregistry.com'
PROJECT_NAME = 'myapp'
COMMIT_SHORT_SHA = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim()
}
stages {
stage('Build and Tag') {
steps {
script {
// Собираем список тегов
def tags = []
// Базовый тег с хешем коммита
tags.add("${DOCKER_REGISTRY}/${PROJECT_NAME}:${COMMIT_SHORT_SHA}")
// Для master ветки
if (env.BRANCH_NAME == 'master') {
tags.add("${DOCKER_REGISTRY}/${PROJECT_NAME}:latest")
// Читаем версию из package.json или другого файла
def version = readJSON(file: 'package.json').version
tags.add("${DOCKER_REGISTRY}/${PROJECT_NAME}:${version}")
tags.add("${DOCKER_REGISTRY}/${PROJECT_NAME}:v${version.split('\\.')[0]}")
}
// Для feature веток
if (env.BRANCH_NAME.startsWith('feature/')) {
def branchTag = env.BRANCH_NAME.replace('feature/', '').replace('/', '-')
tags.add("${DOCKER_REGISTRY}/${PROJECT_NAME}:${branchTag}")
}
// Собираем и тегируем
docker.build("${DOCKER_REGISTRY}/${PROJECT_NAME}", "--tag ${tags.join(' --tag ')} .")
// Пушим все теги
tags.each { tag ->
docker.withRegistry("https://${DOCKER_REGISTRY}", 'docker-credentials') {
docker.image(tag).push()
}
}
}
}
}
}
}
Лучшие практики
- Используйте хеш коммита как базовый тег — обеспечивает точную воспроизводимость сборок
- Автоматизируйте semantic versioning — интегрируйте с CHANGELOG и conventional commits
- Очищайте старые теги — настройте политику retention policy в registry
- Тестируйте перед пушем — запускайте тесты для каждого тегированного образа
- Используйте multi-stage builds — уменьшайте размер финального образа
Скрипт для локальной сборки с несколькими тегами
#!/bin/bash
# build-with-tags.sh
IMAGE_NAME="myapp"
REGISTRY="myregistry.com"
VERSION=$(git describe --tags --always)
COMMIT_SHA=$(git rev-parse --short HEAD)
# Сборка образа
docker build -t ${REGISTRY}/${IMAGE_NAME}:${COMMIT_SHA} .
# Создание дополнительных тегов
docker tag ${REGISTRY}/${IMAGE_NAME}:${COMMIT_SHA} ${REGISTRY}/${IMAGE_NAME}:latest
if [[ $VERSION =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
MAJOR=$(echo $VERSION | cut -d. -f1)
MINOR=$(echo $VERSION | cut -d. -f1-2)
docker tag ${REGISTRY}/${IMAGE_NAME}:${COMMIT_SHA} ${REGISTRY}/${IMAGE_NAME}:${VERSION}
docker tag ${REGISTRY}/${IMAGE_NAME}:${COMMIT_SHA} ${REGISTRY}/${IMAGE_NAME}:${MINOR}
docker tag ${REGISTRY}/${IMAGE_NAME}:${COMMIT_SHA} ${REGISTRY}/${IMAGE_NAME}:${MAJOR}
fi
# Пуш всех тегов
docker push --all-tags ${REGISTRY}/${IMAGE_NAME}
Оптимизация производительности
Для ускорения процесса используйте:
- Buildx с кешированием —
--cache-from,--cache-to - Параллельный пуш тегов — если registry поддерживает
- Артефакты сборки — сохраняйте context между этапами
Такая настройка обеспечивает гибкое тегирование, совместимость с различными окружениями и соответствие принципам semantic versioning, что критически важно для эффективного DevOps-процесса.