docker部署

This commit is contained in:
2026-05-10 23:26:56 +08:00
parent 2af39e8eb5
commit f0ed88fdf8
12 changed files with 536 additions and 4 deletions
+61
View File
@@ -0,0 +1,61 @@
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
venv/
env/
ENV/
.venv/
# IDE
.idea/
.vscode/
*.swp
*.swo
*~
# Git
.git/
.gitignore
# Docker
Dockerfile
docker-compose.yml
.dockerignore
# Logs (运行时生成)
logs/
*.log
# Local storage (运行时生成)
storage/*.sqlite3
storage/binlog_position.json
# Temporary files
*.tmp
*.temp
.cache/
# Test files
tests/
test_*.py
*_test.py
.pytest_cache/
.coverage
htmlcov/
# Distribution
dist/
build/
*.egg-info/
# OS
.DS_Store
Thumbs.db
# Other
.arts/
*.md
!README.md
+48
View File
@@ -0,0 +1,48 @@
# MyAPS API Dockerfile
# 多阶段构建,优化镜像体积
# 构建阶段
FROM python:3.12-slim AS builder
WORKDIR /app
RUN sed -i 's/deb.debian.org/mirrors.tencentyun.com/g' /etc/apt/sources.list.d/debian.sources \
&& apt-get update && apt-get install -y --no-install-recommends \
gcc \
libpq-dev \
default-libmysqlclient-dev \
&& rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip config set global.index-url http://mirrors.tencentyun.com/pypi/simple \
&& pip config set install.trusted-host mirrors.tencentyun.com \
&& pip install --no-cache-dir --user -r requirements.txt
# 运行阶段
FROM python:3.12-slim
WORKDIR /app
RUN sed -i 's/deb.debian.org/mirrors.tencentyun.com/g' /etc/apt/sources.list.d/debian.sources \
&& apt-get update && apt-get install -y --no-install-recommends \
libpq5 \
libmariadb3 \
curl \
&& rm -rf /var/lib/apt/lists/* \
&& mkdir -p /app/logs /app/storage /app/project_files
COPY --from=builder /root/.local /root/.local
ENV PATH=/root/.local/bin:$PATH
ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1
COPY . .
EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8000/docs || exit 1
CMD ["gunicorn", "-c", "scripts/deploy/gunicorn.conf.py", "main:app"]
+65
View File
@@ -0,0 +1,65 @@
# MyAPS API Docker Compose 配置
# 使用方法: docker-compose up -d
services:
redis:
image: redis:7-alpine
container_name: myaps_redis
restart: unless-stopped
ports:
- "${REDIS_PORT:-6379}:6379"
volumes:
- redis_data:/data
command: redis-server --appendonly yes ${REDIS_PASSWORD:+--requirepass ${REDIS_PASSWORD}}
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
networks:
- myaps_network
app:
build:
context: .
dockerfile: Dockerfile
image: myaps_api:latest
container_name: myaps_api
restart: unless-stopped
ports:
- "${PORT:-8000}:8000"
env_file:
- .env
environment:
- REDIS_HOST=redis
- GUNICORN_BIND=0.0.0.0:8000
- APP_ROOT=/app
volumes:
- ./logs:/app/logs
- ./project_files:/app/project_files
- ./static:/app/static
- ./storage:/app/storage
- ./apps:/app/apps
- ./core:/app/core
- ./globalobjects:/app/globalobjects
- ./scripts:/app/scripts
- ./main.py:/app/main.py
depends_on:
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/docs"]
interval: 30s
timeout: 10s
start_period: 10s
retries: 3
networks:
- myaps_network
volumes:
redis_data:
driver: local
networks:
myaps_network:
driver: bridge
+8 -4
View File
@@ -2,13 +2,17 @@
import os
import multiprocessing
# 设置工作目录为项目根目录
chdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
working_dir = '/app'
# 设置工作目录
# Docker环境下使用/app,否则基于脚本位置计算
if os.path.exists('/app/main.py'):
chdir = '/app'
else:
chdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# 进程数
workers = min(multiprocessing.cpu_count(), 4)
worker_class = "uvicorn.workers.UvicornWorker"
bind = "127.0.0.1:8000"
bind = os.getenv("GUNICORN_BIND", "127.0.0.1:8000")
timeout = 30
# 日志配置
+151
View File
@@ -0,0 +1,151 @@
# MyAPS API Docker 部署指南
## 环境要求
- Docker 20.10+
- Docker Compose V2
- Python 3.12(镜像内置)
## 快速开始
```bash
# 构建镜像
docker-compose build
# 启动服务
docker-compose up -d
# 查看状态
docker-compose ps
# 查看日志
docker-compose logs -f
```
## 辅助脚本
```bash
cd scripts/deploy_docker
./build.sh # 构建镜像 (默认 latest)
./build.sh v1.0 # 构建指定版本
./start.sh # 启动服务
./stop.sh # 停止服务
./restart.sh # 重启服务
./status.sh # 查看状态
./export_image.sh # 导出镜像 (离线部署用)
./import_image.sh # 导入镜像
```
## 环境配置
配置文件 `.env` 会被自动读取,以下变量会被容器环境覆盖:
| 变量 | 容器内值 | 说明 |
|-----|---------|------|
| `REDIS_HOST` | `redis` | 容器名访问 |
| `GUNICORN_BIND` | `0.0.0.0:8000` | 容器内监听 |
| `APP_ROOT` | `/app` | 容器工作目录 |
## 数据持久化
以下目录已配置持久化挂载:
- `logs/` - 应用日志
- `project_files/` - 项目配置缓存
- `static/` - 静态文件
- `storage/` - 存储目录(SQLite、Binlog位置等)
- `apps/` - 应用代码(开发模式热更新)
- `core/` - 核心配置(开发模式热更新)
- `globalobjects/` - 全局对象(开发模式热更新)
- `scripts/` - 脚本文件(开发模式热更新)
- `redis_data` - Redis数据卷
> 注意:生产环境建议移除代码目录挂载,使用镜像内置代码以获得更好隔离性。
## 常用命令
```bash
# 查看应用日志
docker-compose logs -f app
# 进入容器
docker exec -it myaps_api bash
# 重新构建并启动
docker-compose up -d --build
# 停止并清理
docker-compose down
# 停止并清理卷
docker-compose down -v
```
## 版本更新
```bash
# 拉取最新代码
git pull
# 重新构建并启动(零停机)
docker-compose up -d --build
# 或使用脚本
./build.sh v2.0
docker-compose up -d
```
## 回滚操作
```bash
# 回滚到指定版本
docker tag myaps_api:v1.0 myaps_api:latest
docker-compose up -d
```
## 离线部署
```bash
# 导出镜像
./export_image.sh v1.0 /path/to/output
# 在目标机器导入
./import_image.sh /path/to/myaps_api_v1.0.tar
# 启动服务
./start.sh
```
## 健康检查
- 应用健康检查: `curl http://localhost:8000/docs`
- Redis健康检查: `docker exec myaps_redis redis-cli ping`
- 查看容器健康状态: `docker ps --format "table {{.Names}}\t{{.Status}}"`
## 镜像信息
| 项目 | 值 |
|-----|-----|
| 基础镜像 | python:3.12-slim |
| 镜像大小 | ~460MB |
| 多阶段构建 | 是 |
| 国内镜像源 | 已配置(腾讯云) |
## 故障排查
```bash
# 查看应用日志
docker-compose logs -f app
# 查看启动失败原因
docker logs myaps_api 2>&1 | head -50
# 进入容器调试
docker exec -it myaps_api bash
# 检查容器内文件
docker exec myaps_api ls -la /app/
```
+27
View File
@@ -0,0 +1,27 @@
#!/bin/bash
# 构建Docker镜像
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")"
cd "$PROJECT_ROOT"
echo "=========================================="
echo " MyAPS API Docker 镜像构建"
echo "=========================================="
VERSION="${1:-latest}"
IMAGE_NAME="myaps_api:$VERSION"
echo ""
echo "构建镜像: $IMAGE_NAME"
echo ""
docker build -t "$IMAGE_NAME" .
echo ""
echo "✅ 镜像构建完成: $IMAGE_NAME"
echo ""
docker images myaps_api
+35
View File
@@ -0,0 +1,35 @@
#!/bin/bash
# 导出Docker镜像(用于离线部署)
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")"
cd "$PROJECT_ROOT"
echo "=========================================="
echo " MyAPS API Docker 镜像导出"
echo "=========================================="
VERSION="${1:-latest}"
OUTPUT_DIR="${2:-$SCRIPT_DIR}"
IMAGE_NAME="myaps_api:$VERSION"
OUTPUT_FILE="$OUTPUT_DIR/myaps_api_$VERSION.tar"
echo ""
echo "导出镜像: $IMAGE_NAME"
echo "输出文件: $OUTPUT_FILE"
echo ""
if ! docker images "$IMAGE_NAME" | grep -q "myaps_api"; then
echo "❌ 镜像不存在,请先构建镜像"
echo "运行: ./build.sh $VERSION"
exit 1
fi
docker save -o "$OUTPUT_FILE" "$IMAGE_NAME"
echo ""
echo "✅ 镜像已导出: $OUTPUT_FILE"
ls -lh "$OUTPUT_FILE"
+30
View File
@@ -0,0 +1,30 @@
#!/bin/bash
# 导入Docker镜像(用于离线部署)
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")"
cd "$PROJECT_ROOT"
echo "=========================================="
echo " MyAPS API Docker 镜像导入"
echo "=========================================="
IMAGE_FILE="${1:-$SCRIPT_DIR/myaps_api_latest.tar}"
if [ ! -f "$IMAGE_FILE" ]; then
echo "❌ 镜像文件不存在: $IMAGE_FILE"
exit 1
fi
echo ""
echo "导入镜像: $IMAGE_FILE"
echo ""
docker load -i "$IMAGE_FILE"
echo ""
echo "✅ 镜像已导入"
docker images myaps_api
+26
View File
@@ -0,0 +1,26 @@
#!/bin/bash
# 重启Docker服务
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")"
cd "$PROJECT_ROOT"
echo "=========================================="
echo " MyAPS API Docker 服务重启"
echo "=========================================="
echo ""
echo "重启服务..."
echo ""
docker-compose restart
echo ""
echo "服务状态:"
docker-compose ps
echo ""
echo "✅ 服务已重启"
+39
View File
@@ -0,0 +1,39 @@
#!/bin/bash
# 启动Docker服务
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")"
cd "$PROJECT_ROOT"
echo "=========================================="
echo " MyAPS API Docker 服务启动"
echo "=========================================="
if [ ! -f ".env" ]; then
echo "❌ 错误: .env 文件不存在"
echo "请先创建 .env 配置文件"
exit 1
fi
echo ""
echo "启动服务..."
echo ""
docker-compose up -d
echo ""
echo "等待服务启动..."
sleep 5
echo ""
echo "服务状态:"
docker-compose ps
echo ""
echo "✅ 服务已启动"
echo ""
echo "访问地址: http://localhost:${PORT:-8000}"
echo "查看日志: docker-compose logs -f"
+24
View File
@@ -0,0 +1,24 @@
#!/bin/bash
# 查看Docker服务状态
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")"
cd "$PROJECT_ROOT"
echo "=========================================="
echo " MyAPS API Docker 服务状态"
echo "=========================================="
echo ""
docker-compose ps
echo ""
echo "容器健康状态:"
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | grep -E "NAMES|myaps"
echo ""
echo "日志查看命令:"
echo " 全部日志: docker-compose logs -f"
echo " 应用日志: docker-compose logs -f app"
echo " Redis日志: docker-compose logs -f redis"
+22
View File
@@ -0,0 +1,22 @@
#!/bin/bash
# 停止Docker服务
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")"
cd "$PROJECT_ROOT"
echo "=========================================="
echo " MyAPS API Docker 服务停止"
echo "=========================================="
echo ""
echo "停止服务..."
echo ""
docker-compose down
echo ""
echo "✅ 服务已停止"