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

Hey there! I'm currently working as an Associate DevOps Engineer, and I'm diving into popular DevOps tools like Azure Devops,Linux, Docker, Kubernetes,Terraform and Ansible. I'm also on the learning track with AWS certifications to amp up my cloud game. If you're into tech collaborations and exploring new horizons, let's connect!
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
# 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.0version tag
☸️ Kubernetes Deployment
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
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)
# 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
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
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
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:
selector:
app: bankapp
version: blue # Change to green when needed
🔐 MySQL Setup
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 💙💚



