# 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 ↓ ↓ /web: /api: ``` ## Workflow Configuration **Location**: CI/CD workflow files (`.github/workflows/`, `.gitlab-ci.yml`, etc.) ```yaml 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: username: ${{ secrets.REGISTRY_USER }} password: ${{ secrets.REGISTRY_TOKEN }} - name: Extract metadata for web image id: meta-web uses: docker/metadata-action@v5 with: images: /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=/web:buildcache cache-to: type=registry,ref=/web:buildcache,mode=max build-api: runs-on: ubuntu-latest steps: # Similar steps for API application ... ``` ## Trigger Events ### Automatic Triggers **Push to any branch**: ```bash git push origin ``` Images tagged with branch name: - `/web:` - `/api:` ### Manual Trigger **Via CI/CD Interface**: 1. Go to repository → **CI/CD** or **Actions** 2. Select workflow: **Build and Push Docker Images** 3. Click: **Run workflow** 4. Select branch 5. Click: **Run** **Via Git**: ```bash # Trigger workflow with empty commit git commit --allow-empty -m "Trigger CI/CD pipeline" git push ``` ## Setup Instructions ### 1. Create Registry Token **Generate Token**: 1. Go to: **User Settings** or **Access Tokens** 2. Click: **Generate New Token** 3. Name: `container-registry` 4. Select appropriate permissions: - ✅ Write/push access (required) - ✅ Read/pull access (required) 5. Click: **Generate Token** 6. **Copy token** (shown once only) ### 2. Add Repository Secret **In Repository Settings**: 1. Go to: **Repository → Settings → Secrets/Variables** 2. Click: **Add Secret** 3. Add required secrets: - `REGISTRY_TOKEN`: Token from step 1 - `REGISTRY_USER`: Username 4. Click: **Save** ### 3. Verify Workflow **Check workflow file exists**: ```bash ls -la .github/workflows/ # or appropriate CI/CD directory ``` **Push to trigger**: ```bash git add . git commit -m "Test CI/CD pipeline" git push origin main ``` **Monitor execution**: 1. Go to repository → **CI/CD** or **Actions** 2. Click on the running workflow 3. View logs for each job ## Image Naming Convention **Format**: `//:` **Examples**: - `/web:main` - `/web:develop` - `/web:feature-xyz` - `/api:main` ## Using Built Images in Kubernetes ### 1. Pull Images from Container Registry **Create registry secret**: ```bash kubectl create secret docker-registry registry-secret \ --docker-server= \ --docker-username= \ --docker-password= \ -n ``` ### 2. Update Deployment **deployment.yaml**: ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: web namespace: spec: template: spec: imagePullSecrets: - name: registry-secret containers: - name: web image: /web:main imagePullPolicy: Always ``` ### 3. Deploy to Kubernetes ```bash kubectl apply -f deployment.yaml ``` ### 4. Rollout New Version **After pipeline builds new image**: ```bash # Force rollout restart (pulls latest image with same tag) kubectl rollout restart deployment/web -n kubectl rollout restart deployment/api -n # Check rollout status kubectl rollout status deployment/web -n ``` **Or update image explicitly**: ```bash kubectl set image deployment/web \ web=/web:main \ -n kubectl set image deployment/api \ api=/api:main \ -n ``` ## Docker Layer Caching The pipeline uses Docker layer caching to speed up builds: **Cache Configuration**: ```yaml cache-from: type=registry,ref=/web:buildcache cache-to: type=registry,ref=/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 1. Repository → **CI/CD** or **Actions** 2. Click on workflow run 3. Select job (`build-web` or `build-api`) 4. View step-by-step logs ### Via CLI (if available) ```bash # List workflow runs list runs # View specific run logs view run ``` ## Troubleshooting ### Build Fails: Authentication Error **Error**: `unauthorized: authentication required` **Solution**: 1. Verify registry secrets exist in repository settings 2. Check token has appropriate permissions 3. Regenerate token if expired ```bash # Test token manually docker login -u -p ``` ### Build Fails: Dockerfile Not Found **Error**: `unable to prepare context: unable to evaluate symlinks in Dockerfile path` **Solution**: 1. Check Dockerfile exists in correct location: - `web/Dockerfile` - `api/Dockerfile` 2. Verify workflow context path matches: ```yaml context: ./web file: ./web/Dockerfile ``` ### Image Pull Fails in Kubernetes **Error**: `ImagePullBackOff` **Solution**: 1. Verify registry secret exists: ```bash kubectl get secret registry-secret -n ``` 2. Check secret is referenced in deployment: ```yaml spec: template: spec: imagePullSecrets: - name: registry-secret ``` 3. Test manual pull: ```bash docker pull /web:main ``` ### Workflow Doesn't Trigger **Check**: 1. ✅ Workflow file in appropriate CI/CD directory 2. ✅ File is named correctly (`.yml` or `.yaml`) 3. ✅ File is committed and pushed to repository 4. ✅ CI/CD is enabled in repository settings **Force trigger**: ```bash git commit --allow-empty -m "Trigger workflow" git push ``` ## Best Practices ### Version Tagging **For production deployments**: ```bash # Tag release git tag -a v1.0.0 -m "Release v1.0.0" git push origin v1.0.0 ``` **Update workflow for semantic versioning**: ```yaml tags: | type=ref,event=branch type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} ``` ### Branch Strategy **Recommended**: - `main` → production images - `develop` → staging images - `feature/*` → development images **Kubernetes deployments**: ```yaml # Production image: /web:main # Staging image: /web:develop # Development image: /web:feature-xyz ``` ### Security **Protect main branch**: 1. Repository Settings → **Branches** or **Protected Branches** 2. Add branch protection for `main` 3. Require pull/merge request reviews 4. 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: ```dockerfile # 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: ```yaml - 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: ```yaml 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): ```yaml - 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.*