When I first opened GitLab and saw the Projects section, I'll admit, it was exciting to explore. I am familiar with GitHub but not GitLab.
I've explored pipelines, Docker, and DevSecOps, mostly in theory but I'd never built a pipeline myself.
So, I decided to find a simple project and learn how GitLab pipelines actually work.
This article is that journey... a step-by-step guide for beginners who want to see security, automation, and code come together in one workflow.
π§ What You'll Learn
By following along, you'll learn how to:
- Set up a GitLab project from scratch
- Create a Python app
- Build a Docker image
- Configure a GitLab CI/CD pipeline
- Add a security scan using Bandit
- Understand what happens in each stage of the pipeline
No home lab, AWS account, or complex setup is required.. you can do everything inside GitLab.
π Step 1: Create Your GitLab Project
- Go to GitLab.com and sign up.
- On your dashboard, click New Project β Create Blank Project.
- Enter:
- Project Name:
secure-pipeline-demo - Visibility: Public (optional but good for portfolios)
- β Check Initialize repository with README
- Project Name:
Click Create Project, and you'll have an empty repo ready to go.
Note: You may have to verify your account before being able to complete.
π§± Step 2: Add Your First Python File
From your new project page, go to Repository β Web IDE and create a
new file called main.py.
If you have trouble locating Repository, look for the code button, you'll see open with β Web IDE.
def greet():
print("Hello from the Secure CI/CD Pipeline Demo!")
if __name__ == "__main__":
greet()
Commit the change to the main branch.
This tiny file will be our "application"... simple, but perfect for testing automation.
βοΈ Step 3: Create the .gitlab-ci.yml Pipeline File
In the root of your project, create a new file named .gitlab-ci.yml.
This file tells GitLab exactly how to build, test, and scan your project.
Here's the full version you'll use:
# ======================================
# Secure CI/CD Pipeline Demo
# ======================================
# Include GitLab's built-in security scans
include:
- template: Security/SAST.gitlab-ci.yml
stages:
- build
- docker_build
- test
- security_scan
# -----------------------
# 1. Build Stage
# -----------------------
build:
stage: build
script:
- echo "Building project..."
- mkdir dist
- cp main.py dist/
artifacts:
paths:
- dist/
expire_in: 1 week
# -----------------------
# 2. Docker Build Stage
# -----------------------
docker_build:
stage: docker_build
image: docker:24
services:
- docker:dind
variables:
DOCKER_HOST: tcp://docker:2375/
DOCKER_DRIVER: overlay2
script:
- echo "Building Docker image from Dockerfile..."
- docker build -t secure-demo:latest -f Dockerfile .
- echo "β
Docker image built successfully."
artifacts:
paths:
- Dockerfile
expire_in: 1 week
# -----------------------
# 3. Test Stage
# -----------------------
test:
stage: test
image: python:3.9
script:
- echo "Running syntax test..."
- python3 -m py_compile main.py
# -----------------------
# 4. Security Scan Stage
# -----------------------
security_scan:
stage: security_scan
image: python:3.9
script:
- echo "Installing Bandit..."
- pip install bandit
- echo "Running security scan..."
- bandit -r . -f txt -o bandit-report.txt
- echo "β
Security scan complete. Report generated at bandit-report.txt"
artifacts:
paths:
- bandit-report.txt
when: always
Commit this file.
π‘ What it does:
- Each section defines a stage of your pipeline
- GitLab runs them in order: build β docker_build β test β security_scan
- The
include:line adds GitLab's own built-in SAST template for extra security checks
π Step 4: Add a Dockerfile
Pipelines that build Docker images need a Dockerfile.
Create one in the root of your project (same level as .gitlab-ci.yml).
Make sure it's named exactly Dockerfile (case sensitive!).
# =======================================
# Dockerfile for Secure CI/CD Pipeline Demo
# =======================================
FROM python:3.9-slim
WORKDIR /app
COPY main.py /app/
CMD ["python", "main.py"]
Commit it and return to your project's main page.
π Step 5: Watch Your Pipeline Run
Now go to CI/CD β Pipelines.
You'll see a new pipeline triggered automatically.
It should look something like this:
build β docker_build β test β security_scan
Click each stage to view the job logs.
You'll see output such as:
Building Docker image from Dockerfile...
Successfully built abc123
β
Docker image built successfully.
Running security scan...
No issues identified.
β
Security scan complete.
If all stages turn green, congratulations... you just ran your first full
GitLab CI/CD pipeline! π
π Step 6: Analyze Security with Bandit
The security_scan stage uses Bandit, a Python static analysis tool
that checks for vulnerabilities.
To see it in action, edit main.py and add a small (intentional) issue:
import os
def greet():
password = "supersecret" # hardcoded password
os.system("ls") # command injection risk
print("Hello from the Secure CI/CD Pipeline Demo!")
if __name__ == "__main__":
greet()
Commit and rerun the pipeline.
Open security_scan β Job Log to view Bandit's report:
>> Issue: [B105:hardcoded_password_string] Possible hardcoded password
Severity: MEDIUM Confidence: HIGH
Location: main.py:4
>> Issue: [B605:start_process_with_a_shell] Possible shell injection
Severity: HIGH Confidence: HIGH
Location: main.py:5
Now remove those risky lines, commit again, and rerun the pipeline. Bandit should report:
No issues identified.
This is our intro to the foundation of DevSecOps: detect β fix β verify β repeat.
π Step 7: View and Download the Bandit Report
Each time the pipeline runs, it generates a bandit-report.txt file as
an artifact.
You can download it by:
- 1. Opening the security_scan job
- 2. Expanding the Job artifacts section
- 3. Clicking bandit-report.txt
That's your audit trail... a record of the scan results at that point in
time.
π§ Step 8: Understanding the Big Picture
Here's what we've built:
| Stage | Purpose |
|---|---|
| build | Prepares the app for packaging |
| docker_build | Builds a Docker image from the app |
| test | Runs a basic syntax check |
| security_scan | Runs automated vulnerability analysis with Bandit |
This may be a simplified example, but it closely mirrors the workflows DevOps and DevSecOps professionals build and review every day... only youβve created yours entirely on GitLab, with zero infrastructure cost.
π§° Step 9: Common Beginner Pitfalls
-
Failed to read dockerfile
-
Cause: File was named
DockerFileor not in repo root -
Fix: Rename to
Dockerfileand place in root directory
-
Cause: File was named
-
Cannot connect to the Docker daemon
- Cause: Missing Docker service configuration
-
Fix: Add
services: - docker:dindandDOCKER_HOSTvariables
-
Bandit not found
-
Cause:
pip install banditmissing - Fix: Ensure itβs installed in the job before running
-
Cause:
π Step 10: Why This Project Matters
By completing this single project, you've practiced:
- Continuous Integration (CI): automatically building and testing your code
- Continuous Delivery (CD): preparing artifacts for deployment
- DevSecOps mindset: integrating security early in the workflow
- Version control hygiene: every change triggers a traceable build
These are the foundations used by DevSecOps professionals.
π§ Key Takeaways
- GitLab CI/CD pipelines are just scripts that run automatically after each change.
- Docker + Python: lightweight, reproducible builds.
- Bandit makes security visible and fixable early on.
- Automation doesn't have to be about complexity, it's about consistency.
π― Next Steps to Explore
If you want to keep going:
- Add a stage to push your image to GitLab's Container Registry.
- Include other scanning tools like Trivy.
- Replace the Python file with a small Flask or Node.js app.
- Explore variables, rules, and environments in GitLab CI.
Each of these will teach you a deeper layer of automation.
π Final Thoughts
Building your first CI/CD pipeline can feel intimidating, until you realize it's just a sequence of automated steps you already do manually: build, test, check, repeat.
This small project is your first step of exploring security and automation working together.
Whether you're studying for certifications, switching careers, or just
exploring, you now have a living example to reference, modify, and showcase.
π¬ If you're reading this and you're on the fence about trying GitLab
pipelines, start small. The moment you see that first green check-mark,
you'll realize you've just automated your first deployment.
ποΈ Resources
π€ Connect
If you enjoyed this walkthrough or youβre also learning DevOps, Linux, or Cloud automation, Iβd love to connect, share ideas, and learn.
π¬ Feel free to reach out or follow my journey on π LinkedIn
Top comments (0)