diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..3185a16 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,45 @@ +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +*.egg-info/ +dist/ +build/ + +# 虚拟环境 +venv/ +env/ +ENV/ + +# IDE +.vscode/ +.idea/ +*.swp +*.swo + +# Git +.git/ +.gitignore + +# 数据库文件(使用 volume 挂载) +*.db +*.sqlite +*.sqlite3 + +# 日志 +*.log + +# 临时文件 +.DS_Store +Thumbs.db + +# Docker +Dockerfile +docker-compose.yml +.dockerignore + +# 文档 +README.md +*.md diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..15528bf --- /dev/null +++ b/.env.example @@ -0,0 +1,17 @@ +# Flask 配置 +FLASK_APP=web_outlook_app.py +FLASK_ENV=production + +# 应用配置 +PORT=5000 +HOST=0.0.0.0 + +# 登录密码(请修改为你自己的密码) +LOGIN_PASSWORD=admin123 + +# 数据库配置 +DATABASE_PATH=data/outlook_accounts.db + +# GPTMail 配置 +GPTMAIL_BASE_URL=https://mail.chatgpt.org.uk +GPTMAIL_API_KEY=gpt-test diff --git a/.github/workflows/docker-build-push.yml b/.github/workflows/docker-build-push.yml new file mode 100644 index 0000000..c4ae42f --- /dev/null +++ b/.github/workflows/docker-build-push.yml @@ -0,0 +1,62 @@ +name: Build and Push Docker Image + +on: + push: + branches: + - main + - master + paths: + - '**.py' + - 'requirements.txt' + - 'Dockerfile' + - 'templates/**' + workflow_dispatch: + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=ref,event=branch + type=sha,prefix={{branch}}- + type=raw,value=latest,enable={{is_default_branch}} + + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + platforms: linux/amd64,linux/arm64 + + - name: Image digest + run: echo ${{ steps.meta.outputs.digest }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6e351b0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,34 @@ +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +*.egg-info/ +dist/ +build/ +venv/ +env/ +ENV/ + +# 数据库文件 +*.db +*.sqlite +*.sqlite3 +data/ + +# 环境变量 +.env + +# IDE +.vscode/ +.idea/ +*.swp +*.swo + +# 日志 +*.log + +# 系统文件 +.DS_Store +Thumbs.db diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..610817d --- /dev/null +++ b/Dockerfile @@ -0,0 +1,29 @@ +# 使用 Python 3.11 作为基础镜像 +FROM python:3.11-slim + +# 设置工作目录 +WORKDIR /app + +# 设置环境变量 +ENV PYTHONUNBUFFERED=1 \ + PYTHONDONTWRITEBYTECODE=1 \ + PIP_NO_CACHE_DIR=1 + +# 复制依赖文件 +COPY requirements.txt . + +# 安装依赖 +RUN pip install --upgrade pip && \ + pip install -r requirements.txt + +# 复制应用代码 +COPY . . + +# 创建数据目录 +RUN mkdir -p /app/data + +# 暴露端口 +EXPOSE 5000 + +# 启动应用 +CMD ["python", "web_outlook_app.py"] diff --git a/README_DOCKER.md b/README_DOCKER.md new file mode 100644 index 0000000..6339ddf --- /dev/null +++ b/README_DOCKER.md @@ -0,0 +1,219 @@ +# Outlook 邮件阅读器 - Docker 部署指南 + +## 📦 快速开始 + +### 使用 Docker Compose(推荐) + +```bash +# 启动服务 +docker-compose up -d + +# 查看日志 +docker-compose logs -f + +# 停止服务 +docker-compose down +``` + +### 使用 Docker 命令 + +```bash +# 构建镜像 +docker build -t outlook-mail-reader . + +# 运行容器 +docker run -d \ + --name outlook-mail-reader \ + -p 5000:5000 \ + -v $(pwd)/data:/app/data \ + -e LOGIN_PASSWORD=your_password \ + outlook-mail-reader + +# 停止容器 +docker stop outlook-mail-reader +docker rm outlook-mail-reader +``` + +## 🔧 配置说明 + +### 环境变量 + +在 `docker-compose.yml` 中可以配置以下环境变量: + +| 变量名 | 说明 | 默认值 | +|--------|------|--------| +| `LOGIN_PASSWORD` | 登录密码 | `admin123` | +| `FLASK_ENV` | 运行环境 | `production` | +| `DATABASE_PATH` | 数据库路径 | `data/outlook_accounts.db` | +| `GPTMAIL_BASE_URL` | GPTMail API 地址 | `https://mail.chatgpt.org.uk` | +| `GPTMAIL_API_KEY` | GPTMail API Key | `gpt-test` | + +### 数据持久化 + +数据库文件存储在 `./data` 目录中,通过 Docker Volume 挂载实现持久化。 + +### 端口映射 + +默认映射 5000 端口,可以在 `docker-compose.yml` 中修改: + +```yaml +ports: + - "8080:5000" # 将容器的 5000 端口映射到主机的 8080 端口 +``` + +## 🚀 GitHub Actions 自动构建 + +项目已配置 GitHub Actions,当代码推送到 `main` 或 `master` 分支时,会自动构建并推送 Docker 镜像到 GitHub Container Registry。 + +### 使用预构建镜像 + +```bash +# 拉取镜像 +docker pull ghcr.io//:latest + +# 运行容器 +docker run -d \ + --name outlook-mail-reader \ + -p 5000:5000 \ + -v $(pwd)/data:/app/data \ + -e LOGIN_PASSWORD=your_password \ + ghcr.io//:latest +``` + +### 触发构建 + +- 推送代码到 `main` 或 `master` 分支 +- 修改 `*.py`、`requirements.txt`、`Dockerfile`、`templates/**` 文件 +- 手动触发(在 Actions 页面点击 "Run workflow") + +### 镜像标签 + +- `latest` - 最新的主分支构建 +- `main` 或 `master` - 分支名称 +- `main-` - 分支名+提交哈希 + +## 🌐 生产环境部署 + +### 使用 Nginx + HTTPS + +**1. 安装 Nginx** +```bash +sudo apt install nginx certbot python3-certbot-nginx -y +``` + +**2. 配置 Nginx** `/etc/nginx/sites-available/outlook-mail-reader` +```nginx +server { + listen 80; + server_name your-domain.com; + + location / { + proxy_pass http://localhost:5000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} +``` + +**3. 启用配置** +```bash +sudo ln -s /etc/nginx/sites-available/outlook-mail-reader /etc/nginx/sites-enabled/ +sudo nginx -t +sudo systemctl reload nginx +``` + +**4. 配置 HTTPS** +```bash +sudo certbot --nginx -d your-domain.com +``` + +### 使用 Caddy(更简单) + +```bash +# 安装 Caddy +sudo apt install caddy -y + +# 配置 /etc/caddy/Caddyfile +your-domain.com { + reverse_proxy localhost:5000 +} + +# 重载(自动 HTTPS) +sudo systemctl reload caddy +``` + +## 🔐 安全配置 + +### 1. 修改默认密码 + +在 `docker-compose.yml` 中: +```yaml +environment: + - LOGIN_PASSWORD=your_secure_password_here +``` + +### 2. 配置防火墙 + +```bash +sudo ufw allow 80/tcp +sudo ufw allow 443/tcp +sudo ufw enable +``` + +### 3. 限制访问来源(Nginx) + +```nginx +location / { + allow 192.168.1.0/24; # 允许内网 + deny all; # 拒绝其他 + proxy_pass http://localhost:5000; +} +``` + +## 🛠️ 故障排查 + +### 容器无法启动 + +```bash +# 查看日志 +docker-compose logs + +# 检查端口占用 +lsof -i :5000 + +# 检查数据目录权限 +chmod 755 ./data +``` + +### 数据库问题 + +```bash +# 重置数据库 +docker-compose down +rm ./data/outlook_accounts.db +docker-compose up -d +``` + +## 🔄 更新应用 + +### 从源码更新 + +```bash +git pull +docker-compose up -d --build +``` + +### 从镜像更新 + +```bash +docker pull ghcr.io//:latest +docker-compose -f docker-compose.prod.yml up -d +``` + +## 📚 相关文档 + +- [Docker 官方文档](https://docs.docker.com/) +- [Docker Compose 文档](https://docs.docker.com/compose/) +- [GitHub Actions 文档](https://docs.github.com/actions) diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..7278aab --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,32 @@ +version: '3.8' + +services: + outlook-mail-reader: + build: + context: . + dockerfile: Dockerfile + container_name: outlook-mail-reader + restart: unless-stopped + ports: + - "5000:5000" + volumes: + # 持久化数据库文件 + - ./data:/app/data + environment: + # Flask 配置 + - FLASK_APP=web_outlook_app.py + - FLASK_ENV=production + # 可选:自定义登录密码 + # - LOGIN_PASSWORD=your_password + networks: + - outlook-network + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:5000/login"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + +networks: + outlook-network: + driver: bridge diff --git a/web_outlook_app.py b/web_outlook_app.py index 1d94043..f7a2799 100644 --- a/web_outlook_app.py +++ b/web_outlook_app.py @@ -25,7 +25,7 @@ app = Flask(__name__) app.secret_key = os.urandom(24) # 登录密码配置(可以修改为你想要的密码) -LOGIN_PASSWORD = "admin123" +LOGIN_PASSWORD = os.getenv("LOGIN_PASSWORD", "admin123") # ==================== 配置 ==================== # Token 端点 @@ -39,11 +39,11 @@ IMAP_SERVER_NEW = "outlook.live.com" IMAP_PORT = 993 # 数据库文件 -DATABASE = "outlook_accounts.db" +DATABASE = os.getenv("DATABASE_PATH", "data/outlook_accounts.db") # GPTMail API 配置 -GPTMAIL_BASE_URL = "https://mail.chatgpt.org.uk" -GPTMAIL_API_KEY = "gpt-test" # 测试 API Key,可以修改为正式 Key +GPTMAIL_BASE_URL = os.getenv("GPTMAIL_BASE_URL", "https://mail.chatgpt.org.uk") +GPTMAIL_API_KEY = os.getenv("GPTMAIL_API_KEY", "gpt-test") # 测试 API Key,可以修改为正式 Key # 临时邮箱分组 ID(系统保留) TEMP_EMAIL_GROUP_ID = -1 @@ -1556,16 +1556,24 @@ if __name__ == '__main__': # 确保 templates 目录存在 os.makedirs('templates', exist_ok=True) + # 确保数据目录存在 + os.makedirs('data', exist_ok=True) + # 初始化数据库 init_db() - port = 5001 + # 从环境变量获取配置 + port = int(os.getenv('PORT', 5000)) + host = os.getenv('HOST', '0.0.0.0') + debug = os.getenv('FLASK_ENV', 'production') != 'production' + print("=" * 60) print("Outlook 邮件 Web 应用") print("=" * 60) - print(f"访问地址: http://127.0.0.1:{port}") + print(f"访问地址: http://{host}:{port}") print(f"数据库文件: {DATABASE}") print(f"GPTMail API: {GPTMAIL_BASE_URL}") + print(f"运行模式: {'开发' if debug else '生产'}") print("=" * 60) - app.run(debug=True, host='127.0.0.1', port=port) \ No newline at end of file + app.run(debug=debug, host=host, port=port) \ No newline at end of file