End-to-End CI/CD Pipeline Tutorial (Beginner → Advanced)
This tutorial provides a complete, production-grade walkthrough of building a CI/CD (Continuous Integration / Continuous Deployment) pipeline. It covers architecture, tooling, pipeline design, automation workflows, and full working code examples using GitHub Actions, Docker, and deployment strategies.
1. What is CI/CD (Conceptual Foundation)
Continuous Integration (CI)
Developers push code frequently to a shared repository.
Automated processes:
Build
Test
Lint
Objective: detect issues early.
Continuous Deployment (CD)
Automatically deploy validated code to:
staging
production
Eliminates manual release bottlenecks.
2. CI/CD Architecture Overview
A typical pipeline:
Developer → Git Push → CI Pipeline → Build → Test → Artifact → CD Pipeline → Deploy → Monitor
Components:
Version Control: GitHub / GitLab
CI Tool: GitHub Actions
Build Tool: Docker
Artifact Storage: Docker Registry
Deployment Target: VPS / Cloud / Kubernetes
3. Project Setup (Example App)
We’ll use a simple Node.js app.
Project Structure
project/
├── app.js
├── package.json
├── Dockerfile
└── .github/
└── workflows/
└── ci-cd.yml
Code: Node.js App
Title: Basic Node.js Web Server
Description: A minimal HTTP server used to demonstrate CI/CD workflow.
// app.js
const http = require('http');
const PORT = process.env.PORT || 3000;
const server = http.createServer((req, res) => {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('CI/CD Pipeline Working!');
});
server.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
package.json
Title: Node Project Configuration
Description: Defines dependencies and scripts for build/test stages.
{
"name": "ci-cd-demo",
"version": "1.0.0",
"main": "app.js",
"scripts": {
"start": "node app.js",
"test": "echo \"No tests yet\" && exit 0"
}
}
4. Dockerization
Dockerfile
Title: Docker Image Definition
Description: Builds a container image for consistent deployment across environments.
FROM node:18
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
5. CI Pipeline (GitHub Actions)
Workflow File
Title: CI/CD Pipeline Workflow
Description: Automates build, test, Docker image creation, and deployment.
name: CI/CD Pipeline
on:
push:
branches:
- main
jobs:
build-test:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 1
- name: Install Dependencies
run: npm install
- name: Run Tests
run: npm test
docker-build:
needs: build-test
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3
- name: Login to Docker Hub
run: echo "\({{ secrets.DOCKER_PASSWORD }}" | docker login -u "\){{ secrets.DOCKER_USERNAME }}" --password-stdin
- name: Build Docker Image
run: docker build -t ${{ secrets.DOCKER_USERNAME }}/ci-cd-demo:latest .
- name: Push Docker Image
run: docker push ${{ secrets.DOCKER_USERNAME }}/ci-cd-demo:latest
deploy:
needs: docker-build
runs-on: ubuntu-latest
steps:
- name: Deploy via SSH
uses: appleboy/ssh-action@v0.1.6
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SERVER_SSH_KEY }}
script: |
docker pull ${{ secrets.DOCKER_USERNAME }}/ci-cd-demo:latest
docker stop app || true
docker rm app || true
docker run -d -p 80:3000 --name app ${{ secrets.DOCKER_USERNAME }}/ci-cd-demo:latest
6. Secrets Configuration
In your repository settings:
Required secrets:
DOCKER_USERNAME
DOCKER_PASSWORD
SERVER_HOST
SERVER_USER
SERVER_SSH_KEY
7. Deployment Flow (Step-by-Step)
Developer pushes code to
mainGitHub Actions triggers pipeline
CI Stage:
install dependencies
run tests
Build Stage:
create Docker image
push to Docker Hub
CD Stage:
SSH into server
pull latest image
restart container
8. Advanced Enhancements
A. Add Linting
- name: Run Linter
run: npm run lint
B. Add Unit Tests (Jest)
npm install jest --save-dev
"scripts": {
"test": "jest"
}
C. Multi-Environment Deployment
if: github.ref == 'refs/heads/staging'
staging branch → staging server
main branch → production
D. Zero-Downtime Deployment (Blue-Green)
Instead of stopping container:
app-v1 → running
app-v2 → start
switch traffic → remove v1
E. Kubernetes Deployment (Optional Upgrade)
Replace Docker run with:
kubectl apply -f deployment.yaml
9. Common Failure Points
| Issue | Cause | Fix |
|---|---|---|
| Pipeline fails at install | Dependency mismatch | Lock versions |
| Docker push fails | Auth issue | Check secrets |
| SSH deploy fails | Wrong key | Verify permissions |
| App not accessible | Port mismatch | Check EXPOSE vs run |
10. Best Practices
Keep pipelines idempotent
Use immutable artifacts
Separate build and deploy stages
Never hardcode secrets
Use branch protection rules
Monitor deployments (logs, uptime)
11. CI/CD Maturity Model
| Level | Description |
|---|---|
| Basic | Manual deploy |
| Intermediate | CI + manual CD |
| Advanced | Fully automated |
| Elite | Auto rollback + monitoring |
12. Final Outcome
After implementing this:
Every push → automatically tested
Every valid build → deployed
No manual release needed


