Skip to main content

Overview

SkillRise includes Docker configurations for both development and production deployments. Docker provides a consistent, isolated environment that works across all platforms.
Benefits of Docker:
  • No need to install Node.js, MongoDB, or other dependencies locally
  • Consistent environment across development and production
  • Easy scaling and deployment
  • Pre-configured networking between services

Prerequisites

Docker

Docker Engine 20.x or higher

Docker Compose

v2.x (included with Docker Desktop)

Install Docker

Option 1: Docker Desktop (Recommended)
  1. Download Docker Desktop for Mac
  2. Install the .dmg file
  3. Open Docker Desktop and follow the setup wizard
  4. Verify installation:
Option 2: Homebrew

Project Docker Structure

SkillRise includes the following Docker configuration files:

Dockerfile Overview

Backend Dockerfile

The server uses a simple Node.js Alpine image for a lightweight container.
server/Dockerfile
  • Alpine Linux - Minimal base image (~5 MB vs 1+ GB for full Ubuntu)
  • Non-root user - Security best practice (runs as appuser instead of root)
  • Production dependencies only - npm ci --omit=dev skips devDependencies
  • Layer caching - package.json copied before source code for faster rebuilds

Frontend Dockerfile

The client uses a multi-stage build to keep the final image small.
client/Dockerfile
  • Multi-stage build - Build stage is discarded, final image only contains static files + nginx
  • Build arguments - Environment variables are baked into the build at compile time
  • Nginx for serving - Efficient static file server with SPA fallback routing
  • Tiny image size - Final image is ~50 MB (vs ~1 GB if we kept Node.js)

Nginx Configuration

client/nginx.conf
The try_files directive ensures that React Router routes (e.g., /courses/123) serve index.html instead of returning 404.

Docker Compose Configuration

The docker-compose.yml file orchestrates both services:
docker-compose.yml
string
Pre-built Docker Hub image for the backend. You can replace this with build: ./server to build locally.
array
Maps host port 3000 to container port 3000 (Express server).
string
Loads environment variables from server/.env into the container.
array
Ensures the server starts before the client container.

Running with Docker Compose

Using Pre-built Images (Quickest)

The easiest way is to use pre-built images from Docker Hub:
1

Create environment files

Ensure both server/.env and client/.env are configured. See Configuration.
2

Start services

The -d flag runs in detached mode (background):
3

Access the application

4

Stop services

Building Locally

To build images from source instead of using Docker Hub:
1

Modify docker-compose.yml

Replace image references with build contexts:
docker-compose.yml
2

Create root .env file

For client build args, create a .env in the project root:
.env
3

Build and run

This builds both images from scratch (takes 2-5 minutes on first run).

Docker Commands Reference


Seeding Data in Docker

To populate the database with demo data:
See Seeding Data for more details.

Environment Variables in Docker

Backend

Environment variables are loaded from server/.env via the env_file directive:
All variables in server/.env are automatically available in the container.

Frontend (Build Arguments)

For the client, environment variables must be passed as build arguments because Vite bundles them at build time:
These values are read from a root .env file (not client/.env).
Important: Changes to VITE_* variables require rebuilding the client image:

Production Deployment

For production, use the pre-built images with a Docker registry:

Building and Pushing Images

1

Build production images

2

Push to registry

3

Update docker-compose.yml on server

4

Deploy

The official SkillRise images are available at:
  • pushkarverma/skillrise-server:latest
  • pushkarverma/skillrise-client:latest

Docker vs Local Development

Recommendation: Use local development for day-to-day coding (faster hot reload). Use Docker for testing full-stack integration and deployment.

Troubleshooting

Error: Bind for 0.0.0.0:3000 failed: port is already allocatedSolutions:
  1. Stop the process using the port:
  2. Or change the port in docker-compose.yml:
Error: npm ERR! network or npm ERR! code ENOTFOUNDSolutions:
  1. Check your internet connection
  2. Clear Docker build cache:
  3. Use a different npm registry:
Symptom: App can’t connect to database or external APIsSolutions:
  1. Verify server/.env exists and has correct values
  2. Restart containers:
  3. For client env vars, ensure they’re in root .env and rebuild:
Symptom: Frontend loads but shows white screen or errorsSolutions:
  1. Check browser console for errors (F12 β†’ Console)
  2. Verify VITE_BACKEND_URL matches the server URL:
  3. Rebuild client image:
  4. Check nginx logs:
Error: MongoServerError: connect ECONNREFUSEDSolutions:
  1. If using local MongoDB, change MONGODB_URI to use host network:
  2. Or add MongoDB as a service in docker-compose.yml:
Error: MongoServerError: bad authSolutions:
  1. Ensure server container is running:
  2. Verify MONGODB_URI in server/.env is correct
  3. Check server logs:

Next Steps

Seeding Data

Populate database with demo data

CI/CD Pipeline

Automate builds with GitHub Actions

Production Deploy

Deploy to cloud providers