Introduction
Ever wondered how the code you write on your laptop becomes a live website that anyone in the world can access?
- Behind the scenes, several tools and platforms work together:
- GitHub to manage and share your code
- Platforms like Vercel for quick hosting
- Docker containers for portability
- CI/CD pipelines for automation
- Cloud servers for scalability
In this blog, we’ll break the process step by step using a simple React web app as an example.
Step 1: Local Development
Every project starts on your computer.
Example: a React app that displays your projects.
npx create-react-app my-app
cd my-app
npm start
You’ll see the app running locally at http://localhost:3000
.
At this point, only you can see it.
Step 2: Pushing Code to GitHub
Before deploying, you push your project to GitHub.
Why? Because GitHub acts as your project’s source of truth:
- Stores your raw code (React files, configs, Dockerfile, CI/CD workflows).
- Tracks every change (commits, branches, pull requests).
- Enables collaboration with teammates.
- Serves as the trigger point for CI/CD pipelines.
👉 Think of GitHub as the workshop where your blueprints (code) live.
Step 3: Deploying with Platforms like Vercel
Platforms such as Vercel make deployment simple:
- Connect your GitHub repo to Vercel.
- Every time you push code, Vercel:
- Pulls your latest code from GitHub
- Runs
npm run build
- Hosts the app on a public URL
✨ Key points:
- Vercel = serverless hosting → no need to manage servers.
- Handles HTTPS, CDN, caching, and scaling for you.
- Great for static sites or simple web apps.
✅ Benefit: beginner-friendly and fast
❌ Limitation: less control over runtime and environment
Step 4: Introducing Docker
What if you want more control or want your app to run anywhere (cloud, on-premise, or another laptop)?
That’s where Docker helps.
- Docker Image = your app + OS + runtime + dependencies → all packaged together.
- Docker Container = a running instance of that image.
Example Dockerfile:
# Step 1: Build stage
FROM node:18-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# Step 2: Serve with Nginx
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Build & run:
docker build -t my-app:v1 .
docker run -p 8080:80 my-app:v1
Now your app runs inside Docker, independent of your machine setup.
Step 5: Docker Hub (Image Repository)
To share images, we use Docker Hub (like GitHub but for containers).
docker tag my-app:v1 yourusername/my-app:v1
docker push yourusername/my-app:v1
Others can pull & run it:
docker pull yourusername/my-app:v1
docker run -p 8080:80 yourusername/my-app:v1
✅ Benefit: your app is now portable.
👉 Notice the difference:
- GitHub = raw source code, where changes are tracked.
- Docker Hub = built images, ready to run anywhere.
Both are essential parts of the workflow.
Step 6: Cloud Deployment
Instead of running containers locally, deploy them to cloud services:
- Google Cloud Run
- AWS ECS / Fargate
- Azure App Service for Containers
Flow:
- Cloud pulls the image from Docker Hub.
- Runs it inside a container.
- App becomes publicly accessible.
Step 7: Continuous Integration & Deployment (CI/CD)
Up until now, you’ve learned how to:
- Build Docker images locally
- Push them to Docker Hub
- Deploy them on the cloud
That works fine for small projects, but imagine doing it manually every time you make a change.
🔴 The Manual Process (Repetitive & Error-Prone)
Let’s say you change one line of code in your React component. To update your app online, you’d need to:
# Build a new Docker image
docker build -t my-app:v2 .
# Tag the image correctly
docker tag my-app:v2 yourusername/my-app:v2
# Push it to Docker Hub
docker push yourusername/my-app:v2
# SSH into cloud & pull image
docker pull yourusername/my-app:v2
# Stop old container, run new one
docker stop my-app
docker run -d -p 8080:80 --name my-app yourusername/my-app:v2
Now imagine doing this every single time you fix a bug, add a feature, or update content.
- It’s repetitive.
- It’s easy to forget a step.
- Versioning can get messy (v2, v3, final-v3, final-final-v4 😅).
- On a team, multiple developers could overwrite or conflict with each other’s deployments.
Clearly, this doesn’t scale.
🟢 The Automated Process with CI/CD
This is where CI/CD (Continuous Integration / Continuous Deployment) saves the day.
Here’s how it works:
You push your code to GitHub.
- This acts as the trigger.
- No need to run manual Docker commands.
CI (Continuous Integration) kicks in.
- A GitHub Actions workflow (or Jenkins, GitLab CI, CircleCI, etc.) automatically:
- Checks out the latest code.
- Installs dependencies.
- Runs tests (optional but recommended).
- Builds a new Docker image with the latest code.
The image is pushed to Docker Hub automatically.
- The pipeline logs in with your Docker Hub credentials (stored securely as secrets).
- Tags the image with latest (or a commit hash / version number).
- Pushes it to Docker Hub without you lifting a finger.
CD (Continuous Deployment) takes over.
- Depending on your setup, the pipeline can also:
- Trigger your cloud provider (Google Cloud Run, AWS ECS, Kubernetes, etc.).
- Pull the new image.
- Redeploy the container automatically.
End Result: Within minutes of pushing code, your app is updated online.
✅ Why This Matters
- Consistency → Same steps run every time, no “works on my machine” issues.
- Speed → Deployments take minutes, not hours.
- Team-Friendly → Multiple developers can push code, pipeline handles merges and deployments.
- Error Reduction → No forgotten commands, no wrong tags.
- Scalability → Works the same whether you deploy once a week or 20 times a day.
Example: GitHub Actions CI/CD
name: Docker Build & Deploy
on:
push:
branches: [ main ]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build Docker image
run: docker build -t yourusername/my-app:${{ github.sha }} .
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Push Docker image
run: docker push yourusername/my-app:${{ github.sha }}
🔑 Notice:
The image is tagged with the commit SHA (${{ github.sha }}) so every build is uniquely tied to a version of the code.
No manual tagging, no mistakes.
👉 Bottom line:
- Without CI/CD → You’re a human deployment robot, repeating commands.
- With CI/CD → Deployments are automatic, reliable, and scalable.
This is exactly how real-world companies ship code dozens or even hundreds of times per day without breaking things.
End-to-End Summary
Conclusion
- GitHub → the workshop where code lives, collaboration happens, and pipelines are triggered.
- Vercel → quick, beginner-friendly deployments.
- Docker → makes apps portable and production-ready.
- Docker Hub → stores built images for sharing and deployment.
- Cloud → runs containers at scale.
- CI/CD → automates builds, tests, image pushes, and deployments.
Together, these tools form the modern deployment pipeline that real companies use daily.
With this setup, any project, portfolio, blog, or web app can be:
✅ Built locally
✅ Tracked in GitHub
✅ Dockerized
✅ Hosted anywhere
✅ Updated automatically with CI/CD
📌 Thanks for reading!
If you found this guide helpful, let’s stay connected:
🚀 Let’s code, learn, and build together!
Top comments (0)