废话不多数....直接上代码
Dockerfile
# Step 1: Use a Node.js base image
FROM node:18-bullseye
# Step 2: Set the working directory inside the container
WORKDIR /app
# Step 3: Copy package.json and package-lock.json to the working directory
COPY package*.json ./
# Step 4: Set registry
RUN npm set registry=https://registry.npmmirror.com
# Step 5: Install pm2 global
RUN npm install pm2 -g
# Step 6: Install project dependencies
RUN npm install --only=production
# generated prisma files
COPY /src/database/prisma ./prisma/
# COPY ENV variable
COPY .env ./
# COPY tsconfig.json file
COPY tsconfig.json ./
# Step 7: Copy the rest of the application code to the working directory
COPY . .
# generate prisma
RUN npx prisma generate
# Step 8: Build the NestJS application
RUN npm run build
# Step 9: Expose the port the app will run on
EXPOSE 3000
# Step 10: Define the command to run the app
CMD ["pm2-runtime", "start", "ecosystem.config.js"]
docker-compose.yaml
version: "3.9"
services:
# PostgreSQL 数据库
postgres:
image: postgres:latest
container_name: postgres
environment:
POSTGRES_USER: root
POSTGRES_PASSWORD: root
POSTGRES_DB: cosette_database
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- cosette-net
# Redis 缓存
redis:
image: redis:latest
container_name: redis
ports:
- "6379:6379"
restart: always
volumes:
- redis_data:/data
networks:
- cosette-net
# NestJS 应用
server:
build:
context: ./
dockerfile: ./Dockerfile
container_name: server
image: server:latest
restart: always
ports:
- "3000:3000"
networks:
- cosette-net
depends_on:
- postgres
- redis
env_file:
- ./.env
# Nginx 反向代理
nginx:
image: nginx:stable-alpine
container_name: proxy
ports:
- "5000:5000"
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
privileged: true
depends_on:
- server
networks:
- cosette-net
networks:
cosette-net:
driver: bridge
volumes:
postgres_data:
driver: local
redis_data:
driver: local
ecosystem.config.js
module.exports = {
apps: [
{
name: 'cosette-server',
script: './dist/main.js',
instances: 2, // 负载均衡实例数
autorestart: true, // 自动重启
watch: false, // 监听文件变化
max_memory_restart: '1G', // 内存超过1G时重启
env: {
NODE_ENV: 'production'
}
}
]
};
nginx/Dockerfile
FROM nginx:alpine
# Remove any existing config files
RUN rm /etc/nginx/conf.d/*
# Copy config files
# *.conf files in "conf.d/" dir get included in main config
COPY ./nginx/default.conf /etc/nginx/conf.d/
# Expose the listening port
EXPOSE 5000
# Launch NGINX
CMD [ "nginx", "-g", "daemon off;" ]
nginx/default.conf
server {
listen 5000;
server_name localhost;
# Perform reverse proxy when accessing the / path
location / {
proxy_pass http://server:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# The backend web server can obtain the user's real IP through X-Forwarded-For
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Maximum bytes of the client request body buffered by the proxy
client_body_buffer_size 128k;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}