# Day 10 – GitLab CI/CD for Python & Using GitLab Container Registry

Today, I set up a complete CI/CD pipeline using **GitLab** for a **Python FastAPI** application, and published the Docker image to **GitLab’s Container Registry**.

### 🐳 Dockerfile for Python FastAPI App

```plaintext
# Base Python image
FROM python:3.12-slim

# Set working directory inside the container
WORKDIR /usr/local/app

# Copy requirements and install dependencies
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

# Copy application code
COPY src ./src

# Expose the application port
EXPOSE 8000

# Create and switch to non-root user
RUN useradd app
USER app

# Run the app
CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]
```

### 🛠 GitLab CI/CD Setup

* Built Docker image in GitLab pipeline
    
* Pushed it to GitLab’s private container registry
    
* Used `:1.2.0` version tag
    

### ☸️ Kubernetes Deployment

```plaintext
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mypythonapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mypythonapp
  template:
    metadata:
      labels:
        app: mypythonapp
    spec:
      containers:
        - name: mypythonapp
          image: gitlab.hassandevops.site:5050/ramdanbootcamp/multistage-python-cicd:1.2.0
          ports:
            - containerPort: 8000
      imagePullSecrets:
        - name: gitlab-registry-secret
```

### 🌐 Ingress with TLS

```plaintext
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: mypythonapp-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: "/"
spec:
  rules:
    - host: python.hassandevops.site
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: mypythonapp-svc
                port:
                  number: 80
  tls:
    - hosts:
        - python.hassandevops.site
      secretName: hassandevops-tls
```

✅ FastAPI containerized, published, and deployed to Kubernetes with GitLab CI/CD. SSL configured and domain routing set. Solid progress!

---

## 🚀 Day 9 – Blue-Green Deployment with GitLab CI/CD (Spring Boot)

Today was all about **zero-downtime deployments**. I implemented a **Blue-Green Deployment strategy** for a Spring Boot app using GitLab CI/CD and Kubernetes.

### 🐳 Multistage Dockerfile (Java App)

```plaintext
# Stage 1: Build
FROM eclipse-temurin:17-jdk-alpine AS builder
WORKDIR /usr/src/app
COPY . .
RUN chmod +x mvnw
RUN ./mvnw clean package -DskipTests

# Stage 2: Runtime
FROM eclipse-temurin:17-jdk-alpine
WORKDIR /usr/src/app
COPY --from=builder /usr/src/app/target/*.jar app.jar
EXPOSE 8080
CMD ["java", "-jar", "app.jar"]
```

### 🔁 GitLab CI/CD Pipeline with Kaniko

```plaintext
stages:
  - build
  - deploy

build-Blue:
  stage: build
  image: gcr.io/kaniko-project/executor:v1.23.2-debug
  script:
    - /kaniko/executor --context "${CI_PROJECT_DIR}" --dockerfile "${CI_PROJECT_DIR}/Dockerfile" --destination "${CI_REGISTRY_IMAGE}:Blue"

build-Green:
  stage: build
  image: gcr.io/kaniko-project/executor:v1.23.2-debug
  script:
    - /kaniko/executor --context "${CI_PROJECT_DIR}" --dockerfile "${CI_PROJECT_DIR}/Dockerfile" --destination "${CI_REGISTRY_IMAGE}:Green"

deploy-job:
  stage: deploy
  image: alpine:latest
  before_script:
    - apk add --no-cache openssh sshpass
  script:
    - sshpass -p "$MICROK8S_PASSWORD" scp -o StrictHostKeyChecking=no k8s/*.yml ${MICROK8S_USERNAME}@${MICROK8S_IP_ADDRESS}:/path/
    - sshpass -p "$MICROK8S_PASSWORD" ssh -o StrictHostKeyChecking=no ${MICROK8S_USERNAME}@${MICROK8S_IP_ADDRESS} "cd /path && microk8s.kubectl apply -f ."
```

### ☸️ Blue & Green Deployments

Both versions are deployed, but only one serves traffic at a time.

#### `bankapp-blue` Deployment

```plaintext
metadata:
  name: bankapp-blue
spec:
  selector:
    matchLabels:
      app: bankapp
      version: blue
  template:
    metadata:
      labels:
        app: bankapp
        version: blue
    spec:
      containers:
        - image: ...:Blue
```

#### `bankapp-green` Deployment

```plaintext
metadata:
  name: bankapp-green
spec:
  selector:
    matchLabels:
      app: bankapp
      version: green
  template:
    metadata:
      labels:
        app: bankapp
        version: green
    spec:
      containers:
        - image: ...:Green
```

### 💡 Switching Traffic

The service selector decides which version is live:

```plaintext
selector:
  app: bankapp
  version: blue  # Change to green when needed
```

### 🔐 MySQL Setup

```plaintext
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  containers:
    - image: mysql:8
      env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              key: MYSQL_ROOT_PASSWORD
```

---

✅ Now I can deploy, test, and switch versions in Kubernetes **without downtime**. All thanks to **GitLab CI/CD + Blue-Green Strategy** 💙💚
