摘要

本文详细介绍了如何使用Docker部署TrendRadar项目,实现多平台新闻聚合与智能推送。我们将从Docker镜像构建、容器编排、环境变量配置等方面深入探讨,帮助开发者快速搭建一个高效、稳定的新闻推送系统。

正文

1. 引言

TrendRadar作为一个热点资讯聚合系统,其核心功能是定时抓取多个平台的热搜数据,并通过智能算法筛选和排序后推送给用户。为了实现高可用性和易部署性,项目提供了基于Docker的部署方案。

Docker化部署的优势:

  • 环境隔离,避免依赖冲突
  • 一键部署,简化安装过程
  • 资源控制,提高系统稳定性
  • 易于扩展,支持多实例部署

2. Docker镜像构建

TrendRadar的Docker镜像基于Python官方镜像构建,使用多阶段构建优化镜像大小。

2.1 Dockerfile分析
FROM python:3.10-slim

WORKDIR /app

# 安装supercronic定时任务工具
ARG TARGETARCH
ENV SUPERCRONIC_VERSION=v0.2.34

RUN set -ex && \
    apt-get update && \
    apt-get install -y --no-install-recommends curl ca-certificates && \
    # 根据架构下载对应的supercronic版本
    case ${TARGETARCH} in \
    amd64) \
    export SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/${SUPERCRONIC_VERSION}/supercronic-linux-amd64; \
    export SUPERCRONIC_SHA1SUM=e8631edc1775000d119b70fd40339a7238eece14; \
    export SUPERCRONIC=supercronic-linux-amd64; \
    ;; \
    arm64) \
    export SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/${SUPERCRONIC_VERSION}/supercronic-linux-arm64; \
    export SUPERCRONIC_SHA1SUM=4ab6343b52bf9da592e8b4bb7ae6eb5a8e21b71e; \
    export SUPERCRONIC=supercronic-linux-arm64; \
    ;; \
    *) \
    echo "Unsupported architecture: ${TARGETARCH}"; \
    exit 1; \
    ;; \
    esac && \
    # 下载并验证supercronic
    echo "Downloading supercronic for ${TARGETARCH} from ${SUPERCRONIC_URL}" && \
    for i in 1 2 3 4 5; do \
    echo "Download attempt $i/5"; \
    if curl --fail --silent --show-error --location --retry 3 --retry-delay 2 --connect-timeout 30 --max-time 120 -o "$SUPERCRONIC" "$SUPERCRONIC_URL"; then \
    echo "Download successful"; \
    break; \
    else \
    echo "Download attempt $i failed, exit code: $?"; \
    if [ $i -eq 5 ]; then \
    echo "All download attempts failed"; \
    exit 1; \
    fi; \
    sleep $((i * 2)); \
    fi; \
    done && \
    echo "${SUPERCRONIC_SHA1SUM}  ${SUPERCRONIC}" | sha1sum -c - && \
    chmod +x "$SUPERCRONIC" && \
    mv "$SUPERCRONIC" "/usr/local/bin/${SUPERCRONIC}" && \
    ln -s "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic && \
    # 验证安装
    supercronic -version && \
    apt-get remove -y curl && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# 安装Python依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 复制应用代码
COPY main.py .
COPY docker/manage.py .

# 复制入口脚本并设置权限
COPY docker/entrypoint.sh /entrypoint.sh.tmp
RUN sed -i 's/\r$//' /entrypoint.sh.tmp && \
    mv /entrypoint.sh.tmp /entrypoint.sh && \
    chmod +x /entrypoint.sh && \
    chmod +x manage.py && \
    mkdir -p /app/config /app/output

# 设置环境变量
ENV PYTHONUNBUFFERED=1 \
    CONFIG_PATH=/app/config/config.yaml \
    FREQUENCY_WORDS_PATH=/app/config/frequency_words.txt

ENTRYPOINT ["/entrypoint.sh"]
2.2 构建优化策略
  1. 多架构支持:支持amd64和arm64架构
  2. 依赖缓存:利用Docker层缓存机制优化构建速度
  3. 安全验证:通过SHA1SUM验证下载文件完整性
  4. 镜像精简:清理不必要的包管理器缓存

3. 容器编排与部署

TrendRadar提供了完整的docker-compose配置,简化部署过程。

3.1 docker-compose.yml配置
services:
  trend-radar:
    image: wantcat/trendradar:latest
    container_name: trend-radar
    restart: unless-stopped

    volumes:
      - ../config:/app/config:ro
      - ../output:/app/output

    environment:
      - TZ=Asia/Shanghai
      # 核心配置
      - ENABLE_CRAWLER=${ENABLE_CRAWLER:-}
      - ENABLE_NOTIFICATION=${ENABLE_NOTIFICATION:-}
      - REPORT_MODE=${REPORT_MODE:-}
      # 推送时间窗口
      - PUSH_WINDOW_ENABLED=${PUSH_WINDOW_ENABLED:-}
      - PUSH_WINDOW_START=${PUSH_WINDOW_START:-}
      - PUSH_WINDOW_END=${PUSH_WINDOW_END:-}
      - PUSH_WINDOW_ONCE_PER_DAY=${PUSH_WINDOW_ONCE_PER_DAY:-}
      - PUSH_WINDOW_RETENTION_DAYS=${PUSH_WINDOW_RETENTION_DAYS:-}
      # 通知渠道
      - FEISHU_WEBHOOK_URL=${FEISHU_WEBHOOK_URL:-}
      - TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN:-}
      - TELEGRAM_CHAT_ID=${TELEGRAM_CHAT_ID:-}
      - DINGTALK_WEBHOOK_URL=${DINGTALK_WEBHOOK_URL:-}
      - WEWORK_WEBHOOK_URL=${WEWORK_WEBHOOK_URL:-}
      # 邮件配置
      - EMAIL_FROM=${EMAIL_FROM:-}
      - EMAIL_PASSWORD=${EMAIL_PASSWORD:-}
      - EMAIL_TO=${EMAIL_TO:-}
      - EMAIL_SMTP_SERVER=${EMAIL_SMTP_SERVER:-}
      - EMAIL_SMTP_PORT=${EMAIL_SMTP_PORT:-}
      # ntfy配置
      - NTFY_SERVER_URL=${NTFY_SERVER_URL:-https://ntfy.sh}
      - NTFY_TOPIC=${NTFY_TOPIC:-}
      - NTFY_TOKEN=${NTFY_TOKEN:-}
      # 运行模式
      - CRON_SCHEDULE=${CRON_SCHEDULE:-*/5 * * * *}
      - RUN_MODE=${RUN_MODE:-cron}
      - IMMEDIATE_RUN=${IMMEDIATE_RUN:-true}
3.2 环境变量配置

通过.env文件配置环境变量:

# ============================================
# 核心配置(环境变量优先级 > config.yaml)
# ============================================

# 是否启用爬虫 (true/false)
ENABLE_CRAWLER=
# 是否启用通知 (true/false)
ENABLE_NOTIFICATION=
# 报告模式 (all/filtered)
REPORT_MODE=

# ============================================
# 推送时间窗口配置
# ============================================

# 是否启用推送时间窗口 (true/false)
PUSH_WINDOW_ENABLED=
# 推送开始时间 (HH:MM 格式,如 08:00)
PUSH_WINDOW_START=
# 推送结束时间 (HH:MM 格式,如 22:00)
PUSH_WINDOW_END=
# 每天只推送一次 (true/false)
PUSH_WINDOW_ONCE_PER_DAY=
# 推送记录保留天数 (数字,如 7)
PUSH_WINDOW_RETENTION_DAYS=

# ============================================
# 通知渠道配置
# ============================================

# 推送配置
FEISHU_WEBHOOK_URL=
TELEGRAM_BOT_TOKEN=
TELEGRAM_CHAT_ID=
DINGTALK_WEBHOOK_URL=
WEWORK_WEBHOOK_URL=

EMAIL_FROM=
EMAIL_PASSWORD=
EMAIL_TO=
EMAIL_SMTP_SERVER=
EMAIL_SMTP_PORT=

# ntfy 推送配置
NTFY_SERVER_URL=https://ntfy.sh
# ntfy主题名称
NTFY_TOPIC=
# 可选:访问令牌(用于私有主题)
NTFY_TOKEN=

# ============================================
# 运行配置
# ============================================

# 定时任务表达式,每 30 分钟执行一次(比如 8点,8点半,9点,9点半这种时间规律执行)
CRON_SCHEDULE=*/30 * * * *
# 运行模式:cron/once
RUN_MODE=cron
# 启动时立即执行一次
IMMEDIATE_RUN=true

4. 容器管理工具

TrendRadar提供了专门的管理工具[manage.py](file:///e:/Dify/TrendRadar/docker/manage.py),用于容器状态监控和管理。

4.1 状态监控
def show_status():
    """显示容器状态"""
    print("📊 容器状态:")

    # 检查 PID 1 状态
    supercronic_is_pid1 = False
    pid1_cmdline = ""
    try:
        with open('/proc/1/cmdline', 'r') as f:
            pid1_cmdline = f.read().replace('\x00', ' ').strip()
        print(f"  🔍 PID 1 进程: {pid1_cmdline}")
        
        if "supercronic" in pid1_cmdline.lower():
            print("  ✅ supercronic 正确运行为 PID 1")
            supercronic_is_pid1 = True
        else:
            print("  ❌ PID 1 不是 supercronic")
            print(f"  📋 实际的 PID 1: {pid1_cmdline}")
    except Exception as e:
        print(f"  ❌ 无法读取 PID 1 信息: {e}")
4.2 手动执行
def manual_run():
    """手动执行一次爬虫"""
    print("🔄 手动执行爬虫...")
    try:
        result = subprocess.run(
            ["python", "main.py"], cwd="/app", capture_output=False, text=True
        )
        if result.returncode == 0:
            print("✅ 执行完成")
        else:
            print(f"❌ 执行失败,退出码: {result.returncode}")
    except Exception as e:
        print(f"❌ 执行出错: {e}")

5. 入口脚本分析

入口脚本[entrypoint.sh](file:///e:/Dify/TrendRadar/docker/entrypoint.sh)负责容器启动时的初始化工作:

#!/bin/bash
set -e

# 检查配置文件
if [ ! -f "/app/config/config.yaml" ] || [ ! -f "/app/config/frequency_words.txt" ]; then
    echo "❌ 配置文件缺失"
    exit 1
fi

# 保存环境变量
env >> /etc/environment

case "${RUN_MODE:-cron}" in
"once")
    echo "🔄 单次执行"
    exec /usr/local/bin/python main.py
    ;;
"cron")
    # 生成 crontab
    echo "${CRON_SCHEDULE:-*/30 * * * *} cd /app && /usr/local/bin/python main.py" > /tmp/crontab
    
    echo "📅 生成的crontab内容:"
    cat /tmp/crontab

    if ! /usr/local/bin/supercronic -test /tmp/crontab; then
        echo "❌ crontab格式验证失败"
        exit 1
    fi

    # 立即执行一次(如果配置了)
    if [ "${IMMEDIATE_RUN:-false}" = "true" ]; then
        echo "▶️ 立即执行一次"
        /usr/local/bin/python main.py
    fi

    echo "⏰ 启动supercronic: ${CRON_SCHEDULE:-*/30 * * * *}"
    echo "🎯 supercronic 将作为 PID 1 运行"
    
    exec /usr/local/bin/supercronic -passthrough-logs /tmp/crontab
    ;;
*)
    exec "$@"
    ;;
esac

6. 部署实践

6.1 快速部署
# 创建项目目录结构
mkdir -p trendradar/{config,docker}
cd trendradar

# 下载配置文件模板
wget https://raw.githubusercontent.com/sansan0/TrendRadar/master/config/config.yaml -P config/
wget https://raw.githubusercontent.com/sansan0/TrendRadar/master/config/frequency_words.txt -P config/

# 下载 docker-compose 配置
wget https://raw.githubusercontent.com/sansan0/TrendRadar/master/docker/.env
wget https://raw.githubusercontent.com/sansan0/TrendRadar/master/docker/docker-compose.yml

# 启动服务
docker-compose pull
docker-compose up -d
6.2 配置文件说明

目录结构:

trendradar/
├── config/
│   ├── config.yaml      # 主配置文件
│   └── frequency_words.txt  # 关键词配置
└── docker/
    ├── .env             # 环境变量配置
    └── docker-compose.yml   # 容器编排配置

7. 环境变量覆盖机制

TrendRadar支持通过环境变量覆盖配置文件中的设置,这对于在不同环境中部署非常有用:

环境变量对应配置示例值说明
ENABLE_CRAWLERcrawler.enable_crawlertrue / false是否启用爬虫
ENABLE_NOTIFICATIONnotification.enable_notificationtrue / false是否启用通知
REPORT_MODEreport.modeall / filtered报告模式
PUSH_WINDOW_ENABLEDnotification.push_window.enabledtrue / false推送时间窗口开关

8. 故障排查

常见问题及解决方案:

# 检查容器状态
docker inspect trend-radar

# 查看容器日志
docker logs --tail 100 trend-radar

# 进入容器调试
docker exec -it trend-radar /bin/bash

# 验证配置文件
docker exec -it trend-radar ls -la /app/config/

总结

通过Docker化部署,TrendRadar实现了环境隔离、一键部署和高可用性。其基于supercronic的定时任务系统确保了新闻抓取的稳定性,而灵活的环境变量配置机制使得在不同环境中部署变得简单。开发者可以基于这些机制快速搭建自己的新闻推送系统。

参考资料

  1. TrendRadar GitHub仓库:https://github.com/sansan0/TrendRadar
  2. Docker官方文档:https://docs.docker.com/
  3. supercronic项目:https://github.com/aptible/supercronic

更多推荐