Skip to main content

Overview

SkillRise uses a containerized architecture with separate Docker images for the client and server. Both images are built using multi-stage builds for optimal security and performance.

Server Image

Node.js 20 Alpine with production dependencies

Client Image

Nginx Alpine serving optimized Vite build

Quick Start with Docker Compose

The fastest way to deploy SkillRise is using the pre-built images from Docker Hub.
1

Create docker-compose.yml

Create a docker-compose.yml file with the following configuration:
docker-compose.yml
2

Configure Environment Variables

Create a server/.env file with all required environment variables. See the Environment Variables guide for the complete reference.
Ensure MongoDB, Clerk, Cloudinary, and payment gateway credentials are properly configured before starting the containers.
3

Start the Containers

This will:
  • Pull the latest images from Docker Hub
  • Start the server on port 3000
  • Start the client on port 80
  • Automatically restart containers on failure
4

Verify Deployment

Check that both services are running:
Test the server API:
Access the client at http://localhost

Server Dockerfile

The server uses a single-stage build optimized for production:
server/Dockerfile

Server Image Features

  • Runs as non-root user (appuser)
  • Minimal Alpine Linux base image
  • Production dependencies only (--omit=dev)
  • Proper file ownership with --chown
  • Uses npm ci for reproducible builds
  • Node.js 20 LTS for stability
  • Small image size (~150MB)
  • Exposes port 3000
  • Reads environment from .env file
  • Connects to MongoDB on startup
  • Initializes Cloudinary connection

Client Dockerfile

The client uses a multi-stage build to separate build dependencies from the runtime:
client/Dockerfile

Client Image Features

Stage 1 (Builder):
  • Installs all dependencies (including devDependencies)
  • Receives build-time arguments for Vite configuration
  • Compiles React app with Vite
  • Produces optimized static files in /app/dist
Stage 2 (Runtime):
  • Uses minimal Nginx Alpine image
  • Copies only the built static files
  • No Node.js or build tools in final image
  • Results in ~25MB image size
The client includes a custom nginx.conf for SPA routing:
client/nginx.conf
This ensures React Router works correctly by serving index.html for all routes.
The client requires three build-time arguments:
  • VITE_CLERK_PUBLISHABLE_KEY - Clerk authentication public key
  • VITE_STRIPE_PUBLISHABLE_KEY - Stripe payment public key
  • VITE_BACKEND_URL - Backend API URL (e.g., http://localhost:3000)
These are embedded into the build and cannot be changed at runtime.

Building Custom Images

If you need to build images locally or customize the build:

Build Server Image

Build Client Image

Never commit actual API keys to your Dockerfile. Always pass them as build arguments or use CI/CD secrets.

Docker Compose with Custom Images

To use your custom images:
docker-compose.custom.yml
Build and start:

Container Management

View Logs

Restart Services

Stop and Remove

Update to Latest Images

Production Considerations

In production, use a reverse proxy like Nginx or Traefik:
Add resource constraints to prevent resource exhaustion:
docker-compose.yml
Add health checks for automatic recovery:
docker-compose.yml
Configure log rotation to prevent disk space issues:
docker-compose.yml
Use custom networks for service isolation:
docker-compose.yml

Troubleshooting

Check logs:
Common issues:
  • Missing environment variables (check server/.env)
  • MongoDB connection failure (verify MONGODB_URI)
  • Port 3000 already in use (change port mapping)
Verify MongoDB connection:
Check if build arguments were set:
  • Verify VITE_BACKEND_URL points to correct server
  • Check browser console for errors
  • Ensure Clerk public key is valid
Inspect built files:
Check Nginx logs:
Check CORS configuration:
  • Ensure FRONTEND_URL in server .env matches client URL
  • Verify VITE_BACKEND_URL in client build matches server URL
Test server directly:
Check network connectivity:
Check restart logs:
Common causes:
  • Application crash on startup
  • Failed dependency initialization (DB, Cloudinary)
  • Invalid configuration
Disable auto-restart for debugging:

Next Steps

CI/CD Pipeline

Automate builds with GitHub Actions

Environment Variables

Complete configuration reference