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:
@@ -1,25 +1,21 @@
|
|||||||
# Production override — use with:
|
# Production override — use with:
|
||||||
# docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build
|
# 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:
|
# What this changes from the base (dev) config:
|
||||||
# - Backend: production Dockerfile (compiled JS, no watch, no devDeps)
|
# - 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)
|
# - No source-code volume mounts (uses baked-in built code)
|
||||||
# - Memory limits and health checks on backend
|
# - Memory limits and health checks on backend
|
||||||
|
# - Tuned PostgreSQL for production workloads
|
||||||
# - Restart policies for reliability
|
# - 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:
|
services:
|
||||||
nginx:
|
nginx:
|
||||||
ports:
|
|
||||||
- "80:80"
|
|
||||||
- "443:443"
|
|
||||||
volumes:
|
volumes:
|
||||||
- ./nginx/production.conf:/etc/nginx/conf.d/default.conf:ro
|
- ./nginx/production.conf:/etc/nginx/conf.d/default.conf:ro
|
||||||
- certbot_www:/var/www/certbot:ro
|
|
||||||
- certbot_conf:/etc/letsencrypt:ro
|
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
backend:
|
backend:
|
||||||
@@ -81,16 +77,3 @@ services:
|
|||||||
|
|
||||||
redis:
|
redis:
|
||||||
restart: unless-stopped
|
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:
|
|
||||||
|
|||||||
@@ -18,5 +18,5 @@ COPY --from=builder /app/dist /usr/share/nginx/html
|
|||||||
# Copy a small nginx config for SPA routing
|
# Copy a small nginx config for SPA routing
|
||||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
EXPOSE 80
|
EXPOSE 3001
|
||||||
CMD ["nginx", "-g", "daemon off;"]
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# The outer nginx reverse proxy forwards non-API requests here.
|
# The outer nginx reverse proxy forwards non-API requests here.
|
||||||
|
|
||||||
server {
|
server {
|
||||||
listen 80;
|
listen 3001;
|
||||||
server_name _;
|
server_name _;
|
||||||
root /usr/share/nginx/html;
|
root /usr/share/nginx/html;
|
||||||
index index.html;
|
index index.html;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ upstream backend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
upstream frontend {
|
upstream frontend {
|
||||||
server frontend:80;
|
server frontend:3001;
|
||||||
keepalive 16;
|
keepalive 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,44 +22,14 @@ proxy_buffer_size 16k;
|
|||||||
proxy_buffers 8 16k;
|
proxy_buffers 8 16k;
|
||||||
proxy_busy_buffers_size 32k;
|
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 {
|
server {
|
||||||
listen 80;
|
listen 80;
|
||||||
server_name _;
|
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 ---
|
# --- API routes → backend ---
|
||||||
location /api/ {
|
location /api/ {
|
||||||
limit_req zone=api_limit burst=30 nodelay;
|
limit_req zone=api_limit burst=30 nodelay;
|
||||||
@@ -90,8 +60,6 @@ server {
|
|||||||
proxy_pass http://frontend;
|
proxy_pass http://frontend;
|
||||||
proxy_read_timeout 10s;
|
proxy_read_timeout 10s;
|
||||||
proxy_connect_timeout 5s;
|
proxy_connect_timeout 5s;
|
||||||
|
|
||||||
# Cache static assets aggressively at the proxy level
|
|
||||||
proxy_cache_bypass $http_upgrade;
|
proxy_cache_bypass $http_upgrade;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ upstream backend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
upstream frontend {
|
upstream frontend {
|
||||||
server frontend:5173;
|
server frontend:3001;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Redirect all HTTP to HTTPS
|
# Redirect all HTTP to HTTPS
|
||||||
|
|||||||
Reference in New Issue
Block a user