9.9 KiB
CI/CD Pipeline
Automated build and deployment pipeline using Git-based CI/CD systems.
Overview
The CI/CD pipeline automatically builds Docker images and pushes them to the container registry whenever code is pushed to any branch.
Repository: Git repository with application code
Registry: Container registry for Docker images
Pipeline Architecture
Git Push (any branch)
↓
CI/CD System Trigger
↓
┌─────────────────────────────────────┐
│ Job: build-web (parallel) │
│ Job: build-api (parallel) │
└─────────────────────────────────────┘
↓ ↓
Build Web Image Build API Image
↓ ↓
Tag with branch Tag with branch
↓ ↓
Push to Registry Push to Registry
↓ ↓
<registry>/web:<branch>
<registry>/api:<branch>
Workflow Configuration
Location: CI/CD workflow files (.github/workflows/, .gitlab-ci.yml, etc.)
name: Build and Push Docker Images
on:
push:
workflow_dispatch:
jobs:
build-web:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Container Registry
uses: docker/login-action@v3
with:
registry: <registry-url>
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_TOKEN }}
- name: Extract metadata for web image
id: meta-web
uses: docker/metadata-action@v5
with:
images: <registry>/web
tags: |
type=ref,event=branch
- name: Build and push web image
uses: docker/build-push-action@v5
with:
context: ./web
file: ./web/Dockerfile
push: true
tags: ${{ steps.meta-web.outputs.tags }}
labels: ${{ steps.meta-web.outputs.labels }}
cache-from: type=registry,ref=<registry>/web:buildcache
cache-to: type=registry,ref=<registry>/web:buildcache,mode=max
build-api:
runs-on: ubuntu-latest
steps:
# Similar steps for API application
...
Trigger Events
Automatic Triggers
Push to any branch:
git push origin <branch-name>
Images tagged with branch name:
<registry>/web:<branch-name><registry>/api:<branch-name>
Manual Trigger
Via CI/CD Interface:
- Go to repository → CI/CD or Actions
- Select workflow: Build and Push Docker Images
- Click: Run workflow
- Select branch
- Click: Run
Via Git:
# Trigger workflow with empty commit
git commit --allow-empty -m "Trigger CI/CD pipeline"
git push
Setup Instructions
1. Create Registry Token
Generate Token:
- Go to: User Settings or Access Tokens
- Click: Generate New Token
- Name:
container-registry - Select appropriate permissions:
- ✅ Write/push access (required)
- ✅ Read/pull access (required)
- Click: Generate Token
- Copy token (shown once only)
2. Add Repository Secret
In Repository Settings:
- Go to: Repository → Settings → Secrets/Variables
- Click: Add Secret
- Add required secrets:
REGISTRY_TOKEN: Token from step 1REGISTRY_USER: Username
- Click: Save
3. Verify Workflow
Check workflow file exists:
ls -la .github/workflows/ # or appropriate CI/CD directory
Push to trigger:
git add .
git commit -m "Test CI/CD pipeline"
git push origin main
Monitor execution:
- Go to repository → CI/CD or Actions
- Click on the running workflow
- View logs for each job
Image Naming Convention
Format: <registry>/<namespace>/<app>:<tag>
Examples:
<registry>/web:main<registry>/web:develop<registry>/web:feature-xyz<registry>/api:main
Using Built Images in Kubernetes
1. Pull Images from Container Registry
Create registry secret:
kubectl create secret docker-registry registry-secret \
--docker-server=<registry-url> \
--docker-username=<USERNAME> \
--docker-password=<TOKEN> \
-n <namespace>
2. Update Deployment
deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: <namespace>
spec:
template:
spec:
imagePullSecrets:
- name: registry-secret
containers:
- name: web
image: <registry>/web:main
imagePullPolicy: Always
3. Deploy to Kubernetes
kubectl apply -f deployment.yaml
4. Rollout New Version
After pipeline builds new image:
# Force rollout restart (pulls latest image with same tag)
kubectl rollout restart deployment/web -n <namespace>
kubectl rollout restart deployment/api -n <namespace>
# Check rollout status
kubectl rollout status deployment/web -n <namespace>
Or update image explicitly:
kubectl set image deployment/web \
web=<registry>/web:main \
-n <namespace>
kubectl set image deployment/api \
api=<registry>/api:main \
-n <namespace>
Docker Layer Caching
The pipeline uses Docker layer caching to speed up builds:
Cache Configuration:
cache-from: type=registry,ref=<registry>/web:buildcache
cache-to: type=registry,ref=<registry>/web:buildcache,mode=max
Benefits:
- Faster builds (reuses unchanged layers)
- Reduced build time from ~3min to ~30sec
- Lower resource usage
Cache Location: Stored in registry as special tag :buildcache
Parallel Builds
Both applications build in parallel:
Start
├─→ build-web job (3-5 min)
└─→ build-api job (3-5 min)
↓
Complete (~5 min total)
Without parallelization: ~10 minutes With parallelization: ~5 minutes
Viewing Build Logs
Via CI/CD Interface
- Repository → CI/CD or Actions
- Click on workflow run
- Select job (
build-weborbuild-api) - View step-by-step logs
Via CLI (if available)
# List workflow runs
<cli-tool> list runs
# View specific run logs
<cli-tool> view run <run-id>
Troubleshooting
Build Fails: Authentication Error
Error: unauthorized: authentication required
Solution:
- Verify registry secrets exist in repository settings
- Check token has appropriate permissions
- Regenerate token if expired
# Test token manually
docker login <registry-url> -u <USERNAME> -p <TOKEN>
Build Fails: Dockerfile Not Found
Error: unable to prepare context: unable to evaluate symlinks in Dockerfile path
Solution:
- Check Dockerfile exists in correct location:
web/Dockerfileapi/Dockerfile
- Verify workflow context path matches:
context: ./web file: ./web/Dockerfile
Image Pull Fails in Kubernetes
Error: ImagePullBackOff
Solution:
-
Verify registry secret exists:
kubectl get secret registry-secret -n <namespace> -
Check secret is referenced in deployment:
spec: template: spec: imagePullSecrets: - name: registry-secret -
Test manual pull:
docker pull <registry>/web:main
Workflow Doesn't Trigger
Check:
- ✅ Workflow file in appropriate CI/CD directory
- ✅ File is named correctly (
.ymlor.yaml) - ✅ File is committed and pushed to repository
- ✅ CI/CD is enabled in repository settings
Force trigger:
git commit --allow-empty -m "Trigger workflow"
git push
Best Practices
Version Tagging
For production deployments:
# Tag release
git tag -a v1.0.0 -m "Release v1.0.0"
git push origin v1.0.0
Update workflow for semantic versioning:
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
Branch Strategy
Recommended:
main→ production imagesdevelop→ staging imagesfeature/*→ development images
Kubernetes deployments:
# Production
image: <registry>/web:main
# Staging
image: <registry>/web:develop
# Development
image: <registry>/web:feature-xyz
Security
Protect main branch:
- Repository Settings → Branches or Protected Branches
- Add branch protection for
main - Require pull/merge request reviews
- Enable status checks
Rotate tokens regularly:
- Generate new registry token every 90 days
- Update secrets in repository settings
Advanced Configuration
Multi-Stage Builds
Optimize Dockerfile for smaller images:
# Build stage
FROM python:3.11-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt
# Runtime stage
FROM python:3.11-slim
WORKDIR /app
COPY --from=builder /root/.local /root/.local
COPY . .
ENV PATH=/root/.local/bin:$PATH
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Build Arguments
Pass build-time variables:
- name: Build and push
uses: docker/build-push-action@v5
with:
build-args: |
VERSION=${{ github.sha }}
BUILD_DATE=${{ github.event.head_commit.timestamp }}
Matrix Builds
Build for multiple platforms:
strategy:
matrix:
platform: [linux/amd64, linux/arm64]
- name: Build and push
uses: docker/build-push-action@v5
with:
platforms: ${{ matrix.platform }}
Monitoring Pipeline
Metrics to Track
- ✅ Build success rate
- ✅ Average build time
- ✅ Cache hit rate
- ✅ Image size trends
Notifications
Add Discord/Slack notifications (example):
- name: Notify on failure
if: failure()
run: |
curl -X POST ${{ secrets.WEBHOOK_URL }} \
-H 'Content-Type: application/json' \
-d '{"content":"Build failed for ${{ github.ref }}"}'
Automated CI/CD pipeline for building and deploying containerized applications.