DEV Community

Cover image for Building a Complete DevOps Pipeline: Flask App with Docker, Jenkins, GitHub Actions, Prometheus, and Grafana
Abhiraj Adhikary
Abhiraj Adhikary

Posted on

Building a Complete DevOps Pipeline: Flask App with Docker, Jenkins, GitHub Actions, Prometheus, and Grafana

In today's fast-paced software development world, DevOps practices are essential for streamlining workflows, ensuring reliable deployments, and monitoring applications effectively. This tutorial walks you through a hands-on DevOps project using Flask as the web framework, Pytest and Playwright for testing, Docker for containerization, GitHub Actions and Jenkins for CI/CD, and Prometheus with Grafana for monitoring. Whether you're a beginner or an experienced engineer, this guide will help you build, test, deploy, and monitor a simple Flask app.

By the end, you'll have a production-ready setup that demonstrates key DevOps principles like automation, containerization, and observability. Let's dive in!

Project Overview: What We're Building

This DevOps project creates a basic Flask web application that serves a simple HTML template. We integrate testing, containerization, CI/CD pipelines, and monitoring to create a robust ecosystem. Key tools include:

  • Flask: For the backend web app.
  • Pytest & Playwright: For unit and end-to-end (E2E) testing.
  • Docker: For building and orchestrating containers.
  • GitHub Actions & Jenkins: For automated CI/CD.
  • Prometheus & Grafana: For metrics collection and visualization.

The full source code is available on GitHub. Keywords: DevOps tutorial, Flask Docker CI/CD, Prometheus Grafana monitoring.

Step 1: Setting Up the Flask Application

Start by creating a simple Flask app. Install dependencies like flask and prometheus_flask_exporter for metrics exposure.

Here's the core app.py code:

from flask import Flask, render_template
from prometheus_flask_exporter import PrometheusMetrics

app = Flask(__name__)
metrics = PrometheusMetrics(app)

@app.route('/')
def home():
    return render_template('index.html')

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
Enter fullscreen mode Exit fullscreen mode

This app renders an index.html from the templates folder and exposes metrics at /metrics. The static folder holds CSS styles for a polished UI. Run it locally with python app.py and access at http://localhost:5000.

For SEO: Flask web app tutorial, Python DevOps project.

Step 2: Implementing Tests with Pytest and Playwright

Testing is crucial in DevOps. We use Pytest for backend unit tests and Playwright for E2E browser automation.

Install libraries: pip install pytest playwright.

  • Backend Tests (tests/test_app.py): Verifies routes and responses.

Example test:

  from app import app

  def test_home():
      client = app.test_client()
      response = client.get('/')
      assert response.status_code == 200
Enter fullscreen mode Exit fullscreen mode
  • E2E Tests (tests/test_e2e.py): Simulates browser interactions.

Run the app first, then pytest. All 4 tests (2 backend, 2 E2E) should pass. Note: Keep the app running on localhost:5000 for Playwright to test the UI.

This ensures code quality before deployment. Keywords: Pytest Playwright tutorial, automated testing DevOps.

Step 3: Containerizing with Docker

Docker makes deployments consistent. We use a multistage Dockerfile for efficiency:

# Builder stage
FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .

# Runtime stage
FROM python:3.12-slim
WORKDIR /app
COPY --from=builder /app .
EXPOSE 5000
CMD ["python", "app.py"]
Enter fullscreen mode Exit fullscreen mode

Build and push: docker build -t yourusername/flask-app:latest . and docker push yourusername/flask-app:latest.

For orchestration, docker-compose.yml spins up the full stack:

version: '3'
services:
  app:
    build: .
    ports:
      - "5000:5000"
  prometheus:
    image: prom/prometheus
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    ports:
      - "9090:9090"
  grafana:
    image: grafana/grafana
    ports:
      - "3000:3000"
  jenkins:
    image: jenkins/jenkins:lts
    ports:
      - "8080:8080"
      - "50000:50000"
    volumes:
      - jenkins_home:/var/jenkins_home
volumes:
  jenkins_home:
Enter fullscreen mode Exit fullscreen mode

Run with docker-compose up. Access services at:

  • Flask: http://localhost:5000
  • Prometheus: http://localhost:9090
  • Grafana: http://localhost:3000
  • Jenkins: http://localhost:8080

The prometheus.yml configures scraping:

scrape_configs:
  - job_name: 'flask'
    scrape_interval: 15s
    metrics_path: '/metrics'
    static_configs:
      - targets: ['app:5000']
Enter fullscreen mode Exit fullscreen mode

Keywords: Docker multistage build, Docker Compose DevOps.

Step 4: CI/CD with GitHub Actions and Jenkins

Automation is the heart of DevOps.

  • GitHub Actions (.github/workflows/ci.yml): Triggers on push/PR to main. Tests, builds, and pushes Docker image if tests pass.
  name: CI
  on: [push, pull_request]
  jobs:
    build:
      runs-on: ubuntu-latest
      steps:
        - uses: actions/checkout@v2
        - name: Set up Python
          uses: actions/setup-python@v2
          with: { python-version: '3.12' }
        - run: pip install -r requirements.txt
        - run: pytest
        - name: Build and Push Docker
          if: success()
          uses: docker/build-push-action@v2
          with:
            push: true
            tags: yourusername/flask-app:latest
Enter fullscreen mode Exit fullscreen mode
  • Jenkins (Jenkinsfile): Pipeline for build, test, and deploy.
  pipeline {
      agent { docker { image 'python:3.12' } }
      stages {
          stage('Build') { steps { sh 'pip install -r requirements.txt' } }
          stage('Test') { steps { sh 'pytest' } }
          stage('Deploy') {
              steps {
                  withCredentials([usernamePassword(credentialsId: 'dockerhub', usernameVariable: 'USER', passwordVariable: 'PASS')]) {
                      sh 'docker build -t $USER/flask-app:latest .'
                      sh 'echo $PASS | docker login -u $USER --password-stdin'
                      sh 'docker push $USER/flask-app:latest'
                  }
              }
          }
      }
  }
Enter fullscreen mode Exit fullscreen mode

Setup Jenkins: Install Docker, Docker Pipeline, and Git plugins. Restart at http://localhost:8080/restart. Create a pipeline with your GitHub repo.

Keywords: Jenkins CI/CD pipeline, GitHub Actions Docker push.

Step 5: Monitoring with Prometheus and Grafana

Expose metrics via prometheus_flask_exporter. In Grafana, add Prometheus as data source (http://prometheus:9090), create dashboards for app metrics like requests and response times.

This setup provides real-time insights. Keywords: Prometheus Grafana tutorial, Flask monitoring DevOps.

Conclusion: Why This DevOps Project Matters

This project showcases a full DevOps lifecycle: from coding and testing to deployment and monitoring. It's scalable, automated, and observable—perfect for modern apps. Fork the repo, experiment, and level up your skills!

For more repos, follow me on GitHub. Share your thoughts in the comments!

Top comments (0)