feat: add Docker Compose setup with Nginx, PostgreSQL, MinIO

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
consultoria-as
2026-02-22 04:10:38 +00:00
parent 7571ea3bab
commit e95b9a61c9
5 changed files with 205 additions and 0 deletions

13
apps/cms/Dockerfile Normal file
View File

@@ -0,0 +1,13 @@
FROM node:20-alpine AS base
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:20-alpine AS production
WORKDIR /app
COPY --from=base /app ./
EXPOSE 1337
CMD ["npm", "run", "start"]

26
apps/web/Dockerfile Normal file
View File

@@ -0,0 +1,26 @@
FROM node:20-alpine AS base
WORKDIR /app
COPY package.json package-lock.json* turbo.json ./
COPY apps/web/package.json ./apps/web/
COPY packages/shared/package.json ./packages/shared/
RUN npm ci
COPY packages/shared/ ./packages/shared/
COPY apps/web/ ./apps/web/
WORKDIR /app/apps/web
RUN npm run build
FROM node:20-alpine AS production
WORKDIR /app/apps/web
COPY --from=base /app/apps/web/.next ./.next
COPY --from=base /app/apps/web/public ./public
COPY --from=base /app/apps/web/package.json ./
COPY --from=base /app/apps/web/node_modules ./node_modules
COPY --from=base /app/node_modules /app/node_modules
COPY --from=base /app/packages /app/packages
EXPOSE 3000
CMD ["npm", "start"]

19
docker/.env.example Normal file
View File

@@ -0,0 +1,19 @@
# Database
DATABASE_NAME=afterlife
DATABASE_USERNAME=afterlife
DATABASE_PASSWORD=change_me_in_production
# Strapi
APP_KEYS=key1,key2,key3,key4
API_TOKEN_SALT=change_me
ADMIN_JWT_SECRET=change_me
TRANSFER_TOKEN_SALT=change_me
JWT_SECRET=change_me
STRAPI_API_TOKEN=your_api_token_after_first_boot
# MinIO
MINIO_ROOT_USER=afterlife
MINIO_ROOT_PASSWORD=change_me_in_production
# Public URL (for frontend image/media URLs)
PUBLIC_STRAPI_URL=http://yourdomain.com

89
docker/docker-compose.yml Normal file
View File

@@ -0,0 +1,89 @@
services:
postgres:
image: postgres:16-alpine
restart: unless-stopped
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
POSTGRES_DB: ${DATABASE_NAME:-afterlife}
POSTGRES_USER: ${DATABASE_USERNAME:-afterlife}
POSTGRES_PASSWORD: ${DATABASE_PASSWORD:-afterlife}
ports:
- "5432:5432"
minio:
image: minio/minio:latest
restart: unless-stopped
command: server /data --console-address ":9001"
volumes:
- minio_data:/data
environment:
MINIO_ROOT_USER: ${MINIO_ROOT_USER:-afterlife}
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-afterlife123}
ports:
- "9000:9000"
- "9001:9001"
cms:
build:
context: ../apps/cms
dockerfile: Dockerfile
restart: unless-stopped
depends_on:
- postgres
- minio
environment:
HOST: 0.0.0.0
PORT: 1337
DATABASE_HOST: postgres
DATABASE_PORT: 5432
DATABASE_NAME: ${DATABASE_NAME:-afterlife}
DATABASE_USERNAME: ${DATABASE_USERNAME:-afterlife}
DATABASE_PASSWORD: ${DATABASE_PASSWORD:-afterlife}
APP_KEYS: ${APP_KEYS}
API_TOKEN_SALT: ${API_TOKEN_SALT}
ADMIN_JWT_SECRET: ${ADMIN_JWT_SECRET}
TRANSFER_TOKEN_SALT: ${TRANSFER_TOKEN_SALT}
JWT_SECRET: ${JWT_SECRET}
ports:
- "1337:1337"
web:
build:
context: ../
dockerfile: apps/web/Dockerfile
restart: unless-stopped
depends_on:
- cms
environment:
STRAPI_URL: http://cms:1337
STRAPI_API_TOKEN: ${STRAPI_API_TOKEN}
NEXT_PUBLIC_STRAPI_URL: ${PUBLIC_STRAPI_URL:-http://localhost:1337}
ports:
- "3000:3000"
nginx:
image: nginx:alpine
restart: unless-stopped
depends_on:
- web
- cms
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- certbot_certs:/etc/letsencrypt:ro
- certbot_www:/var/www/certbot:ro
certbot:
image: certbot/certbot
volumes:
- certbot_certs:/etc/letsencrypt
- certbot_www:/var/www/certbot
volumes:
postgres_data:
minio_data:
certbot_certs:
certbot_www:

58
docker/nginx/nginx.conf Normal file
View File

@@ -0,0 +1,58 @@
events {
worker_connections 1024;
}
http {
upstream web {
server web:3000;
}
upstream cms {
server cms:1337;
}
server {
listen 80;
server_name _;
client_max_body_size 100M;
location / {
proxy_pass http://web;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /api/ {
proxy_pass http://cms;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /admin {
proxy_pass http://cms;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /uploads/ {
proxy_pass http://cms;
proxy_set_header Host $host;
}
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
}
}