// DevOps blueprint

Deploying Your First Web Application: A Step-by-Step Cloud Hosting Guide

A comprehensive developer's guide to cloud deployment. Learn PaaS vs. IaaS hosting models, build containerized applications with Docker, and construct automated CI/CD pipelines with GitHub Actions.

Published: June 5, 2026 · 14 min read · Category: DevOps

Tags: DevOps, Deployment, Cloud Hosting, CI-CD, GitHub Actions, Docker, Vercel

Introduction

Imagine you have just finished building a beautiful house. The interior design is perfect, the plumbing is connected, and the rooms are fully furnished. However, there is a catch: the house is built entirely inside a private storage vault that only you can enter. If anyone else wants to visit, they can't access it. To let people live in it, you need to relocate the house to a public plot of land, set up a permanent road connection, and register the address with the city.

In software development, this relocation process is called Deployment. When you build a web application on your local computer, it runs inside a private sandbox accessible only via localhost. Deployment moves your code to a public cloud server, links it to a custom domain name, and ensures anyone in the world can access it.

For beginners, the world of cloud hosting can feel overwhelming. With options ranging from simple drag-and-drop hosting to complex server setups, it is easy to get lost. This guide breaks down the core concepts of cloud hosting models, introduces containerization with Docker, and builds an automated CI/CD pipeline.


Cloud Hosting Models: PaaS vs. IaaS

When deploying an application, your first decision is choosing the level of control you want over the hosting infrastructure. Cloud hosting falls into two main categories:

1. Platform as a Service (PaaS)

PaaS providers manage the underlying server hardware, operating systems, and network configurations for you. You only supply your application code.

  • Examples: Vercel, Netlify, Render, Heroku.
  • Pros: Incredibly fast setup. You can deploy React, Next.js, or Node.js apps in minutes using git integration. SSL certificates and domain mapping are handled automatically.
  • Cons: Limited custom control. If your app requires custom operating system binaries or specific background processes, PaaS providers might not support them.

2. Infrastructure as a Service (IaaS)

IaaS providers rent you virtual machines (servers) in the cloud. You are responsible for installing the operating system updates, setting up firewalls, configuring Nginx, and managing security patches.

  • Examples: DigitalOcean (Droplets), AWS (EC2), Google Cloud (Compute Engine).
  • Pros: Absolute control and flexibility. You can run any database, backend framework, or tool configuration you choose. It is also cheaper at high traffic scales.
  • Cons: Steep learning curve. If your server crashes or gets hacked, you have to fix it yourself.

The CI/CD Deployment Flow

In modern software organizations, developers do not deploy applications by manually copying files to servers. Instead, they use CI/CD (Continuous Integration and Continuous Deployment) pipelines.

A CI/CD pipeline is an automated workflow that runs every time you push code changes to a repository (like GitHub). The pipeline automatically runs tests, checks for code style errors, builds production bundles, and deploys the updated code to the cloud.

Here is the path code takes from your local machine to the live web server:

[ Developer writes code locally ]
               │
               ▼
   [ Git Commit & Push to GitHub ]
               │
               ▼
┌──────────────────────────────────────────────┐
│     CONTINUOUS INTEGRATION (CI) PIPELINE     │
│  - Triggers on commit push                   │
│  - Runs security scanners & linter checks     │
│  - Executes automated unit & integration tests│
└──────────────┬───────────────────────────────┘
               │ (Tests Pass)
               ▼
┌──────────────────────────────────────────────┐
│     CONTINUOUS DEPLOYMENT (CD) PIPELINE     │
│  - Compiles code into production assets      │
│  - Builds containerized Docker image         │
│  - Pushes Docker image to registry (hub/ECR)  │
└──────────────┬───────────────────────────────┘
               │
               ▼
┌──────────────────────────────────────────────┐
│            PRODUCTION SERVERS                │
│  - Web server pulls updated Docker image     │
│  - Swaps out old container with zero-downtime│
│  - App goes live for users                   │
└──────────────────────────────────────────────┘

Production-Grade Code Configurations

To deploy applications reliably, we use Docker to containerize our code, ensuring it runs the exact same way on the production server as it did locally. We then write a GitHub Actions workflow to automate the entire process.

1. Multi-Stage Dockerfile for a React/Node Application

This Dockerfile uses multi-stage builds to minimize file sizes. It uses a heavy Node image to compile the application assets, and then copies only the final static files to a lightweight Nginx server:

# filepath: Dockerfile
# Stage 1: Build phase
FROM node:20-alpine AS builder
WORKDIR /app

# Copy dependency manifests first to leverage Docker cache layers
COPY package*.json ./
RUN npm ci

# Copy application source files and run the build command
COPY . .
RUN npm run build

# Stage 2: Production runtime phase
FROM nginx:stable-alpine
WORKDIR /usr/share/nginx/html

# Clean default Nginx static files
RUN rm -rf ./*

# Copy build output from Stage 1 to Nginx static serving directory
COPY --from=builder /app/dist .

# Copy custom Nginx configuration for single-page routing
COPY nginx.conf /etc/nginx/conf.d/default.conf

EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

2. GitHub Actions CI/CD Pipeline Configuration

This YAML script is placed in your repository under .github/workflows/deploy.yml. It runs automated tests on every code push to the main branch, builds a Docker image, and handles deploy variables:

# filepath: .github/workflows/deploy.yml
name: Production CI/CD Pipeline

on:
  push:
    branches: [ main ]

jobs:
  test-and-lint:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Source Code
        uses: actions/checkout@v4

      - name: Setup Node.js Environment
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'

      - name: Install Project Dependencies
        run: npm ci

      - name: Run Linter Checks
        run: npm run lint

      - name: Execute Automated Tests
        run: npm run test

  build-and-deploy:
    needs: test-and-lint
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Source Code
        uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Log in to Docker Hub Registry
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Build and Push Docker Image
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: samadshaikh/portfolio-app:latest
          cache-from: type=gha
          cache-to: type=gha,mode=max

      - name: Trigger Server Redeploy
        run: |
          echo "Connecting to production VPS via SSH and updating service..."
          # In a real environment, you would use ssh-action to run:
          # docker pull samadshaikh/portfolio-app:latest
          # docker stop portfolio-container || true
          # docker rm portfolio-container || true
          # docker run -d --name portfolio-container -p 80:80 samadshaikh/portfolio-app:latest

Security & Performance Deployment Checklist

When preparing your application for launch, run through this production checklist:

  • Manage Environment Variables Safely: Never write API keys, database credentials, or secret passwords directly in your source files. Always load them from environment files (.env). When using CI/CD pipelines, store credentials in Encrypted Secrets (like GitHub Actions Secrets) and inject them at build time.
  • Configure SSL/TLS Encryption: Secure your domain name with HTTPS. If using PaaS (like Vercel), this is handled automatically. If hosting on a virtual machine (like AWS or DigitalOcean), install Certbot to configure free Let's Encrypt certificates.
  • Implement Health Checks: Configure your hosting platform to monitor your application's health. Setting up a basic endpoint like /api/health allows your server router to restart containers automatically if the database connection drops or the memory usage spikes.

Reading Recommendations

To see how deployed code connects to backend storage networks, check out these articles:

  • SQL vs. NoSQL: Choosing the Right Database for Your Project: Learn how database structures affect your application deployment pipelines.
  • Multi-Stage Docker Builds for Minimized AWS Lambda Deployment: An advanced guide to reducing build times and container sizes for serverless cloud environments.

References & Resources

  • Docker Documentation: Docker Reference Guide
  • GitHub Actions Help: Automating Builds and Deployments
  • Vercel Deployment Guides: Frontend Framework Deployments

Feedback & Collaboration

Are you preparing to deploy your first project, or are you trying to resolve container issues in Docker? I would love to assist you! Check out my work at samadshaikh.dev, look over my background on my Resume Portal, or leave your feedback on the Connect page.

Written by Samad Shaikh · Back to all articles