feat: add Docker Compose setup with Nginx, PostgreSQL, MinIO
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
13
apps/cms/Dockerfile
Normal file
13
apps/cms/Dockerfile
Normal 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
26
apps/web/Dockerfile
Normal 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
19
docker/.env.example
Normal 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
89
docker/docker-compose.yml
Normal 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
58
docker/nginx/nginx.conf
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user