From 0c599ba70b38b75f5654eb9d8081e14c5896a11a Mon Sep 17 00:00:00 2001 From: d0lwl0b <208416493+d0lwl0b@users.noreply.github.com> Date: Wed, 29 Oct 2025 22:35:01 +0800 Subject: [PATCH 1/4] chore: add environment variable support and enhance startup script - Add .env.example template for configurable Docker deployment settings - Update docker-compose.yml to support environment-driven port/timezone configuration - Refactor start.sh with improved Docker Compose detection, environment validation, and automated frontend building - Enhance script documentation and error handling for better maintainability --- .env.example | 13 ++++ .gitignore | 1 + docker-compose.yml | 6 +- start.sh | 150 ++++++++++++++++++++++++++++++++++++--------- 4 files changed, 137 insertions(+), 33 deletions(-) create mode 100644 .env.example diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..bcff8c82 --- /dev/null +++ b/.env.example @@ -0,0 +1,13 @@ +# NOFX Environment Variables Template +# Copy this file to .env and modify the values as needed + +# Ports Configuration +# Backend API server port (internal: 8080, external: configurable) +NOFX_BACKEND_PORT=8080 + +# Frontend web interface port (Nginx listens on port 80 internally) +NOFX_FRONTEND_PORT=3000 + +# Timezone Setting +# System timezone for container time synchronization +NOFX_TIMEZONE=Asia/Shanghai diff --git a/.gitignore b/.gitignore index 384b3f41..d501f8dd 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ Thumbs.db *.log *.tmp *.bak +*.backup # 环境变量 .env diff --git a/docker-compose.yml b/docker-compose.yml index a4b35310..689758a5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,13 +9,13 @@ services: container_name: nofx-trading restart: unless-stopped ports: - - "8080:8080" + - "${NOFX_BACKEND_PORT:-8080}:8080" volumes: - ./config.json:/app/config.json:ro - ./decision_logs:/app/decision_logs - /etc/localtime:/etc/localtime:ro # 同步主机时间 environment: - - TZ=Asia/Shanghai # 使用中国时区 + - TZ=${NOFX_TIMEZONE:-Asia/Shanghai} # 使用中国时区 networks: - nofx-network healthcheck: @@ -31,7 +31,7 @@ services: container_name: nofx-frontend restart: unless-stopped ports: - - "3000:80" + - "${NOFX_FRONTEND_PORT:-3000}:80" volumes: - ./web/dist:/usr/share/nginx/html:ro - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro diff --git a/start.sh b/start.sh index 1a4971e5..383cdede 100755 --- a/start.sh +++ b/start.sh @@ -1,18 +1,24 @@ #!/bin/bash +# ═══════════════════════════════════════════════════════════════ # NOFX AI Trading System - Docker Quick Start Script -# 使用方法: ./start.sh [command] +# Usage: ./start.sh [command] +# ═══════════════════════════════════════════════════════════════ set -e -# 颜色定义 +# ------------------------------------------------------------------------ +# Color Definitions +# ------------------------------------------------------------------------ RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color -# 打印带颜色的消息 +# ------------------------------------------------------------------------ +# Utility Functions: Colored Output +# ------------------------------------------------------------------------ print_info() { echo -e "${BLUE}[INFO]${NC} $1" } @@ -29,22 +35,51 @@ print_error() { echo -e "${RED}[ERROR]${NC} $1" } -# 检查 Docker 是否安装 +# ------------------------------------------------------------------------ +# Detection: Docker Compose Command (Backward Compatible) +# ------------------------------------------------------------------------ +detect_compose_cmd() { + if command -v docker compose &> /dev/null; then + COMPOSE_CMD="docker compose" + elif command -v docker-compose &> /dev/null; then + COMPOSE_CMD="docker-compose" + else + print_error "Docker Compose 未安装!请先安装 Docker Compose" + exit 1 + fi + print_info "使用 Docker Compose 命令: $COMPOSE_CMD" +} + +# ------------------------------------------------------------------------ +# Validation: Docker Installation +# ------------------------------------------------------------------------ check_docker() { if ! command -v docker &> /dev/null; then print_error "Docker 未安装!请先安装 Docker: https://docs.docker.com/get-docker/" exit 1 fi - if ! command -v docker-compose &> /dev/null; then - print_error "Docker Compose 未安装!请先安装 Docker Compose" - exit 1 - fi - + detect_compose_cmd print_success "Docker 和 Docker Compose 已安装" } -# 检查配置文件 +# ------------------------------------------------------------------------ +# Validation: Environment File (.env) +# ------------------------------------------------------------------------ +check_env() { + if [ ! -f ".env" ]; then + print_warning ".env 不存在,从模板复制..." + cp .env.example .env + print_info "请编辑 .env 填入你的环境变量配置" + print_info "运行: nano .env 或使用其他编辑器" + exit 1 + fi + print_success "环境变量文件存在" +} + +# ------------------------------------------------------------------------ +# Validation: Configuration File (config.json) +# ------------------------------------------------------------------------ check_config() { if [ ! -f "config.json" ]; then print_warning "config.json 不存在,从模板复制..." @@ -56,15 +91,53 @@ check_config() { print_success "配置文件存在" } -# 启动服务 +# ------------------------------------------------------------------------ +# Build: Frontend (Node.js Based) +# ------------------------------------------------------------------------ +build_frontend() { + print_info "检查前端构建环境..." + + if ! command -v node &> /dev/null; then + print_error "Node.js 未安装!请先安装 Node.js" + exit 1 + fi + + if ! command -v npm &> /dev/null; then + print_error "npm 未安装!请先安装 npm" + exit 1 + fi + + print_info "正在构建前端..." + cd web + + print_info "安装 Node.js 依赖..." + npm install + + print_info "构建前端应用..." + npm run build + + cd .. + print_success "前端构建完成" +} + +# ------------------------------------------------------------------------ +# Service Management: Start +# ------------------------------------------------------------------------ start() { print_info "正在启动 NOFX AI Trading System..." + # Auto-build frontend if missing or forced + if [ ! -d "web/dist" ] || [ "$1" == "--build" ]; then + build_frontend + fi + + # Rebuild images if flag set if [ "$1" == "--build" ]; then print_info "重新构建镜像..." - docker-compose up -d --build + $COMPOSE_CMD up -d --build else - docker-compose up -d + print_info "启动容器..." + $COMPOSE_CMD up -d fi print_success "服务已启动!" @@ -75,60 +148,74 @@ start() { print_info "停止服务: ./start.sh stop" } -# 停止服务 +# ------------------------------------------------------------------------ +# Service Management: Stop +# ------------------------------------------------------------------------ stop() { print_info "正在停止服务..." - docker-compose stop + $COMPOSE_CMD stop print_success "服务已停止" } -# 重启服务 +# ------------------------------------------------------------------------ +# Service Management: Restart +# ------------------------------------------------------------------------ restart() { print_info "正在重启服务..." - docker-compose restart + $COMPOSE_CMD restart print_success "服务已重启" } -# 查看日志 +# ------------------------------------------------------------------------ +# Monitoring: Logs +# ------------------------------------------------------------------------ logs() { if [ -z "$2" ]; then - docker-compose logs -f + $COMPOSE_CMD logs -f else - docker-compose logs -f "$2" + $COMPOSE_CMD logs -f "$2" fi } -# 查看状态 +# ------------------------------------------------------------------------ +# Monitoring: Status +# ------------------------------------------------------------------------ status() { print_info "服务状态:" - docker-compose ps + $COMPOSE_CMD ps echo "" print_info "健康检查:" curl -s http://localhost:8080/health | jq '.' || echo "后端未响应" } -# 清理 +# ------------------------------------------------------------------------ +# Maintenance: Clean (Destructive) +# ------------------------------------------------------------------------ clean() { print_warning "这将删除所有容器和数据!" read -p "确认删除?(yes/no): " confirm if [ "$confirm" == "yes" ]; then print_info "正在清理..." - docker-compose down -v + $COMPOSE_CMD down -v print_success "清理完成" else print_info "已取消" fi } -# 更新 +# ------------------------------------------------------------------------ +# Maintenance: Update +# ------------------------------------------------------------------------ update() { print_info "正在更新..." git pull - docker-compose up -d --build + $COMPOSE_CMD up -d --build print_success "更新完成" } -# 显示帮助 +# ------------------------------------------------------------------------ +# Help: Usage Information +# ------------------------------------------------------------------------ show_help() { echo "NOFX AI Trading System - Docker 管理脚本" echo "" @@ -150,12 +237,15 @@ show_help() { echo " ./start.sh status # 查看状态" } -# 主函数 +# ------------------------------------------------------------------------ +# Main: Command Dispatcher +# ------------------------------------------------------------------------ main() { check_docker case "${1:-start}" in start) + check_env check_config start "$2" ;; @@ -188,5 +278,5 @@ main() { esac } -# 运行主函数 -main "$@" +# Execute Main +main "$@" \ No newline at end of file From e564392eb92a330a95e3269e31f910ccca0d72c8 Mon Sep 17 00:00:00 2001 From: d0lwl0b <208416493+d0lwl0b@users.noreply.github.com> Date: Thu, 30 Oct 2025 00:28:39 +0800 Subject: [PATCH 2/4] chore: update .dockerignore to exclude lock files --- start.sh | 44 ++++++++++++++++++++++---------------------- web/.dockerignore | 3 --- 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/start.sh b/start.sh index 383cdede..f4589f96 100755 --- a/start.sh +++ b/start.sh @@ -94,31 +94,31 @@ check_config() { # ------------------------------------------------------------------------ # Build: Frontend (Node.js Based) # ------------------------------------------------------------------------ -build_frontend() { - print_info "检查前端构建环境..." +# build_frontend() { +# print_info "检查前端构建环境..." - if ! command -v node &> /dev/null; then - print_error "Node.js 未安装!请先安装 Node.js" - exit 1 - fi +# if ! command -v node &> /dev/null; then +# print_error "Node.js 未安装!请先安装 Node.js" +# exit 1 +# fi - if ! command -v npm &> /dev/null; then - print_error "npm 未安装!请先安装 npm" - exit 1 - fi +# if ! command -v npm &> /dev/null; then +# print_error "npm 未安装!请先安装 npm" +# exit 1 +# fi - print_info "正在构建前端..." - cd web +# print_info "正在构建前端..." +# cd web - print_info "安装 Node.js 依赖..." - npm install +# print_info "安装 Node.js 依赖..." +# npm install - print_info "构建前端应用..." - npm run build +# print_info "构建前端应用..." +# npm run build - cd .. - print_success "前端构建完成" -} +# cd .. +# print_success "前端构建完成" +# } # ------------------------------------------------------------------------ # Service Management: Start @@ -127,9 +127,9 @@ start() { print_info "正在启动 NOFX AI Trading System..." # Auto-build frontend if missing or forced - if [ ! -d "web/dist" ] || [ "$1" == "--build" ]; then - build_frontend - fi + # if [ ! -d "web/dist" ] || [ "$1" == "--build" ]; then + # build_frontend + # fi # Rebuild images if flag set if [ "$1" == "--build" ]; then diff --git a/web/.dockerignore b/web/.dockerignore index 2d8c3534..651c8af9 100644 --- a/web/.dockerignore +++ b/web/.dockerignore @@ -1,8 +1,5 @@ # Dependencies node_modules/ -package-lock.json -yarn.lock -pnpm-lock.yaml # Build output (will be regenerated) dist/ From 2a3276c1252fae25a5ee67283e043e9ab027fc1d Mon Sep 17 00:00:00 2001 From: d0lwl0b <208416493+d0lwl0b@users.noreply.github.com> Date: Thu, 30 Oct 2025 12:26:00 +0800 Subject: [PATCH 3/4] docs: update Docker Compose documentation to V2 syntax --- DOCKER_DEPLOY.en.md | 99 ++++++++++++++++++++++------------------- DOCKER_DEPLOY.md | 104 +++++++++++++++++++++++++------------------- README.md | 10 ++++- README.ru.md | 6 ++- README.uk.md | 6 ++- README.zh-CN.md | 6 ++- 6 files changed, 135 insertions(+), 96 deletions(-) diff --git a/DOCKER_DEPLOY.en.md b/DOCKER_DEPLOY.en.md index 1b9c42f2..bf8adf63 100644 --- a/DOCKER_DEPLOY.en.md +++ b/DOCKER_DEPLOY.en.md @@ -15,22 +15,33 @@ Before you begin, ensure your system has: Download and install [Docker Desktop](https://www.docker.com/products/docker-desktop/) #### Linux (Ubuntu/Debian) + +> #### Docker Compose Version Notes +> +> **New User Recommendation:** +> - **Use Docker Desktop**: Automatically includes latest Docker Compose, no separate installation needed +> - Simple installation, one-click setup, provides GUI management +> - Supports macOS, Windows, and some Linux distributions +> +> **Upgrading User Note:** +> - **Deprecating standalone docker-compose**: No longer recommended to download the independent Docker Compose binary +> - **Use built-in version**: Docker 20.10+ includes `docker compose` command (with space) +> - If still using old `docker-compose`, please upgrade to new syntax + +*Recommended: Use Docker Desktop (if available) or Docker CE with built-in Compose* + ```bash -# Install Docker +# Install Docker (includes compose) curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh -# Install Docker Compose -sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose -sudo chmod +x /usr/local/bin/docker-compose - -# Add current user to docker group +# Add user to docker group sudo usermod -aG docker $USER newgrp docker -# Verify installation +# Verify installation (new command) docker --version -docker-compose --version +docker compose --version # Docker 24+ includes this, no separate installation needed ``` ## 🚀 Quick Start (3 Steps) @@ -69,10 +80,10 @@ nano config.json # or use any other editor ```bash # Build and start all services (first run) -docker-compose up -d --build +docker compose up -d --build # Subsequent starts (without rebuilding) -docker-compose up -d +docker compose up -d ``` **Startup options:** @@ -91,49 +102,49 @@ Once deployed, open your browser and visit: ### View Running Status ```bash # View all container status -docker-compose ps +docker compose ps # View service health status -docker-compose ps --format json | jq +docker compose ps --format json | jq ``` ### View Logs ```bash # View all service logs -docker-compose logs -f +docker compose logs -f # View backend logs only -docker-compose logs -f backend +docker compose logs -f backend # View frontend logs only -docker-compose logs -f frontend +docker compose logs -f frontend # View last 100 lines -docker-compose logs --tail=100 +docker compose logs --tail=100 ``` ### Stop Services ```bash # Stop all services (keep data) -docker-compose stop +docker compose stop # Stop and remove containers (keep data) -docker-compose down +docker compose down # Stop and remove containers and volumes (clear all data) -docker-compose down -v +docker compose down -v ``` ### Restart Services ```bash # Restart all services -docker-compose restart +docker compose restart # Restart backend only -docker-compose restart backend +docker compose restart backend # Restart frontend only -docker-compose restart frontend +docker compose restart frontend ``` ### Update Services @@ -142,7 +153,7 @@ docker-compose restart frontend git pull # Rebuild and restart -docker-compose up -d --build +docker compose up -d --build ``` ## 🔧 Advanced Configuration @@ -226,14 +237,14 @@ tar -xzf backup_20241029.tar.gz ```bash # View detailed error messages -docker-compose logs backend -docker-compose logs frontend +docker compose logs backend +docker compose logs frontend # Check container status -docker-compose ps -a +docker compose ps -a # Rebuild (clear cache) -docker-compose build --no-cache +docker compose build --no-cache ``` ### Port Already in Use @@ -273,10 +284,10 @@ curl http://localhost:3000/health ```bash # Check network connectivity -docker-compose exec frontend ping backend +docker compose exec frontend ping backend # Check if backend service is running -docker-compose exec frontend wget -O- http://backend:8080/health +docker compose exec frontend wget -O- http://backend:8080/health ``` ### Clean Docker Resources @@ -321,8 +332,8 @@ docker system prune -a --volumes 4. **Regularly update images** ```bash - docker-compose pull - docker-compose up -d + docker compose pull + docker compose up -d ``` ## 🌐 Production Deployment @@ -391,7 +402,7 @@ logging: max-file: "3" # View log statistics -docker-compose logs --timestamps | wc -l +docker compose logs --timestamps | wc -l ``` ### Monitoring Tool Integration @@ -424,28 +435,28 @@ services: ```bash # Start -docker-compose up -d --build # Build and start -docker-compose up -d # Start (without rebuilding) +docker compose up -d --build # Build and start +docker compose up -d # Start (without rebuilding) # Stop -docker-compose stop # Stop services -docker-compose down # Stop and remove containers -docker-compose down -v # Stop and remove containers and data +docker compose stop # Stop services +docker compose down # Stop and remove containers +docker compose down -v # Stop and remove containers and data # View -docker-compose ps # View status -docker-compose logs -f # View logs -docker-compose top # View processes +docker compose ps # View status +docker compose logs -f # View logs +docker compose top # View processes # Restart -docker-compose restart # Restart all services -docker-compose restart backend # Restart backend +docker compose restart # Restart all services +docker compose restart backend # Restart backend # Update -git pull && docker-compose up -d --build +git pull && docker compose up -d --build # Clean -docker-compose down -v # Clear all data +docker compose down -v # Clear all data docker system prune -a # Clean Docker resources ``` diff --git a/DOCKER_DEPLOY.md b/DOCKER_DEPLOY.md index f48b005e..536ee159 100644 --- a/DOCKER_DEPLOY.md +++ b/DOCKER_DEPLOY.md @@ -11,26 +11,42 @@ ### 安装 Docker +> #### 提示:Docker Compose 版本说明 +> +> **新用户建议**: +> - **推荐使用 Docker Desktop**:自动包含最新 Docker Compose,无需单独安装 +> - 安装简单,一键搞定,提供图形界面管理 +> - 支持 macOS、Windows、部分 Linux 发行版 +> +> **旧用户提醒**: +> - **弃用独立 docker-compose**:不再推荐下载独立的 Docker Compose 二进制文件 +> - **使用内置版**:Docker 20.10+ 自带 `docker compose` 命令(注意是空格) +> - 如果还在使用旧的 `docker-compose`,请升级到新语法 + #### macOS / Windows 下载并安装 [Docker Desktop](https://www.docker.com/products/docker-desktop/) -#### Linux (Ubuntu/Debian) +**安装后验证:** ```bash -# 安装 Docker +docker --version +docker compose --version # 注意:使用空格,不再是连字符 +``` + +#### Linux (Ubuntu/Debian) +**推荐方式:使用 Docker Desktop(如果可用)或 Docker CE** + +```bash +# 安装 Docker (自动包含 compose) curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh -# 安装 Docker Compose -sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose -sudo chmod +x /usr/local/bin/docker-compose - # 将当前用户加入 docker 组 sudo usermod -aG docker $USER newgrp docker -# 验证安装 +# 验证安装(新命令) docker --version -docker-compose --version +docker compose --version # Docker 24+ 自带,无需单独安装 ``` ## 🚀 快速开始(3步完成部署) @@ -69,10 +85,10 @@ nano config.json # 或使用其他编辑器 ```bash # 构建并启动所有服务(首次运行) -docker-compose up -d --build +docker compose up -d --build # 后续启动(不重新构建) -docker-compose up -d +docker compose up -d ``` **启动过程说明:** @@ -91,49 +107,49 @@ docker-compose up -d ### 查看运行状态 ```bash # 查看所有容器状态 -docker-compose ps +docker compose ps # 查看服务健康状态 -docker-compose ps --format json | jq +docker compose ps --format json | jq ``` ### 查看日志 ```bash # 查看所有服务日志 -docker-compose logs -f +docker compose logs -f # 只查看后端日志 -docker-compose logs -f backend +docker compose logs -f backend # 只查看前端日志 -docker-compose logs -f frontend +docker compose logs -f frontend # 查看最近 100 行日志 -docker-compose logs --tail=100 +docker compose logs --tail=100 ``` ### 停止服务 ```bash # 停止所有服务(保留数据) -docker-compose stop +docker compose stop # 停止并删除容器(保留数据) -docker-compose down +docker compose down # 停止并删除容器和卷(清除所有数据) -docker-compose down -v +docker compose down -v ``` ### 重启服务 ```bash # 重启所有服务 -docker-compose restart +docker compose restart # 只重启后端 -docker-compose restart backend +docker compose restart backend # 只重启前端 -docker-compose restart frontend +docker compose restart frontend ``` ### 更新服务 @@ -142,7 +158,7 @@ docker-compose restart frontend git pull # 重新构建并重启 -docker-compose up -d --build +docker compose up -d --build ``` ## 🔧 高级配置 @@ -226,14 +242,14 @@ tar -xzf backup_20241029.tar.gz ```bash # 查看详细错误信息 -docker-compose logs backend -docker-compose logs frontend +docker compose logs backend +docker compose logs frontend # 检查容器状态 -docker-compose ps -a +docker compose ps -a # 重新构建(清除缓存) -docker-compose build --no-cache +docker compose build --no-cache ``` ### 端口被占用 @@ -273,10 +289,10 @@ curl http://localhost:3000/health ```bash # 检查网络连接 -docker-compose exec frontend ping backend +docker compose exec frontend ping backend # 检查后端服务是否正常 -docker-compose exec frontend wget -O- http://backend:8080/health +docker compose exec frontend wget -O- http://backend:8080/health ``` ### 清理 Docker 资源 @@ -321,8 +337,8 @@ docker system prune -a --volumes 4. **定期更新镜像** ```bash - docker-compose pull - docker-compose up -d + docker compose pull + docker compose up -d ``` ## 🌐 生产环境部署 @@ -391,7 +407,7 @@ logging: max-file: "3" # 查看日志统计 -docker-compose logs --timestamps | wc -l +docker compose logs --timestamps | wc -l ``` ### 监控工具集成 @@ -424,28 +440,28 @@ services: ```bash # 启动 -docker-compose up -d --build # 构建并启动 -docker-compose up -d # 启动(不重新构建) +docker compose up -d --build # 构建并启动 +docker compose up -d # 启动(不重新构建) # 停止 -docker-compose stop # 停止服务 -docker-compose down # 停止并删除容器 -docker-compose down -v # 停止并删除容器和数据 +docker compose stop # 停止服务 +docker compose down # 停止并删除容器 +docker compose down -v # 停止并删除容器和数据 # 查看 -docker-compose ps # 查看状态 -docker-compose logs -f # 查看日志 -docker-compose top # 查看进程 +docker compose ps # 查看状态 +docker compose logs -f # 查看日志 +docker compose top # 查看进程 # 重启 -docker-compose restart # 重启所有服务 -docker-compose restart backend # 重启后端 +docker compose restart # 重启所有服务 +docker compose restart backend # 重启后端 # 更新 -git pull && docker-compose up -d --build +git pull && docker compose up -d --build # 清理 -docker-compose down -v # 清除所有数据 +docker compose down -v # 清除所有数据 docker system prune -a # 清理 Docker 资源 ``` diff --git a/README.md b/README.md index 1e6c15f7..ba9305fa 100644 --- a/README.md +++ b/README.md @@ -260,8 +260,14 @@ nano config.json # or use any editor chmod +x start.sh ./start.sh start --build -# Option 2: Use docker-compose directly -docker-compose up -d --build +> #### Docker Compose Version Notes +> +> **This project uses Docker Compose V2 syntax (with spaces)** +> +> If you have the older standalone `docker-compose` installed, please upgrade to Docker Desktop or Docker 20.10+ + +# Option 2: Use docker compose directly +docker compose up -d --build ``` #### Step 3: Access Dashboard diff --git a/README.ru.md b/README.ru.md index 874c478a..51d8054a 100644 --- a/README.ru.md +++ b/README.ru.md @@ -196,8 +196,10 @@ nano config.json # или используйте любой редактор chmod +x start.sh ./start.sh start --build -# Вариант 2: Используйте docker-compose напрямую -docker-compose up -d --build +# Вариант 2: Используйте docker compose напрямую +# Этот проект использует синтаксис Docker Compose V2 (с пробелами) +# Если у вас установлена старая версия `docker-compose`, обновитесь до Docker Desktop или Docker 20.10+ +docker compose up -d --build ``` #### Шаг 3: Доступ к панели diff --git a/README.uk.md b/README.uk.md index 8c955c59..d47c5921 100644 --- a/README.uk.md +++ b/README.uk.md @@ -196,8 +196,10 @@ nano config.json # або використайте будь-який редак chmod +x start.sh ./start.sh start --build -# Варіант 2: Використайте docker-compose безпосередньо -docker-compose up -d --build +# Варіант 2: Використайте docker compose безпосередньо +# Цей проект використовує синтаксис Docker Compose V2 (з пробілами) +# Якщо у вас встановлена стара версія `docker-compose`, оновіть до Docker Desktop або Docker 20.10+ +docker compose up -d --build ``` #### Крок 3: Доступ до панелі diff --git a/README.zh-CN.md b/README.zh-CN.md index 91447973..9b47fa04 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -260,8 +260,10 @@ nano config.json # 或使用其他编辑器 chmod +x start.sh ./start.sh start --build -# 方式2:直接使用docker-compose -docker-compose up -d --build + +# 方式2:直接使用docker compose +# 如果您还在使用旧的独立 `docker-compose`,请升级到 Docker Desktop 或 Docker 20.10+ +docker compose up -d --build ``` #### 步骤3:访问控制台 From 0d52bc8ad95ce6e8cac18f01d3e3dcc08664d70a Mon Sep 17 00:00:00 2001 From: d0lwl0b <208416493+d0lwl0b@users.noreply.github.com> Date: Thu, 30 Oct 2025 13:11:29 +0800 Subject: [PATCH 4/4] refactor(docker): restructure Docker setup with dedicated backend/frontend services --- Dockerfile | 123 --------------------------------- docker-compose.yml | 30 ++++---- docker/Dockerfile.backend | 68 ++++++++++++++++++ docker/Dockerfile.frontend | 36 ++++++++++ nginx.conf => nginx/nginx.conf | 16 +++-- web/Dockerfile | 72 ------------------- 6 files changed, 129 insertions(+), 216 deletions(-) delete mode 100644 Dockerfile create mode 100644 docker/Dockerfile.backend create mode 100644 docker/Dockerfile.frontend rename nginx.conf => nginx/nginx.conf (67%) delete mode 100644 web/Dockerfile diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 4a8d8fb4..00000000 --- a/Dockerfile +++ /dev/null @@ -1,123 +0,0 @@ -# Multi-stage build for NOFX AI Trading System -FROM golang:1.25-alpine AS backend-builder - -# Install build dependencies including TA-Lib -RUN apk update && \ - apk add --no-cache \ - git \ - make \ - gcc \ - g++ \ - musl-dev \ - wget \ - tar \ - autoconf \ - automake - -# Install TA-Lib -RUN wget http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz && \ - tar -xzf ta-lib-0.4.0-src.tar.gz && \ - cd ta-lib && \ - if [ "$(uname -m)" = "aarch64" ]; then \ - CONFIG_GUESS=$(find /usr/share -name config.guess | head -1) && \ - CONFIG_SUB=$(find /usr/share -name config.sub | head -1) && \ - cp "$CONFIG_GUESS" config.guess && \ - cp "$CONFIG_SUB" config.sub && \ - chmod +x config.guess config.sub; \ - fi && \ - ./configure --prefix=/usr && \ - make && \ - make install && \ - cd .. && \ - rm -rf ta-lib ta-lib-0.4.0-src.tar.gz - -# Set working directory -WORKDIR /app - -# Copy go mod files -COPY go.mod go.sum ./ - -# Download dependencies -RUN go mod download - -# Copy backend source code -COPY . . - -# Build the application -RUN CGO_ENABLED=1 GOOS=linux go build -trimpath -ldflags="-s -w" -o nofx . - -# Frontend build stage -FROM node:18-alpine AS frontend-builder - -WORKDIR /app/web - -# Copy package files -COPY web/package*.json ./ - -# Install dependencies -RUN npm ci - -# Copy frontend source -COPY web/ ./ - -# Build frontend -RUN npm run build - -# Final stage -FROM alpine:latest - -# Update package index and install runtime dependencies -RUN apk update && \ - apk add --no-cache \ - ca-certificates \ - tzdata \ - wget \ - tar \ - make \ - gcc \ - g++ \ - musl-dev \ - autoconf \ - automake - -# Install TA-Lib runtime -RUN wget http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz && \ - tar -xzf ta-lib-0.4.0-src.tar.gz && \ - cd ta-lib && \ - if [ "$(uname -m)" = "aarch64" ]; then \ - CONFIG_GUESS=$(find /usr/share -name config.guess | head -1) && \ - CONFIG_SUB=$(find /usr/share -name config.sub | head -1) && \ - cp "$CONFIG_GUESS" config.guess && \ - cp "$CONFIG_SUB" config.sub && \ - chmod +x config.guess config.sub; \ - fi && \ - ./configure --prefix=/usr && \ - make && \ - make install && \ - cd .. && \ - rm -rf ta-lib ta-lib-0.4.0-src.tar.gz - -# Set timezone to UTC -ENV TZ=UTC - -WORKDIR /app - -# Copy backend binary from builder -COPY --from=backend-builder /app/nofx . - -# Copy frontend build from builder -COPY --from=frontend-builder /app/web/dist ./web/dist - -# Create directories for logs and data -RUN mkdir -p /app/decision_logs - -# Expose ports -# 8080 for backend API -EXPOSE 8080 - -# Health check -HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \ - CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1 - -# Run the application -CMD ["./nofx"] diff --git a/docker-compose.yml b/docker-compose.yml index e273f511..dad8b7a4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,11 +1,11 @@ version: '3.8' services: - # NOFX Trading Backend + # Backend service (API and core logic) nofx: build: context: . - dockerfile: Dockerfile + dockerfile: ./docker/Dockerfile.backend container_name: nofx-trading restart: unless-stopped ports: @@ -13,10 +13,9 @@ services: volumes: - ./config.json:/app/config.json:ro - ./decision_logs:/app/decision_logs - - /etc/localtime:/etc/localtime:ro # 同步主机时间 - - frontend-dist:/app/web/dist-shared:rw # 共享前端文件 + - /etc/localtime:/etc/localtime:ro # Sync host time environment: - - TZ=${NOFX_TIMEZONE:-Asia/Shanghai} # 使用中国时区 + - TZ=${NOFX_TIMEZONE:-Asia/Shanghai} # Set timezone networks: - nofx-network healthcheck: @@ -25,26 +24,27 @@ services: timeout: 10s retries: 3 start_period: 60s - command: sh -c "cp -r /app/web/dist/* /app/web/dist-shared/ 2>/dev/null || true && exec ./nofx" - # Frontend (Nginx) + # Frontend service (static serving and proxy) nofx-frontend: - image: nginx:alpine + build: + context: . + dockerfile: ./docker/Dockerfile.frontend container_name: nofx-frontend restart: unless-stopped ports: - "${NOFX_FRONTEND_PORT:-3000}:80" - volumes: - - frontend-dist:/usr/share/nginx/html:ro - - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro networks: - nofx-network depends_on: - nofx - -volumes: - frontend-dist: + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s networks: nofx-network: - driver: bridge + driver: bridge \ No newline at end of file diff --git a/docker/Dockerfile.backend b/docker/Dockerfile.backend new file mode 100644 index 00000000..18387f67 --- /dev/null +++ b/docker/Dockerfile.backend @@ -0,0 +1,68 @@ +# docker/backend/Dockerfile + +# ═══════════════════════════════════════════════════════════════ +# NOFX Backend Dockerfile (Go + TA-Lib) +# Multi-stage build with shared TA-Lib compilation stage +# Versions extracted as ARGs for maintainability +# ═══════════════════════════════════════════════════════════════ + +ARG GO_VERSION=1.25-alpine +ARG ALPINE_VERSION=latest +ARG TA_LIB_VERSION=0.4.0 + +# ────────────────────────────────────────────────────────────── +# TA-Lib Build Stage (shared across builds) +# ────────────────────────────────────────────────────────────── +FROM alpine:${ALPINE_VERSION} AS ta-lib-builder +ARG TA_LIB_VERSION + +RUN apk update && apk add --no-cache \ + wget tar make gcc g++ musl-dev autoconf automake + +RUN wget http://prdownloads.sourceforge.net/ta-lib/ta-lib-${TA_LIB_VERSION}-src.tar.gz && \ + tar -xzf ta-lib-${TA_LIB_VERSION}-src.tar.gz && \ + cd ta-lib && \ + if [ "$(uname -m)" = "aarch64" ]; then \ + CONFIG_GUESS=$(find /usr/share -name config.guess | head -1) && \ + CONFIG_SUB=$(find /usr/share -name config.sub | head -1) && \ + cp "$CONFIG_GUESS" config.guess && \ + cp "$CONFIG_SUB" config.sub && \ + chmod +x config.guess config.sub; \ + fi && \ + ./configure --prefix=/usr/local && \ + make && make install && \ + cd .. && rm -rf ta-lib ta-lib-${TA_LIB_VERSION}-src.tar.gz + +# ────────────────────────────────────────────────────────────── +# Backend Build Stage (Go Application) +# ────────────────────────────────────────────────────────────── +FROM golang:${GO_VERSION} AS backend-builder + +RUN apk update && apk add --no-cache git make gcc g++ musl-dev + +COPY --from=ta-lib-builder /usr/local /usr/local + +WORKDIR /app +COPY go.mod go.sum ./ +RUN go mod download + +COPY . . +RUN CGO_ENABLED=1 GOOS=linux go build -trimpath -ldflags="-s -w" -o nofx . + +# ────────────────────────────────────────────────────────────── +# Runtime Stage (Minimal Executable Environment) +# ────────────────────────────────────────────────────────────── +FROM alpine:${ALPINE_VERSION} + +RUN apk update && apk add --no-cache ca-certificates tzdata + +COPY --from=ta-lib-builder /usr/local /usr/local +WORKDIR /app +COPY --from=backend-builder /app/nofx . + +EXPOSE 8080 + +HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \ + CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1 + +CMD ["./nofx"] diff --git a/docker/Dockerfile.frontend b/docker/Dockerfile.frontend new file mode 100644 index 00000000..75098bd1 --- /dev/null +++ b/docker/Dockerfile.frontend @@ -0,0 +1,36 @@ +# docker/frontend/Dockerfile + +# ═══════════════════════════════════════════════════════════════ +# NOFX Frontend Dockerfile (Node Build → Nginx Runtime) +# Versions extracted as ARGs for consistency +# ═══════════════════════════════════════════════════════════════ + +ARG NODE_VERSION=20-alpine +ARG NGINX_VERSION=alpine + +# ────────────────────────────────────────────────────────────── +# Build Stage (Node) +# ────────────────────────────────────────────────────────────── +FROM node:${NODE_VERSION} AS builder +WORKDIR /build + +COPY web/package*.json ./ +RUN npm ci + +COPY web/ ./ +RUN npm run build + +# ────────────────────────────────────────────────────────────── +# Runtime Stage (Nginx) +# ────────────────────────────────────────────────────────────── +FROM nginx:${NGINX_VERSION} + +COPY nginx/nginx.conf /etc/nginx/conf.d/default.conf +COPY --from=builder /build/dist /usr/share/nginx/html + +EXPOSE 80 + +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ + CMD wget --no-verbose --tries=1 --spider http://localhost/health || exit 1 + +CMD ["nginx", "-g", "daemon off;"] diff --git a/nginx.conf b/nginx/nginx.conf similarity index 67% rename from nginx.conf rename to nginx/nginx.conf index 4c5abf81..e09eec2c 100644 --- a/nginx.conf +++ b/nginx/nginx.conf @@ -1,3 +1,6 @@ +# nginx.conf - Extracted Nginx configuration for NOFX Frontend +# This configuration merges enhancements from provided variants: improved gzip, static asset caching, adjusted API proxy (preserving /api/ path), extended timeouts, and a static health response for frontend independence. + server { listen 80; server_name localhost; @@ -6,13 +9,13 @@ server { root /usr/share/nginx/html; index index.html; - # Gzip compression + # Gzip compression (enhanced) gzip on; gzip_vary on; gzip_min_length 1024; gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/javascript application/json; - # Frontend routes (SPA) + # Frontend routes (SPA) with static asset caching location / { try_files $uri $uri/ /index.html; @@ -23,9 +26,9 @@ server { } } - # Proxy API requests to backend + # Proxy API requests to backend (preserves /api/ path, with timeouts) location /api/ { - proxy_pass http://nofx-trading:8080; + proxy_pass http://nofx:8080/api/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; @@ -41,9 +44,10 @@ server { proxy_read_timeout 300s; } - # Health check endpoint + # Health check endpoint (static response for frontend health, independent of backend) location /health { return 200 "OK\n"; add_header Content-Type text/plain; + access_log off; } -} +} \ No newline at end of file diff --git a/web/Dockerfile b/web/Dockerfile deleted file mode 100644 index f7614cad..00000000 --- a/web/Dockerfile +++ /dev/null @@ -1,72 +0,0 @@ -# 构建阶段 -FROM node:20-alpine AS builder - -# 设置工作目录 -WORKDIR /app - -# 复制 package 文件 -COPY package*.json ./ - -# 安装依赖 -RUN npm ci --only=production=false - -# 复制源代码 -COPY . . - -# 构建应用 -RUN npm run build - -# 运行阶段 -FROM nginx:alpine - -# 复制自定义 nginx 配置 -COPY <