Hotfix release available: 2025-05-14b "Librarian".
upgrade now! [56.2] (what's this?)
project:deployment:start
Table of Contents
🚀 DV IT Infrastructure Platform - 生产环境部署指南
更新日期: 2025年1月 项目: DV IT Infrastructure Platform 部署方式: 生产环境实际部署 域名: oasisvape.co.nz + 二级域名
🎯 部署概述
生产环境信息
- VPS IP: 156.67.214.225
- 操作系统: Ubuntu (Linux 6.11.0-29-generic)
- Docker Compose: v2 (docker compose)
- 时区: Pacific/Auckland
- 部署路径: /opt/discountvapor-it/
核心原则
- 容器化部署: 所有服务使用Docker Compose部署
- 自动化SSL: 通过Traefik自动管理Let's Encrypt证书
- 网络安全: 仅开放必要端口,通过反向代理访问
- 监控集成: 完整的监控栈 (cAdvisor + Prometheus + Grafana)
📋 服务版本清单
核心服务
| 服务 | 版本 | 官方文档 | 访问地址 |
|---|---|---|---|
| ERPNext | v15.67.5 | Frappe Docker | https://erp.oasisvape.co.nz |
| Strapi CMS | 自定义镜像 | Strapi Docker | https://cms.oasisvape.co.nz |
| n8n | v1.100.1 | n8n Docker | https://n8n.oasisvape.co.nz |
| DokuWiki | 最新版 | DokuWiki Docker | https://wiki.oasisvape.co.nz |
| Traefik | v2.10 | Traefik Docs | https://traefik.oasisvape.co.nz |
| Grafana | 最新版 | Grafana Docs | https://grafana.oasisvape.co.nz |
数据库服务
| 服务 | 版本 | 用途 | 架构 |
|---|---|---|---|
| MariaDB | 10.6 | ERPNext专用数据库 | 独立实例 |
| PostgreSQL | 15-alpine | Strapi + n8n共享数据库 | 共享实例,Schema隔离 |
🏗️ 生产环境部署
1. 环境准备
# 创建项目目录 mkdir -p /opt/discountvapor-it cd /opt/discountvapor-it # 创建必要目录 mkdir -p data logs traefik config_backup scripts wiki
2. 网络配置
# 创建Traefik网络 docker network create traefik-network # 创建Strapi网络 docker network create strapi_network # 创建ERPNext网络 docker network create discountvapor-it_erpnext-network # 创建监控网络 docker network create monitoring
3. 环境变量配置
# .env 文件 ERPNEXT_VERSION=v15.67.5 DB_PASSWORD=35@Riccarton LETSENCRYPT_EMAIL=discountvapor2025@gmail.com SITES=erp.oasisvape.co.nz
🐳 服务部署配置
1. Traefik 反向代理
# docker-compose-traefik.yml version: '3.8' services: traefik: image: traefik:v2.10 container_name: traefik restart: unless-stopped ports: - "80:80" - "443:443" volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - ./traefik/traefik.yml:/etc/traefik/traefik.yml:ro - traefik_certs:/letsencrypt networks: - traefik-network labels: - traefik.enable=true - traefik.http.routers.traefik.rule=Host(`traefik.oasisvape.co.nz`) - traefik.http.routers.traefik.entrypoints=websecure - traefik.http.routers.traefik.tls.certresolver=letsencrypt - traefik.http.services.traefik.loadbalancer.server.port=8080 volumes: traefik_certs: driver: local networks: traefik-network:
2. Traefik 配置文件
# traefik/traefik.yml api: dashboard: true insecure: true entryPoints: web: address: ":80" http: redirections: entrypoint: to: websecure scheme: https websecure: address: ":443" providers: docker: endpoint: "unix:///var/run/docker.sock" exposedByDefault: false network: traefik-network certificatesResolvers: letsencrypt: acme: email: admin@discountvapor.co.nz storage: /letsencrypt/acme.json httpChallenge: entryPoint: web log: level: INFO
3. ERPNext 部署
# docker-compose-erpnext.yml version: '3.8' services: database: image: mariadb:10.6 restart: unless-stopped command: - --character-set-server=utf8mb4 - --collation-server=utf8mb4_unicode_ci - --skip-character-set-client-handshake - --skip-innodb-read-only-compressed environment: MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} volumes: - db-data:/var/lib/mysql networks: - erpnext-network healthcheck: test: mysqladmin ping -h localhost --password=${DB_PASSWORD} interval: 1s retries: 15 redis-cache: image: redis:6.2-alpine restart: unless-stopped volumes: - redis-cache-data:/data networks: - erpnext-network redis-queue: image: redis:6.2-alpine restart: unless-stopped volumes: - redis-queue-data:/data networks: - erpnext-network configurator: image: frappe/erpnext:${ERPNEXT_VERSION} restart: "no" entrypoint: - bash - -c command: - > ls -1 apps > sites/apps.txt; bench set-config -g db_host database; bench set-config -gp db_port 3306; bench set-config -g redis_cache "redis://redis-cache:6379"; bench set-config -g redis_queue "redis://redis-queue:6379"; bench set-config -g redis_socketio "redis://redis-queue:6379"; bench set-config -gp socketio_port 9000; depends_on: database: condition: service_healthy redis-cache: condition: service_started redis-queue: condition: service_started volumes: - sites:/home/frappe/frappe-bench/sites networks: - erpnext-network backend: image: frappe/erpnext:${ERPNEXT_VERSION} restart: unless-stopped depends_on: configurator: condition: service_completed_successfully volumes: - sites:/home/frappe/frappe-bench/sites networks: - erpnext-network frontend: image: frappe/erpnext:${ERPNEXT_VERSION} restart: unless-stopped command: - nginx-entrypoint.sh environment: BACKEND: backend:8000 FRAPPE_SITE_NAME_HEADER: ${SITES} SOCKETIO: websocket:9000 UPSTREAM_REAL_IP_ADDRESS: 127.0.0.1 UPSTREAM_REAL_IP_HEADER: X-Forwarded-For UPSTREAM_REAL_IP_RECURSIVE: "off" PROXY_READ_TIMEOUT: 120 CLIENT_MAX_BODY_SIZE: 50m depends_on: backend: condition: service_started websocket: condition: service_started volumes: - sites:/home/frappe/frappe-bench/sites ports: - "8080:8080" labels: - traefik.enable=true - traefik.http.routers.erpnext.rule=Host(`erp.oasisvape.co.nz`) - traefik.http.routers.erpnext.entrypoints=websecure - traefik.http.routers.erpnext.tls.certresolver=letsencrypt - traefik.http.services.erpnext.loadbalancer.server.port=8080 - traefik.docker.network=traefik-network networks: - erpnext-network - traefik-network # 其他ERPNext服务... queue-default: image: frappe/erpnext:${ERPNEXT_VERSION} restart: unless-stopped command: - bench - worker - --queue - default depends_on: configurator: condition: service_completed_successfully volumes: - sites:/home/frappe/frappe-bench/sites networks: - erpnext-network queue-short: image: frappe/erpnext:${ERPNEXT_VERSION} restart: unless-stopped command: - bench - worker - --queue - short depends_on: configurator: condition: service_completed_successfully volumes: - sites:/home/frappe/frappe-bench/sites networks: - erpnext-network queue-long: image: frappe/erpnext:${ERPNEXT_VERSION} restart: unless-stopped command: - bench - worker - --queue - long depends_on: configurator: condition: service_completed_successfully volumes: - sites:/home/frappe/frappe-bench/sites networks: - erpnext-network scheduler: image: frappe/erpnext:${ERPNEXT_VERSION} restart: unless-stopped command: - bench - schedule depends_on: configurator: condition: service_completed_successfully volumes: - sites:/home/frappe/frappe-bench/sites networks: - erpnext-network websocket: image: frappe/erpnext:${ERPNEXT_VERSION} restart: unless-stopped command: - node - /home/frappe/frappe-bench/apps/frappe/socketio.js depends_on: configurator: condition: service_completed_successfully volumes: - sites:/home/frappe/frappe-bench/sites networks: - erpnext-network volumes: sites: db-data: redis-cache-data: redis-queue-data: networks: erpnext-network: driver: bridge traefik-network: external: true
4. Strapi CMS 部署
# docker-compose-strapi.yml version: '3.8' services: strapi: image: strapi_infra-strapi:latest container_name: strapi_cms restart: unless-stopped environment: DATABASE_CLIENT: postgres DATABASE_HOST: strapi_postgres DATABASE_PORT: 5432 DATABASE_NAME: strapi_db DATABASE_USERNAME: strapi_user DATABASE_PASSWORD: 35@Riccarton DATABASE_SSL: false DATABASE_SCHEMA: strapi_schema NODE_ENV: production HOST: 0.0.0.0 PORT: 1337 TZ: Pacific/Auckland volumes: - strapi_app_data:/srv/app labels: - traefik.enable=true - traefik.http.routers.strapi.rule=Host(`cms.oasisvape.co.nz`) - traefik.http.routers.strapi.entrypoints=websecure - traefik.http.routers.strapi.tls.certresolver=letsencrypt - traefik.http.services.strapi.loadbalancer.server.port=1337 networks: - strapi_network - traefik-network volumes: strapi_app_data: driver: local networks: strapi_network: external: true traefik-network:
5. n8n 工作流自动化
# docker-compose-n8n.yml version: '3.8' services: n8n: image: n8nio/n8n:1.100.1 restart: unless-stopped environment: - DB_TYPE=postgresdb - DB_POSTGRESDB_HOST=strapi_postgres - DB_POSTGRESDB_PORT=5432 - DB_POSTGRESDB_DATABASE=strapi_db - DB_POSTGRESDB_SCHEMA=n8n_schema - DB_POSTGRESDB_USER=strapi_user - DB_POSTGRESDB_PASSWORD=35@Riccarton - GENERIC_TIMEZONE=Pacific/Auckland - TZ=Pacific/Auckland - N8N_BASIC_AUTH_ACTIVE=true - N8N_BASIC_AUTH_USER=admin - N8N_BASIC_AUTH_PASSWORD=35@Riccarton - N8N_HOST=n8n.oasisvape.co.nz - N8N_PORT=5678 - N8N_SECURE_COOKIE=false - WEBHOOK_TUNNEL_URL=https://n8n.oasisvape.co.nz ports: - "5678:5678" volumes: - ./data:/home/node/.n8n - ./logs:/var/log/n8n networks: - strapi_network - traefik-network labels: - "traefik.enable=true" - "traefik.http.routers.n8n.rule=Host(`n8n.oasisvape.co.nz`)" - "traefik.http.routers.n8n.entrypoints=websecure" - "traefik.http.routers.n8n.tls.certresolver=letsencrypt" - "traefik.http.services.n8n.loadbalancer.server.port=5678" networks: strapi_network: external: true traefik-network:
6. DokuWiki 文档系统
# docker-compose-dokuwiki.yml version: '3.8' services: dokuwiki: image: lscr.io/linuxserver/dokuwiki:latest container_name: dokuwiki restart: unless-stopped environment: - PUID=1000 - PGID=1000 - TZ=Pacific/Auckland volumes: - ./data:/config - ./logs:/var/log/dokuwiki ports: - "8081:80" networks: - strapi_network - traefik-network labels: - "traefik.enable=true" - "traefik.http.routers.dokuwiki.rule=Host(`wiki.oasisvape.co.nz`)" - "traefik.http.routers.dokuwiki.entrypoints=websecure" - "traefik.http.routers.dokuwiki.tls.certresolver=letsencrypt" - "traefik.http.services.dokuwiki.loadbalancer.server.port=80" networks: strapi_network: external: true traefik-network:
7. 监控系统
# docker-compose.yml (监控系统) version: '3.8' services: prometheus: image: prom/prometheus:latest container_name: prometheus restart: unless-stopped ports: - "9090:9090" volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml - ./data/prometheus:/prometheus command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.path=/prometheus' - '--web.console.libraries=/etc/prometheus/console_libraries' - '--web.console.templates=/etc/prometheus/consoles' - '--storage.tsdb.retention.time=200h' - '--web.enable-lifecycle' - '--web.enable-admin-api' environment: - TZ=Pacific/Auckland networks: - monitoring - traefik-network cadvisor: image: gcr.io/cadvisor/cadvisor:latest container_name: cadvisor restart: unless-stopped privileged: true devices: - /dev/kmsg:/dev/kmsg volumes: - /:/rootfs:ro - /var/run:/var/run:ro - /sys:/sys:ro - /var/lib/docker/:/var/lib/docker:ro - /dev/disk/:/dev/disk:ro ports: - "8180:8080" environment: - TZ=Pacific/Auckland networks: - monitoring - traefik-network grafana: image: grafana/grafana:latest container_name: grafana restart: unless-stopped ports: - "3000:3000" volumes: - ./data/grafana:/var/lib/grafana - ./data/grafana/logs:/var/log/grafana environment: - GF_SECURITY_ADMIN_USER=admin - GF_SECURITY_ADMIN_PASSWORD=35@Riccarton - GF_USERS_ALLOW_SIGN_UP=false - GF_INSTALL_PLUGINS=grafana-piechart-panel,grafana-worldmap-panel - TZ=Pacific/Auckland networks: - monitoring - traefik-network labels: - "traefik.enable=true" - "traefik.http.routers.grafana.rule=Host(`grafana.oasisvape.co.nz`)" - "traefik.http.routers.grafana.entrypoints=websecure" - "traefik.http.routers.grafana.tls.certresolver=letsencrypt" - "traefik.http.services.grafana.loadbalancer.server.port=3000" networks: monitoring: driver: bridge name: monitoring traefik-network: external: true volumes: prometheus_data:
🔧 网络安全配置
防火墙设置
# 启用UFW ufw enable # 开放必要端口 ufw allow 22/tcp # SSH ufw allow 80/tcp # HTTP ufw allow 443/tcp # HTTPS # 关闭其他端口 ufw deny 3000 # Grafana ufw deny 5678 # n8n ufw deny 8080 # ERPNext ufw deny 8081 # DokuWiki ufw deny 8180 # cAdvisor ufw deny 9090 # Prometheus # 查看状态 ufw status
SSL证书管理
- 证书类型: Let's Encrypt
- 挑战方式: HTTP Challenge
- 存储位置: /letsencrypt/acme.json
- 自动续期: Traefik自动处理
📊 监控配置
Prometheus 配置
# prometheus.yml global: scrape_interval: 15s evaluation_interval: 15s rule_files: # - "first_rules.yml" # - "second_rules.yml" scrape_configs: - job_name: 'prometheus' static_configs: - targets: ['localhost:9090'] - job_name: 'cadvisor' static_configs: - targets: ['cadvisor:8080'] - job_name: 'traefik' static_configs: - targets: ['traefik:8080']
Grafana 配置
- 默认用户: admin
- 默认密码: 35@Riccarton
- 时区: Pacific/Auckland
- 插件: grafana-piechart-panel, grafana-worldmap-panel
🚀 部署流程
1. 初始化部署
# 进入项目目录 cd /opt/discountvapor-it # 创建网络 docker network create traefik-network docker network create strapi_network docker network create discountvapor-it_erpnext-network docker network create monitoring # 启动Traefik docker compose -f docker-compose-traefik.yml up -d # 启动PostgreSQL docker compose -f docker-compose-postgres.yml up -d # 启动ERPNext docker compose -f docker-compose-erpnext.yml up -d # 启动Strapi docker compose -f docker-compose-strapi.yml up -d # 启动n8n docker compose -f docker-compose-n8n.yml up -d # 启动DokuWiki docker compose -f docker-compose-dokuwiki.yml up -d # 启动监控系统 docker compose up -d
2. 服务验证
# 检查所有容器状态 docker ps # 检查网络连接 docker network ls # 检查Traefik路由 docker logs traefik # 验证SSL证书 curl -I https://erp.oasisvape.co.nz curl -I https://cms.oasisvape.co.nz curl -I https://n8n.oasisvape.co.nz curl -I https://wiki.oasisvape.co.nz curl -I https://grafana.oasisvape.co.nz
3. 防火墙配置
# 配置防火墙 ufw enable ufw allow 22/tcp ufw allow 80/tcp ufw allow 443/tcp ufw deny 3000 ufw deny 5678 ufw deny 8080 ufw deny 8081 ufw deny 8180 ufw deny 9090
🔍 故障排查
常见问题
1. SSL证书问题
# 检查acme.json权限 ls -la traefik/acme.json # 重启Traefik docker compose -f docker-compose-traefik.yml restart
2. 服务无法访问
# 检查容器状态 docker ps -a # 检查网络 docker network inspect traefik-network # 查看服务日志 docker logs <container_name>
3. 数据库连接问题
# 检查数据库容器 docker logs strapi_postgres # 检查网络连接 docker exec -it strapi_cms ping strapi_postgres
日志查看
# 查看所有服务日志
docker logs traefik
docker logs erpnext-frontend
docker logs strapi_cms
docker logs n8n-automation
docker logs dokuwiki
docker logs grafana
📋 访问信息汇总
| 服务 | 域名 | 登录信息 | 状态 |
|---|---|---|---|
| ERPNext | https://erp.oasisvape.co.nz | 管理员账号 | ✅ 正常 |
| Strapi CMS | https://cms.oasisvape.co.nz | 管理员账号 | ✅ 正常 |
| n8n | https://n8n.oasisvape.co.nz | admin / 35@Riccarton | ✅ 正常 |
| DokuWiki | https://wiki.oasisvape.co.nz | 管理员账号 | ✅ 正常 |
| Grafana | https://grafana.oasisvape.co.nz | admin / 35@Riccarton | ✅ 正常 |
| Traefik Dashboard | https://traefik.oasisvape.co.nz | - | ✅ 正常 |
🔄 维护和更新
服务更新
# 更新特定服务 docker compose -f docker-compose-xxx.yml pull docker compose -f docker-compose-xxx.yml up -d # 更新所有服务 docker compose -f docker-compose-traefik.yml pull docker compose -f docker-compose-erpnext.yml pull docker compose -f docker-compose-strapi.yml pull docker compose -f docker-compose-n8n.yml pull docker compose -f docker-compose-dokuwiki.yml pull docker compose pull
备份策略
# 备份配置文件 cp docker-compose-*.yml config_backup/ cp .env config_backup/ cp traefik/traefik.yml config_backup/ # 备份数据 tar -czf backup-$(date +%Y%m%d).tar.gz data/
📞 技术支持
- 联系邮箱: discountvapor2025@gmail.com
- 最后更新: 2025-01-06
project/deployment/start.txt · Last modified: by 127.0.0.1
