Prod infra: frontend on port 3001, remove certbot from compose

- Frontend container nginx listens on 3001 instead of 80 to avoid
  conflicts with the host-level reverse proxy
- Removed certbot service, volumes, and SSL config from
  docker-compose.prod.yml — SSL/certbot is managed at the host level
- Updated nginx/production.conf: HTTP-only (host handles TLS),
  upstream frontend points to port 3001
- Updated nginx/ssl.conf frontend upstream to 3001 for consistency

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-02 19:43:14 -05:00
parent 7e6c4c16ce
commit 411239bea4
5 changed files with 13 additions and 62 deletions

View File

@@ -1,25 +1,21 @@
# Production override — use with:
# docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build
#
# For SSL add docker-compose.ssl.yml as well:
# docker compose -f docker-compose.yml -f docker-compose.prod.yml -f docker-compose.ssl.yml up -d --build
#
# What this changes from the base (dev) config:
# - Backend: production Dockerfile (compiled JS, no watch, no devDeps)
# - Frontend: production Dockerfile (static build served by nginx, not Vite)
# - Frontend: production Dockerfile (static build served by nginx on port 3001)
# - No source-code volume mounts (uses baked-in built code)
# - Memory limits and health checks on backend
# - Tuned PostgreSQL for production workloads
# - Restart policies for reliability
#
# SSL/TLS is handled at the host level (e.g., host nginx + certbot).
# The Docker nginx container listens on port 80 only.
services:
nginx:
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/production.conf:/etc/nginx/conf.d/default.conf:ro
- certbot_www:/var/www/certbot:ro
- certbot_conf:/etc/letsencrypt:ro
restart: unless-stopped
backend:
@@ -81,16 +77,3 @@ services:
redis:
restart: unless-stopped
certbot:
image: certbot/certbot:latest
volumes:
- certbot_www:/var/www/certbot
- certbot_conf:/etc/letsencrypt
networks:
- hoanet
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew --quiet; sleep 12h & wait $${!}; done'"
volumes:
certbot_www:
certbot_conf:

View File

@@ -18,5 +18,5 @@ COPY --from=builder /app/dist /usr/share/nginx/html
# Copy a small nginx config for SPA routing
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
EXPOSE 3001
CMD ["nginx", "-g", "daemon off;"]

View File

@@ -2,7 +2,7 @@
# The outer nginx reverse proxy forwards non-API requests here.
server {
listen 80;
listen 3001;
server_name _;
root /usr/share/nginx/html;
index index.html;

View File

@@ -4,7 +4,7 @@ upstream backend {
}
upstream frontend {
server frontend:80;
server frontend:3001;
keepalive 16;
}
@@ -22,44 +22,14 @@ proxy_buffer_size 16k;
proxy_buffers 8 16k;
proxy_busy_buffers_size 32k;
# Redirect HTTP → HTTPS
# Rate limit zone (10 req/s per IP for API)
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
# HTTP server — SSL termination is handled by the host reverse proxy
server {
listen 80;
server_name _;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
# HTTPS server
server {
listen 443 ssl;
# Replace with your hostname:
server_name staging.example.com;
# --- TLS certificates ---
ssl_certificate /etc/letsencrypt/live/staging.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/staging.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
add_header X-Content-Type-Options nosniff always;
add_header X-Frame-Options SAMEORIGIN always;
# --- Rate limit zone (10 req/s per IP for API) ---
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
# --- API routes → backend ---
location /api/ {
limit_req zone=api_limit burst=30 nodelay;
@@ -90,8 +60,6 @@ server {
proxy_pass http://frontend;
proxy_read_timeout 10s;
proxy_connect_timeout 5s;
# Cache static assets aggressively at the proxy level
proxy_cache_bypass $http_upgrade;
}
}

View File

@@ -3,7 +3,7 @@ upstream backend {
}
upstream frontend {
server frontend:5173;
server frontend:3001;
}
# Redirect all HTTP to HTTPS