Gitlab
GitlabIntermediate

GitLab Container Registry: A Complete Guide to Docker Image Management

DeveloperHat Team
5 min read
GitLabDockerContainer RegistryDevOpsCI/CD

TL;DR

Learn how to effectively use GitLab Container Registry for storing, managing, and distributing Docker images, including security scanning and optimization techniques.

Introduction 🚀

GitLab Container Registry is a secure and private registry for Docker images. In this comprehensive guide, we'll explore how to effectively use GitLab's Container Registry to store, manage, and distribute your Docker images.

$1

  • Setting up GitLab Container Registry
  • Managing Docker images
  • Implementing security scanning
  • Optimizing storage and performance
  • Integrating with CI/CD pipelines
  • $1

    Before we begin, ensure you have:

  • GitLab account (Free or higher tier)
  • Docker installed locally
  • Basic understanding of Docker concepts
  • GitLab CI/CD pipeline experience
  • Setting Up Container Registry 🔧

    $1

    First, ensure the registry is enabled in your GitLab instance:

    ``ruby

    For self-hosted GitLab in gitlab.rb

    registry_external_url 'https://registry.example.com'

    `

    $1

    Log in to the registry:

    `bash

    docker login registry.example.com

    `

    $1

    Enable Container Registry in project settings:

    `yaml

    .gitlab-ci.yml

    variables:

    DOCKER_REGISTRY: $CI_REGISTRY

    DOCKER_IMAGE: $CI_REGISTRY_IMAGE

    `

    Managing Docker Images 🐳

    $1

    `yaml

    .gitlab-ci.yml

    build:

    image: docker:latest

    services:

    - docker:dind

    script:

    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .

    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

    `

    $1

    `bash

    Tag with version and latest

    docker tag myapp:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:latest

    docker tag myapp:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:v1.0.0

    `

    $1

    `dockerfile

    Dockerfile

    FROM node:16 AS builder

    WORKDIR /app

    COPY package*.json ./

    RUN npm install

    COPY . .

    RUN npm run build

    FROM nginx:alpine

    COPY --from=builder /app/dist /usr/share/nginx/html

    `

    Security Scanning 🔍

    $1

    `yaml

    .gitlab-ci.yml

    include:

    - template: Security/Container-Scanning.gitlab-ci.yml

    container_scanning:

    variables:

    CS_DEFAULT_BRANCH_IMAGE: $CI_REGISTRY_IMAGE:latest

    `

    $1

    `yaml

    vulnerability_scan:

    script:

    - trivy image $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

    artifacts:

    reports:

    security: gl-container-scanning-report.json

    `

    $1

    `yaml

    .gitlab/container-policy.yml

    rules:

    - name: no-critical-vulnerabilities

    description: "No critical vulnerabilities allowed"

    enabled: true

    threshold: critical

    `

    Storage Optimization 📦

    $1

    `yaml

    cleanup_registry:

    script:

    - |

    for tag in $(gitlab-registry-cleanup list-tags); do

    if [[ $tag =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then

    continue

    fi

    gitlab-registry-cleanup delete-tag $tag

    done

    `

    $1

    `yaml

    build_with_cache:

    script:

    - docker pull $CI_REGISTRY_IMAGE:latest || true

    - docker build

    --cache-from $CI_REGISTRY_IMAGE:latest

    -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .

    `

    $1

    `dockerfile

    Optimized Dockerfile

    FROM node:16-alpine AS builder

    WORKDIR /app

    COPY package*.json ./

    RUN npm ci --only=production

    COPY . .

    FROM alpine:latest

    RUN apk --no-cache add nodejs

    COPY --from=builder /app /app

    WORKDIR /app

    CMD ["node", "index.js"]

    `

    CI/CD Integration ⚡

    $1

    `yaml

    .gitlab-ci.yml

    stages:

    - build

    - test

    - deploy

    build_image:

    stage: build

    script:

    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .

    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

    test_image:

    stage: test

    script:

    - docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

    - docker run --rm $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA npm test

    deploy_image:

    stage: deploy

    script:

    - docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

    - docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:latest

    - docker push $CI_REGISTRY_IMAGE:latest

    `

    $1

    `yaml

    build_staging:

    script:

    - docker build

    --build-arg ENV=staging

    -t $CI_REGISTRY_IMAGE:staging .

    build_production:

    script:

    - docker build

    --build-arg ENV=production

    -t $CI_REGISTRY_IMAGE:production .

    `

    $1

    `yaml

    integration_test:

    services:

    - name: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

    alias: app

    - name: postgres:13-alpine

    alias: db

    script:

    - npm run integration-tests

    `

    Best Practices Checklist ✅

    1. Registry Management

    - [ ] Enable registry cleanup policies

    - [ ] Implement proper tagging strategy

    - [ ] Configure access controls

    2. Security

    - [ ] Enable container scanning

    - [ ] Implement vulnerability policies

    - [ ] Regular security updates

    3. Performance

    - [ ] Use multi-stage builds

    - [ ] Implement layer caching

    - [ ] Optimize image sizes

    Troubleshooting Guide 🔧

    Common issues and solutions:

    1. Authentication Issues

    `bash

    # Reset Docker credentials

    docker logout registry.example.com

    docker login registry.example.com

    `

    2. Push Failures

    `bash

    # Check registry status

    curl -k https://registry.example.com/v2/_catalog

    `

    3. Storage Problems

    `bash

    # Clean up dangling images

    docker system prune -a

    `

    Advanced Features 🌟

    $1

    `bash

    List repositories

    curl -H "Authorization: Bearer $TOKEN" \

    "https://registry.example.com/v2/_catalog"

    List tags

    curl -H "Authorization: Bearer $TOKEN" \

    "https://registry.example.com/v2/project/tags/list"

    `

    $1

    `yaml

    config.toml

    [[registry.mirrors]]

    location = "us-east-1"

    url = "https://registry-1.docker.io"

    `

    $1

    `bash

    Add custom certificate

    cp domain.crt /etc/docker/certs.d/registry.example.com/ca.crt

    `

    Monitoring and Maintenance 📊

    $1

    `yaml

    prometheus metrics

    metrics:

    enabled: true

    port: 5001

    `

    $1

    `bash

    Check registry health

    curl -k https://registry.example.com/v2/_catalog

    `

    $1

    `bash

    Backup registry data

    tar -czf registry-backup.tar.gz /var/lib/registry

    ``

    Conclusion 🎉

    You've learned how to:

  • Set up and configure GitLab Container Registry
  • Manage Docker images effectively
  • Implement security scanning
  • Optimize storage and performance
  • Integrate with CI/CD pipelines
  • Remember to:

  • Regularly update base images
  • Monitor registry usage
  • Implement security best practices
  • Maintain proper documentation
  • Need help? Check out:

  • GitLab Container Registry documentation
  • Docker documentation
  • Community forums
  • Happy containerizing! 🚀

    Why This Matters

    Understanding the business and technical context helps you make informed decisions rather than blindly following patterns.

    Trade-offs to Consider

    Every architectural decision involves trade-offs. Consider your specific requirements, team expertise, and scale when evaluating options.

    When NOT to Use This

    Knowing when a solution doesn't apply is as valuable as knowing when it does. Consider alternatives for your specific situation.

    Decision Framework

    Use this framework to evaluate whether this approach is right for your use case based on your specific constraints and requirements.