Docker CI/CD Pipeline
A push to deploy pipeline for a containerized Node.js app. Every commit to main builds the image, pushes it to Docker Hub, and triggers a redeploy on Render, live in under two minutes.

Overview
The goal of this project was to understand what actually happens between git push and a running service. The app itself is a minimal Express server. One endpoint, one page. The point isn't the application. It's the automation around it.
Every push to main results in a new Docker image, a new tag on Docker Hub, and a fresh deploy on Render. No manual steps. If the pipeline is green, the change is live.
How it works
GitHub Actions runs on every push to main. The workflow checks out the code, sets up Node, builds the Docker image, and tags it as hasithaea/express-ci-cd-demo:latest. It authenticates with Docker Hub using a repository secret, pushes the image, then hits a Render deploy webhook to trigger a redeploy.
Render pulls the new image and restarts the service. End-to-end, the whole thing runs in under two minutes.
Locally, docker-compose.yml runs the same image against the same port. The dev environment and the production environment stay close enough that bugs don't hide between them.
The Dockerfile uses a multi stage build to keep the final layer small. Dependencies get installed in one stage, the production image copies only what it needs.
What broke
The first version failed constantly. Wrong secrets, mismatched image tags, a deploy webhook that fired before the Docker push had finished propagating.
Every failure taught something about ordering and idempotency. The webhook issue was the interesting one, GitHub Actions reported the push as complete before Docker Hub had fully registered the new tag. The fix was a small delay, but the lesson was bigger: any system with multiple moving parts needs to be designed around the assumption that events are eventually consistent, not instant.
The pipeline that works today is boring: four steps, in order, that fail loudly when something's wrong. That's what a production pipeline is supposed to look like. The interesting part is getting there.
Reflection
This is the project that made CI/CD click. Reading about pipelines is abstract; watching one fail in the middle of a build, at 11pm, because a secret name was wrong, that's concrete.