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
$1
Before we begin, ensure you have:
Setting Up Container Registry 🔧
$1
First, ensure the registry is enabled in your GitLab instance:
`` registry_external_url 'https://registry.example.com'
ruby
`For self-hosted GitLab in gitlab.rb
$1
Log in to the registry:
` docker login registry.example.com
bash
`
$1
Enable Container Registry in project settings:
` variables:
DOCKER_REGISTRY: $CI_REGISTRY
DOCKER_IMAGE: $CI_REGISTRY_IMAGE
yaml
`.gitlab-ci.yml
Managing Docker Images 🐳
$1
` 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
yaml
`.gitlab-ci.yml
$1
` docker tag myapp:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:latest
docker tag myapp:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:v1.0.0
bash
`Tag with version and latest
$1
` 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
dockerfile
`Dockerfile
Security Scanning 🔍
$1
` include:
- template: Security/Container-Scanning.gitlab-ci.yml container_scanning:
variables:
CS_DEFAULT_BRANCH_IMAGE: $CI_REGISTRY_IMAGE:latest
yaml
`.gitlab-ci.yml
$1
` vulnerability_scan:
script:
- trivy image $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
artifacts:
reports:
security: gl-container-scanning-report.json
yaml
`
$1
` rules:
- name: no-critical-vulnerabilities
description: "No critical vulnerabilities allowed"
enabled: true
threshold: critical
yaml
`.gitlab/container-policy.yml
Storage Optimization 📦
$1
` 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
yaml
`
$1
` 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 .
yaml
`
$1
` 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"]
dockerfile
`Optimized Dockerfile
CI/CD Integration ⚡
$1
` 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
yaml
`.gitlab-ci.yml
$1
` 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 .
yaml
`
$1
` integration_test:
services:
- name: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
alias: app
- name: postgres:13-alpine
alias: db
script:
- npm run integration-tests
yaml
`
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
` # Reset Docker credentials
docker logout registry.example.com
docker login registry.example.com
bash
`
2. Push Failures
` # Check registry status
curl -k https://registry.example.com/v2/_catalog
bash
`
3. Storage Problems
` # Clean up dangling images
docker system prune -a
bash
`
Advanced Features 🌟
$1
` curl -H "Authorization: Bearer $TOKEN" \
"https://registry.example.com/v2/_catalog" curl -H "Authorization: Bearer $TOKEN" \
"https://registry.example.com/v2/project/tags/list"
bash
`List repositories
List tags
$1
` [[registry.mirrors]]
location = "us-east-1"
url = "https://registry-1.docker.io"
yaml
`config.toml
$1
` cp domain.crt /etc/docker/certs.d/registry.example.com/ca.crt
bash
`Add custom certificate
Monitoring and Maintenance 📊
$1
` metrics:
enabled: true
port: 5001
yaml
`prometheus metrics
$1
` curl -k https://registry.example.com/v2/_catalog
bash
`Check registry health
$1
` tar -czf registry-backup.tar.gz /var/lib/registry
bash
``Backup registry data
Conclusion 🎉
You've learned how to:
Remember to:
Need help? Check out:
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.