-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdocker-compose.cloud.yml
More file actions
204 lines (195 loc) · 7.53 KB
/
docker-compose.cloud.yml
File metadata and controls
204 lines (195 loc) · 7.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# Cloud Server Docker Compose - Let's Encrypt SSL Support
# Usage: docker compose -f docker-compose.cloud.yml up -d
#
# Prerequisites:
# - Domain name pointing to server IP (A record)
# - Port 80 and 443 open in firewall
# - Build images first using: .\scripts\build-production.ps1
# - Or pull from Docker Hub if images are published
#
# Image Source Configuration:
# - Set DOCKER_IMAGE_PREFIX environment variable to choose image source:
# - Unset or empty: Use local images (kasapro-backend:latest)
# - Set to "sofyansolutions/kasapro": Use Docker Hub images (sofyansolutions/kasapro-backend:${ERP_VERSION})
# Example: export DOCKER_IMAGE_PREFIX=sofyansolutions/kasapro
# Example: export ERP_VERSION=v1.0.0
#
# IMPORTANT - SSL/HTTPS Access:
# - Nginx uses Let's Encrypt for proper SSL certificates
# - Certificates auto-renew every 90 days
# - Domain must be accessible from internet for certificate validation
# - First certificate request may take 1-2 minutes
#
# Required Environment Variables:
# - DOMAIN: Your domain name (e.g., pos.example.com)
# - LETSENCRYPT_EMAIL: Email for Let's Encrypt notifications
# - SSL_MODE=letsencrypt (auto-set, but can override)
#
# Optional Environment Variables:
# - NGINX_HTTP_PORT: HTTP port (default: 80)
# - NGINX_HTTPS_PORT: HTTPS port (default: 443)
# - STAGING: Set to 'true' to use Let's Encrypt staging (for testing)
#
# Security Notes:
# - Database migrations are automatically run by the backend service on startup.
# - All images are pre-built (local or from Docker Hub). No build context exposure.
# - SSL certificates are obtained via Let's Encrypt and stored in Docker volume.
# - Certificates auto-renew via certbot cron job.
# - All images use unified versioning via ERP_VERSION environment variable.
services:
backend:
image: ${DOCKER_IMAGE_PREFIX:-kasapro}-backend:${ERP_VERSION:-latest} # Pre-built production image (local or Docker Hub)
container_name: kasapro-backend-cloud
restart: unless-stopped
ports:
- "${BACKEND_PORT:-8100}:8100"
environment:
- APP_ENV=production
- PORT=8100
# DATABASE_URL format: postgres://username:password@host:port/database_name?sslmode=disable
# IMPORTANT: database_name must be 'pos_db', NOT 'pos_user' (pos_user is the username)
- DATABASE_URL=${DATABASE_URL:-postgres://pos_user:pos_pass@postgres:5432/pos_db?sslmode=disable}
- REDIS_URL=${REDIS_URL:-redis://redis:6379/0}
- CORS_ALLOW_ORIGIN=${CORS_ALLOW_ORIGIN:-https://${DOMAIN:-localhost}}
# JWT Secrets - MUST be set in production! Using defaults for development/testing only
# Generate secure secrets: openssl rand -base64 32
- JWT_ACCESS_SECRET=${JWT_ACCESS_SECRET:-dev-access-secret-change-in-production-min-32-chars}
- JWT_REFRESH_SECRET=${JWT_REFRESH_SECRET:-dev-refresh-secret-change-in-production-min-32-chars}
- JWT_ISSUER=${JWT_ISSUER:-kasapro-backend}
- JWT_AUDIENCE=${JWT_AUDIENCE:-kasapro-frontend}
- DEPLOYMENT_MODEL=${DEPLOYMENT_MODEL:-self-hosted}
# NO VOLUME MOUNTS - Source code not accessible
# Backend runs migrations automatically on startup (embedded in binary)
# Migrations are executed before the server starts
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_started
networks:
- default
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8100/healthz"]
interval: 30s
timeout: 10s
retries: 5
start_period: 60s # Give backend more time to start and run migrations
frontend:
image: ${DOCKER_IMAGE_PREFIX:-kasapro}-frontend:${ERP_VERSION:-latest} # Pre-built production image (local or Docker Hub)
container_name: kasapro-frontend-cloud
restart: unless-stopped
ports:
- "${FRONTEND_PORT:-3100}:3100"
environment:
- NODE_ENV=production
- NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL:-https://${DOMAIN:-localhost}/api}
- NEXT_TELEMETRY_DISABLED=1
# NO VOLUME MOUNTS - Source code not accessible
depends_on:
- backend
networks:
- default
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:3100"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
postgres:
image: postgres:14-alpine
container_name: kasapro-postgres-cloud
restart: unless-stopped
ports:
- "${POSTGRES_PORT:-5544}:5432" # External:Internal - Change POSTGRES_PORT if 5544 is in use
environment:
- POSTGRES_DB=${POSTGRES_DB:-pos_db}
- POSTGRES_USER=${POSTGRES_USER:-pos_user}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-pos_pass}
volumes:
- kasapro_postgres_data_cloud:/var/lib/postgresql/data
networks:
- default
healthcheck:
# Use explicit database name to avoid connection issues
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-pos_user} -d ${POSTGRES_DB:-pos_db}"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
container_name: kasapro-redis-cloud
restart: unless-stopped
ports:
- "${REDIS_PORT:-6381}:6379" # External:Internal - Change REDIS_PORT if 6381 is in use
volumes:
- kasapro_redis_data_cloud:/data
networks:
- default
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
# Certbot service for Let's Encrypt certificate management
# Note: Initial certificate is obtained by nginx container's init script
# This service is optional and can be used for manual certificate operations
# Renewal is handled by nginx container's cron job
certbot:
image: certbot/certbot:latest
container_name: kasapro-certbot
restart: "no" # Only run when manually invoked
volumes:
- certbot_data:/etc/letsencrypt
- certbot_www:/var/www/certbot
entrypoint: ""
command: echo "Certbot service ready. Use 'docker compose exec certbot certbot ...' for manual operations."
depends_on:
- nginx
networks:
- default
profiles:
- manual # Only start when explicitly requested
nginx:
image: ${DOCKER_IMAGE_PREFIX:-kasapro}-nginx:${ERP_VERSION:-latest} # Pre-built production image (local or Docker Hub)
container_name: kasapro-nginx-cloud
restart: unless-stopped
ports:
- "${NGINX_HTTP_PORT:-80}:80" # HTTP port for Let's Encrypt validation
- "${NGINX_HTTPS_PORT:-443}:443" # HTTPS port - MUST use https:// protocol
environment:
- SSL_MODE=letsencrypt
- DOMAIN=${DOMAIN}
- LETSENCRYPT_EMAIL=${LETSENCRYPT_EMAIL}
- STAGING=${STAGING:-false}
volumes:
# Let's Encrypt certificates from certbot
- certbot_data:/etc/letsencrypt:ro
# Certbot webroot for validation
- certbot_www:/var/www/certbot:ro
# Nginx SSL directory (for symlinks)
- nginx_ssl_data:/etc/nginx/ssl
depends_on:
- frontend
- backend
networks:
- default
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/healthz"]
interval: 30s
timeout: 10s
retries: 3
volumes:
kasapro_postgres_data_cloud:
kasapro_redis_data_cloud:
nginx_ssl_data:
# SSL certificate symlinks are stored here
# Actual certificates are in certbot_data volume
certbot_data:
# Let's Encrypt certificates are stored here
# Auto-renewed every 90 days
certbot_www:
# Webroot for Let's Encrypt validation
# Certbot writes challenge files here for domain validation
networks:
default:
name: kasapro-network-cloud