grants/DOCKER_DEPLOYMENT.md
gdegelas a05331128b Atlas Green Morocco — grant strategy platform
- Full grant strategy framework for renewable energy & green hydrogen
- AI-powered grant studio, partner outreach, financial modeling
- Umami analytics with data-performance tracking
- Live Degelas metrics connected to solar.degelas.be
- Trilingual (EN/FR/AR) with i18n support
- Dockerized with Nginx frontend + Express API proxy
2026-06-01 09:44:03 +00:00

12 KiB
Raw Permalink Blame History

Atlas Green Morocco — Docker Deployment Guide

Production-Ready Containerization & Deployment


Overview

This guide covers deploying Atlas Green Morocco using Docker and Docker Compose. The setup includes:

  • Multi-stage Dockerfile: Efficient Node.js → Alpine build pipeline
  • Nginx Configuration: High-performance serving with gzip, security headers, and SPA routing
  • Docker Compose: One-command local and production deployment
  • Optimized Images: Final production image is <25MB

Prerequisites

Before deploying, ensure you have:

  1. Docker installed (v20.10+)

    docker --version
    
  2. Docker Compose installed (v2.0+)

    docker compose version
    
  3. Git (to clone the project)

    git clone https://github.com/your-repo/atlas-green-morocco.git
    cd atlas-green-morocco
    

Quick Start: Local Deployment (1 Minute)

1. Build and Run with Docker Compose

docker compose up -d --build

This command:

  • Builds the Docker image from the Dockerfile
  • Starts a container mapping port 80 to your localhost
  • Runs Nginx in the foreground (production-ready)

2. Access the Application

Open your browser and go to:

http://localhost

You should see the Atlas Green Morocco playbook website live.

3. Check Container Logs

docker compose logs -f atlas-green-app

4. Stop the Container

docker compose down

Production Deployment Guide

Option 1: Deploy to a VPS (DigitalOcean, Linode, Vultr, AWS EC2, etc.)

Step 1: SSH into Your Server

ssh root@your_server_ip

Step 2: Install Docker & Docker Compose

# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# Add your user to docker group
sudo usermod -aG docker $USER
newgrp docker

# Verify installation
docker --version
docker compose version

Step 3: Clone the Repository

git clone https://github.com/your-repo/atlas-green-morocco.git
cd atlas-green-morocco

Step 4: Deploy with Docker Compose

docker compose up -d --build

Step 5: Verify Deployment

docker compose ps

You should see:

CONTAINER ID   IMAGE                      STATUS
abc123def456   atlas-green-morocco:latest   Up 2 minutes

Step 6: Access Your Application

Visit:

http://your_server_ip

Option 2: Deploy to Heroku (with Heroku Container Registry)

Step 1: Install Heroku CLI

curl https://cli.heroku.com/install.sh | sh
heroku login

Step 2: Create Heroku App

heroku create atlas-green-morocco

Step 3: Deploy Docker Image

heroku container:push web -a atlas-green-morocco
heroku container:release web -a atlas-green-morocco

Step 4: View Application

heroku open -a atlas-green-morocco

Option 3: Deploy to AWS ECS (Elastic Container Service)

Step 1: Create ECR Repository

aws ecr create-repository --repository-name atlas-green-morocco --region us-east-1

Step 2: Build and Push Image

# Get AWS credentials
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin YOUR_AWS_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com

# Build image
docker build -t atlas-green-morocco .

# Tag image for ECR
docker tag atlas-green-morocco:latest YOUR_AWS_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/atlas-green-morocco:latest

# Push to ECR
docker push YOUR_AWS_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/atlas-green-morocco:latest

Step 3: Create ECS Task Definition

Use the AWS Console or CLI to create a task definition pointing to your ECR image on port 80.

Step 4: Create ECS Service & Launch

Use AWS ECS Console to create a service from the task definition and launch on your cluster.


Option 4: Deploy to DigitalOcean App Platform (Easiest)

Step 1: Connect Your GitHub Repository

Go to DigitalOcean App Platform > Create App > Select your GitHub repository.

Step 2: Configure Build Settings

  • Buildpack: Docker (automatic detection from Dockerfile)
  • Port: 80
  • Environment: Production

Step 3: Deploy

Click "Deploy" and DigitalOcean will:

  • Build your Docker image
  • Push to their registry
  • Deploy to a container
  • Assign a public URL

Docker Image Architecture

Dockerfile Explanation

# Stage 1: Builder (Node.js 20 Alpine)
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci                          # Clean install (faster, more reliable)
COPY . .
RUN npm run build                   # Build Vite app → dist/

# Stage 2: Runtime (Nginx Alpine)
FROM nginx:alpine AS runner
RUN rm -rf /usr/share/nginx/html/*  # Remove default nginx content
COPY nginx.conf /etc/nginx/conf.d/default.conf  # Custom config
COPY --from=builder /app/dist /usr/share/nginx/html  # Copy build output
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]  # Run Nginx in foreground

Why Multi-Stage?

  • Stage 1 (Node.js): Only used for building
  • Stage 2 (Nginx): Only used for running
  • Final image: <25MB (no Node.js bloat)

Nginx Configuration Highlights

# Gzip compression (text, CSS, JS, SVG)
gzip on;
gzip_min_length 1024;
gzip_types text/plain text/css application/javascript;

# Security headers
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";

# SPA routing support
location / {
    try_files $uri $uri/ /index.html;
}

# Static asset caching (6 months for fingerprinted files)
location ~* \.(?:ico|css|js|gif|jpe?g|png|svg)$ {
    expires 6M;
    add_header Cache-Control "public, max-age=15552000, immutable";
}

Docker Compose Configuration

docker-compose.yml Explained

version: '3.8'

services:
  atlas-green-app:
    build:
      context: .              # Build from current directory
      dockerfile: Dockerfile  # Use our multi-stage Dockerfile
    image: atlas-green-morocco:latest
    container_name: atlas-green-production
    ports:
      - "80:80"              # Map port 80 (HTTP) to container
    restart: unless-stopped   # Auto-restart on crash
    environment:
      - NODE_ENV=production  # Production environment

Common Docker Compose Commands

# Start containers in background
docker compose up -d

# Build and start
docker compose up -d --build

# View logs
docker compose logs -f

# Stop containers
docker compose down

# Remove images too
docker compose down --rmi all

# View running containers
docker compose ps

# Execute command in container
docker compose exec atlas-green-app /bin/sh

# Restart service
docker compose restart atlas-green-app

Environment Variables & Customization

Build-Time Variables

To pass custom variables during build, update docker-compose.yml:

services:
  atlas-green-app:
    build:
      context: .
      dockerfile: Dockerfile
      args:
        NODE_ENV: production

Runtime Variables

To set runtime environment variables for Nginx:

services:
  atlas-green-app:
    environment:
      - NODE_ENV=production
      - CUSTOM_DOMAIN=atlasgreenmorocco.com  # Add your domain

Health Checks & Monitoring

Add Health Check to docker-compose.yml

services:
  atlas-green-app:
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost/"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s

Monitor Logs

# Real-time logs
docker compose logs -f

# Last 100 lines
docker compose logs --tail 100

# Specific service logs
docker compose logs atlas-green-app

Scaling & Performance Tips

1. Use a Reverse Proxy (Nginx, Traefik)

If running multiple containers, use a load balancer:

docker network create atlas-network
# Add to docker-compose.yml:
networks:
  - atlas-network

2. Enable Resource Limits

services:
  atlas-green-app:
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
        reservations:
          cpus: '0.25'
          memory: 256M

3. Use a CDN (CloudFlare, AWS CloudFront)

  • Cache static assets globally
  • Reduce origin server load
  • Improve page load times globally

4. Enable Gzip in Nginx (Already Done)

The provided nginx.conf includes gzip compression for:

  • Text, CSS, JavaScript
  • SVG, JSON
  • Reduces bandwidth by ~60%

Troubleshooting

Container Won't Start

# Check logs
docker compose logs atlas-green-app

# Common issues:
# 1. Port 80 already in use → change docker-compose.yml
# 2. Disk space → docker system prune
# 3. Out of memory → increase Docker memory limit

Nginx Returning 404

Check that dist/ folder exists:

ls dist/
# Should show: index.html, and assets

If missing, rebuild:

docker compose down
docker compose up -d --build

High Memory Usage

Check container stats:

docker stats atlas-green-app

Nginx is very lightweight. If memory is high:

  • Clear Docker cache: docker system prune
  • Check for background processes: docker exec atlas-green-app ps aux

HTTPS / SSL Setup

To add SSL (required for production):

  1. Use Let's Encrypt with Traefik (easiest for Docker)
  2. Use AWS ALB (if on AWS)
  3. Use Cloudflare (free SSL + CDN)

Example with Traefik:

services:
  traefik:
    image: traefik:latest
    # Configure automatic SSL from Let's Encrypt
    # Point your domain to server IP

Security Best Practices

Do:

  • Keep Docker and images updated
  • Run containers as non-root user (Nginx does this by default)
  • Use .dockerignore to exclude sensitive files
  • Implement environment-based configuration
  • Use health checks
  • Set resource limits

Don't:

  • Run containers as root
  • Commit credentials to Dockerfile
  • Use :latest tag in production (use specific versions)
  • Skip security headers (we've included them in nginx.conf)

Cost Optimization

Platform Cost Notes
VPS (DigitalOcean) $520/mo Simplest for small teams
DigitalOcean App Platform $12100/mo Managed, auto-scaling
Heroku $7500/mo Easy, but pricier at scale
AWS ECS $0100+/mo Most flexible, steepest learning curve
Your own hardware $0 For tech-savvy founders (risky)

Recommendation for MVP: Start with DigitalOcean VPS ($510/mo) or DigitalOcean App Platform ($12/mo for managed container).


Backup & Data Persistence

Since Atlas Green is a static website (no database), backups are simple:

# Backup your git repository (that's your backup!)
git push origin main

# For database (if you add one later)
docker compose exec postgres pg_dump -U postgres mydb > backup.sql

Final Checklist: Ready to Deploy?

Before going live to production:

  • .dockerignore created (excludes node_modules, .git, etc.)
  • Dockerfile tested locally (docker build .)
  • nginx.conf in root directory
  • docker-compose.yml customized with your domain/env
  • npm run build works locally
  • dist/index.html contains your compiled app
  • Health checks configured (optional but recommended)
  • Monitoring / alerting set up (optional)
  • Backup strategy defined
  • DNS pointing to your server
  • SSL certificate ready (if HTTPS required)

One-Line Production Deploy

Once everything is tested:

ssh root@your_server && \
git clone https://github.com/your-repo/atlas-green-morocco.git && \
cd atlas-green-morocco && \
docker compose up -d --build

That's it. Your application is live.


Support & Resources


Last Updated: January 2026
Production Ready: Yes


For questions or issues, open an issue on GitHub or email hello@atlasgreenmorocco.com