compose coolify

This commit is contained in:
echo 2026-02-23 04:51:14 +01:00
parent 69833d2067
commit dc93a8b652
3 changed files with 306 additions and 8 deletions

View File

@ -124,6 +124,80 @@ Configure these DNS A records pointing to your VPS IP:
--- ---
## Quick Deploy (Docker Compose)
Deploy all services in one step using Docker Compose.
### Step 1: Create Service
1. In `production` environment, click **+ New Resource**
2. Select **Docker Compose** (not Dockerfile)
3. Name: `placebo-stack`
4. Repository: Select your connected repo
5. Compose File: `docker-compose.coolify.yml`
### Step 2: Set Environment Variables
Click **Environment Variables** and add these secrets:
| Variable | How to Generate |
|----------|-----------------|
| `DATABASE_PASSWORD` | `openssl rand -base64 32` |
| `JWT_SECRET` | `openssl rand -base64 64 \| tr -d '\n'` |
| `VAPID_PUBLIC_KEY` | Run `npm run generate-vapid` locally |
| `VAPID_PRIVATE_KEY` | Run `npm run generate-vapid` locally |
| `STRAPI_APP_KEYS` | See generation command below |
| `STRAPI_API_TOKEN_SALT` | `openssl rand -base64 32` |
| `STRAPI_ADMIN_JWT_SECRET` | `openssl rand -base64 32` |
| `STRAPI_TRANSFER_TOKEN_SALT` | `openssl rand -base64 32` |
| `STRAPI_JWT_SECRET` | `openssl rand -base64 32` |
| `STRAPI_API_TOKEN` | Get from CMS admin after first deploy |
**Generate Strapi APP_KEYS** (4 comma-separated keys):
```bash
for i in {1..4}; do node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"; done | paste -sd "," -
```
**Generate VAPID Keys** (run locally):
```bash
cd backend
npm install
npm run generate-vapid
```
### Step 3: Configure Domains
The compose file uses Traefik labels with these domains:
- `placebo.mk` - Frontend
- `www.placebo.mk` - Frontend (redirect)
- `api.placebo.mk` - Backend API
- `app.placebo.mk` - PWA
- `cms.placebo.mk` - CMS (Strapi)
Ensure DNS is configured before deploying.
### Step 4: Deploy
1. Click **Deploy**
2. Wait for all services to start (2-5 minutes)
3. Check logs if any service fails
### Step 5: Create CMS Admin
1. Visit `https://cms.placebo.mk/admin`
2. Create your admin user
3. Generate API token for backend
4. Add `STRAPI_API_TOKEN` to environment variables
5. Redeploy
---
## Manual Deploy (Individual Services)
If you prefer deploying each service separately, follow these steps.
---
## Database Configuration ## Database Configuration
### Create PostgreSQL Service ### Create PostgreSQL Service
@ -141,7 +215,7 @@ Configure these DNS A records pointing to your VPS IP:
| PostgreSQL Database | `placebo_db` | | PostgreSQL Database | `placebo_db` |
| Persistent Volume | Enabled | | Persistent Volume | Enabled |
4. Click **Deploy** 4. Click **Deploy`
### Note Connection Details ### Note Connection Details
@ -156,7 +230,7 @@ Password: <your-password>
--- ---
## Service Deployments ## Service Deployments (Manual)
### 1. Backend (NestJS API) ### 1. Backend (NestJS API)

View File

@ -9,8 +9,8 @@ WORKDIR /app
COPY package*.json ./ COPY package*.json ./
COPY package-lock.json* ./ COPY package-lock.json* ./
# Install dependencies # Install ALL dependencies (including devDependencies for build)
RUN npm ci --only=production RUN npm ci
# Copy source code # Copy source code
COPY . . COPY . .
@ -18,6 +18,9 @@ COPY . .
# Build TypeScript # Build TypeScript
RUN npm run build RUN npm run build
# Prune devDependencies after build
RUN npm prune --production
# Production stage # Production stage
FROM node:20-alpine FROM node:20-alpine
@ -32,9 +35,6 @@ COPY --from=builder --chown=nodejs:nodejs /app/dist ./dist
COPY --from=builder --chown=nodejs:nodejs /app/node_modules ./node_modules COPY --from=builder --chown=nodejs:nodejs /app/node_modules ./node_modules
COPY --from=builder --chown=nodejs:nodejs /app/package*.json ./ COPY --from=builder --chown=nodejs:nodejs /app/package*.json ./
# Copy environment configuration
COPY --chown=nodejs:nodejs .env.example .env
# Switch to non-root user # Switch to non-root user
USER nodejs USER nodejs
@ -46,4 +46,4 @@ HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
EXPOSE 3000 EXPOSE 3000
# Start application # Start application
CMD ["node", "dist/main.js"] CMD ["node", "dist/main.js"]

224
docker-compose.coolify.yml Normal file
View File

@ -0,0 +1,224 @@
# Docker Compose for Coolify Deployment
# Deploy all services in one run
#
# Usage in Coolify:
# 1. Create new Docker Compose service
# 2. Point to this file
# 3. Set environment variables in Coolify UI
# 4. Deploy
services:
# ===========================================
# DATABASES
# ===========================================
postgres-backend:
image: postgres:16-alpine
container_name: placebo-postgres-backend
restart: unless-stopped
environment:
POSTGRES_DB: placebo_backend_db
POSTGRES_USER: placebo_user
POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
volumes:
- placebo-postgres-backend-data:/var/lib/postgresql/data
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U placebo_user -d placebo_backend_db']
interval: 10s
timeout: 5s
retries: 5
networks:
- placebo-internal
postgres-cms:
image: postgres:16-alpine
container_name: placebo-postgres-cms
restart: unless-stopped
environment:
POSTGRES_DB: placebo_cms_db
POSTGRES_USER: placebo_user
POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
volumes:
- placebo-postgres-cms-data:/var/lib/postgresql/data
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U placebo_user -d placebo_cms_db']
interval: 10s
timeout: 5s
retries: 5
networks:
- placebo-internal
# ===========================================
# BACKEND (NestJS API)
# ===========================================
backend:
build:
context: ./backend
dockerfile: Dockerfile
container_name: placebo-backend
restart: unless-stopped
environment:
NODE_ENV: production
PORT: 3000
DATABASE_TYPE: postgres
DATABASE_HOST: postgres-backend
DATABASE_PORT: 5432
DATABASE_USERNAME: placebo_user
DATABASE_PASSWORD: ${DATABASE_PASSWORD}
DATABASE_NAME: placebo_backend_db
DATABASE_SYNCHRONIZE: 'false'
DATABASE_LOGGING: 'false'
JWT_SECRET: ${JWT_SECRET}
JWT_EXPIRATION: '86400'
CORS_ORIGIN: https://placebo.mk,https://www.placebo.mk,https://app.placebo.mk
STRAPI_URL: http://cms:1337
STRAPI_API_TOKEN: ${STRAPI_API_TOKEN}
VAPID_SUBJECT: ${VAPID_SUBJECT:-mailto:contact@placebo.mk}
VAPID_PUBLIC_KEY: ${VAPID_PUBLIC_KEY}
VAPID_PRIVATE_KEY: ${VAPID_PRIVATE_KEY}
depends_on:
postgres-backend:
condition: service_healthy
healthcheck:
test: ['CMD', 'node', '-e', "require('http').get('http://localhost:3000/health', (r) => {if(r.statusCode !== 200) process.exit(1)})"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
networks:
- placebo-internal
labels:
- 'coolify.managed=true'
- 'traefik.enable=true'
- 'traefik.http.routers.placebo-backend.rule=Host(`api.placebo.mk`)'
- 'traefik.http.routers.placebo-backend.entrypoints=websecure'
- 'traefik.http.routers.placebo-backend.tls.certresolver=letsencrypt'
- 'traefik.http.services.placebo-backend.loadbalancer.server.port=3000'
# ===========================================
# CMS (Strapi)
# ===========================================
cms:
build:
context: ./cms/cms
dockerfile: Dockerfile
container_name: placebo-cms
restart: unless-stopped
environment:
NODE_ENV: production
HOST: 0.0.0.0
PORT: 1337
DATABASE_CLIENT: postgres
DATABASE_HOST: postgres-cms
DATABASE_PORT: 5432
DATABASE_NAME: placebo_cms_db
DATABASE_USERNAME: placebo_user
DATABASE_PASSWORD: ${DATABASE_PASSWORD}
DATABASE_SSL: 'false'
APP_KEYS: ${STRAPI_APP_KEYS}
API_TOKEN_SALT: ${STRAPI_API_TOKEN_SALT}
ADMIN_JWT_SECRET: ${STRAPI_ADMIN_JWT_SECRET}
TRANSFER_TOKEN_SALT: ${STRAPI_TRANSFER_TOKEN_SALT}
JWT_SECRET: ${STRAPI_JWT_SECRET}
depends_on:
postgres-cms:
condition: service_healthy
volumes:
- placebo-cms-uploads:/app/public/uploads
healthcheck:
test: ['CMD', 'node', '-e', "require('http').get('http://localhost:1337/_health', (r) => {if(r.statusCode !== 200) process.exit(1)})"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
networks:
- placebo-internal
labels:
- 'coolify.managed=true'
- 'traefik.enable=true'
- 'traefik.http.routers.placebo-cms.rule=Host(`cms.placebo.mk`)'
- 'traefik.http.routers.placebo-cms.entrypoints=websecure'
- 'traefik.http.routers.placebo-cms.tls.certresolver=letsencrypt'
- 'traefik.http.services.placebo-cms.loadbalancer.server.port=1337'
# ===========================================
# FRONTEND (React)
# ===========================================
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
args:
VITE_API_URL: https://api.placebo.mk/api/v1
VITE_CMS_URL: https://cms.placebo.mk
container_name: placebo-frontend
restart: unless-stopped
depends_on:
- backend
healthcheck:
test: ['CMD', 'wget', '--no-verbose', '--tries=1', '--spider', 'http://localhost:80/']
interval: 30s
timeout: 10s
retries: 3
networks:
- placebo-internal
labels:
- 'coolify.managed=true'
- 'traefik.enable=true'
- 'traefik.http.routers.placebo-frontend.rule=Host(`placebo.mk`) || Host(`www.placebo.mk`)'
- 'traefik.http.routers.placebo-frontend.entrypoints=websecure'
- 'traefik.http.routers.placebo-frontend.tls.certresolver=letsencrypt'
- 'traefik.http.services.placebo-frontend.loadbalancer.server.port=80'
# ===========================================
# PWA (Progressive Web App)
# ===========================================
pwa:
build:
context: ./pwa
dockerfile: Dockerfile
args:
VITE_API_URL: https://api.placebo.mk/api/v1
VITE_CMS_URL: https://cms.placebo.mk
container_name: placebo-pwa
restart: unless-stopped
depends_on:
- backend
healthcheck:
test: ['CMD', 'wget', '--no-verbose', '--tries=1', '--spider', 'http://localhost:80/']
interval: 30s
timeout: 10s
retries: 3
networks:
- placebo-internal
labels:
- 'coolify.managed=true'
- 'traefik.enable=true'
- 'traefik.http.routers.placebo-pwa.rule=Host(`app.placebo.mk`)'
- 'traefik.http.routers.placebo-pwa.entrypoints=websecure'
- 'traefik.http.routers.placebo-pwa.tls.certresolver=letsencrypt'
- 'traefik.http.services.placebo-pwa.loadbalancer.server.port=80'
# ===========================================
# VOLUMES (Managed by Coolify)
# ===========================================
volumes:
placebo-postgres-backend-data:
driver: local
placebo-postgres-cms-data:
driver: local
placebo-cms-uploads:
driver: local
# ===========================================
# NETWORKS
# ===========================================
networks:
placebo-internal:
driver: bridge