强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

11 - Docker 部署

Docker 部署流媒体服务

11.1 为什么使用 Docker

优势说明
环境一致性开发/测试/生产环境完全一致
快速部署一条命令启动完整服务
版本管理轻松切换和回滚版本
资源隔离CPU/内存/网络隔离
可扩展轻松增加实例
可复现部署过程文档化

11.2 SRS Docker 快速启动

11.2.1 单命令启动

# 启动 SRS(最简方式)
docker run --rm \
    -p 1935:1935 \
    -p 1985:1985 \
    -p 8080:8080 \
    ossrs/srs:5

# 推流测试
ffmpeg -re -i test.mp4 -c copy -f flv \
    rtmp://localhost:1935/live/test

# 播放测试
ffplay rtmp://localhost:1935/live/test
ffplay http://localhost:8080/live/test.flv
ffplay http://localhost:8080/live/test.m3u8

11.2.2 使用自定义配置

# 创建配置文件
mkdir -p conf
cat > conf/docker.conf << 'EOF'
listen 1935;
max_connections 1000;
srs_log_tank console;

http_api {
    enabled on;
    listen 1985;
}

http_server {
    enabled on;
    listen 8080;
}

vhost __defaultVhost__ {
    hls {
        enabled on;
        hls_fragment 2;
        hls_window 10;
    }
    http_remux {
        enabled on;
        mount [vhost]/[app]/[stream].flv;
    }
}
EOF

# 挂载配置文件启动
docker run --rm \
    -p 1935:1935 \
    -p 1985:1985 \
    -p 8080:8080 \
    -v $(pwd)/conf/docker.conf:/usr/local/srs/conf/docker.conf \
    ossrs/srs:5 ./objs/srs -c conf/docker.conf

11.3 Docker Compose 基础配置

11.3.1 项目结构

srs-docker/
├── docker-compose.yml
├── conf/
│   ├── srs.conf
│   └── edge.conf
├── web/
│   └── index.html
└── data/
    ├── recordings/
    └── hls/

11.3.2 docker-compose.yml

version: '3.8'

services:
  # SRS 流媒体服务器
  srs:
    image: ossrs/srs:5
    container_name: srs-server
    ports:
      - "1935:1935"    # RTMP
      - "1985:1985"    # HTTP API
      - "8080:8080"    # HTTP Server
    volumes:
      - ./conf/srs.conf:/usr/local/srs/conf/docker.conf
      - ./data/hls:/usr/local/srs/objs/nginx/html
      - ./data/recordings:/data/recordings
    command: ./objs/srs -c conf/docker.conf
    restart: unless-stopped
    networks:
      - srs-net

  # HLS Web 服务(可选)
  nginx:
    image: nginx:alpine
    container_name: srs-nginx
    ports:
      - "80:80"
    volumes:
      - ./data/hls:/usr/share/nginx/html:ro
      - ./web:/usr/share/nginx/html/web:ro
    depends_on:
      - srs
    restart: unless-stopped
    networks:
      - srs-net

networks:
  srs-net:
    driver: bridge

11.3.3 SRS 配置文件

# conf/srs.conf
listen 1935;
max_connections 1000;
srs_log_tank console;

http_api {
    enabled on;
    listen 1985;
}

http_server {
    enabled on;
    listen 8080;
    dir ./objs/nginx/html;
}

vhost __defaultVhost__ {
    # 最小延迟
    min_latency on;

    # GOP Cache
    gop_cache on;
    gop_cache_max_frames 2500;

    # HLS 配置
    hls {
        enabled on;
        hls_fragment 2;
        hls_window 10;
        hls_path ./objs/nginx/html;
        hls_m3u8_file [app]/[stream].m3u8;
        hls_ts_file [app]/[stream]-[seq].ts;
        hls_cleanup on;
        hls_dispose 30;
    }

    # HTTP-FLV
    http_remux {
        enabled on;
        mount [vhost]/[app]/[stream].flv;
    }

    # DVR 录制
    dvr {
        enabled on;
        dvr_path /data/recordings/[app]/[stream].[timestamp].flv;
        dvr_plan session;
        dvr_wait_keyframe on;
    }
}

11.3.4 启动与管理

# 启动所有服务
docker-compose up -d

# 查看状态
docker-compose ps

# 查看日志
docker-compose logs -f srs

# 停止所有服务
docker-compose down

# 重启 SRS
docker-compose restart srs

11.4 多实例集群部署

11.4.1 Origin + Edge 集群

# docker-compose-cluster.yml
version: '3.8'

services:
  # Origin 源站
  srs-origin:
    image: ossrs/srs:5
    container_name: srs-origin
    ports:
      - "1935:1935"
      - "1985:1985"
    volumes:
      - ./conf/origin.conf:/usr/local/srs/conf/docker.conf
    command: ./objs/srs -c conf/docker.conf
    restart: unless-stopped
    networks:
      srs-net:
        ipv4_address: 172.20.0.10

  # Edge 边缘节点 1
  srs-edge-1:
    image: ossrs/srs:5
    container_name: srs-edge-1
    ports:
      - "1936:1935"
      - "1986:1985"
      - "8081:8080"
    volumes:
      - ./conf/edge.conf:/usr/local/srs/conf/docker.conf
    command: ./objs/srs -c conf/docker.conf
    depends_on:
      - srs-origin
    restart: unless-stopped
    networks:
      srs-net:
        ipv4_address: 172.20.0.11

  # Edge 边缘节点 2
  srs-edge-2:
    image: ossrs/srs:5
    container_name: srs-edge-2
    ports:
      - "1937:1935"
      - "1987:1985"
      - "8082:8080"
    volumes:
      - ./conf/edge.conf:/usr/local/srs/conf/docker.conf
    command: ./objs/srs -c conf/docker.conf
    depends_on:
      - srs-origin
    restart: unless-stopped
    networks:
      srs-net:
        ipv4_address: 172.20.0.12

networks:
  srs-net:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/24

11.4.2 Origin 配置

# conf/origin.conf
listen 1935;
max_connections 1000;

http_api {
    enabled on;
    listen 1985;
}

http_server {
    enabled on;
    listen 8080;
}

vhost __defaultVhost__ {
    gop_cache on;
    hls {
        enabled on;
        hls_fragment 2;
        hls_window 10;
    }
}

11.4.3 Edge 配置

# conf/edge.conf
listen 1935;
max_connections 1000;

http_api {
    enabled on;
    listen 1985;
}

http_server {
    enabled on;
    listen 8080;
}

vhost __defaultVhost__ {
    cluster {
        mode remote;
        origin 172.20.0.10:1935;
    }
    gop_cache on;
    hls {
        enabled on;
        hls_fragment 2;
        hls_window 10;
    }
}

11.5 完整生产环境配置

11.5.1 带监控的生产配置

# docker-compose-production.yml
version: '3.8'

services:
  # SRS 流媒体服务器
  srs:
    image: ossrs/srs:5
    container_name: srs-server
    ports:
      - "1935:1935"
      - "1985:1985"
      - "8080:8080"
    volumes:
      - ./conf/srs.conf:/usr/local/srs/conf/docker.conf
      - ./data/hls:/data/hls
      - ./data/recordings:/data/recordings
    command: ./objs/srs -c conf/docker.conf
    restart: unless-stopped
    deploy:
      resources:
        limits:
          cpus: '4.0'
          memory: 4G
        reservations:
          cpus: '2.0'
          memory: 2G
    networks:
      - srs-net

  # Prometheus 指标收集
  prometheus:
    image: prom/prometheus:latest
    container_name: srs-prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus-data:/prometheus
    restart: unless-stopped
    networks:
      - srs-net

  # Grafana 监控面板
  grafana:
    image: grafana/grafana:latest
    container_name: srs-grafana
    ports:
      - "3000:3000"
    volumes:
      - grafana-data:/var/lib/grafana
    environment:
      GF_SECURITY_ADMIN_PASSWORD: admin123
    restart: unless-stopped
    networks:
      - srs-net

  # Nginx 反向代理
  nginx:
    image: nginx:alpine
    container_name: srs-nginx
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./nginx/ssl:/etc/nginx/ssl
      - ./data/hls:/usr/share/nginx/html:ro
    depends_on:
      - srs
    restart: unless-stopped
    networks:
      - srs-net

volumes:
  prometheus-data:
  grafana-data:

networks:
  srs-net:
    driver: bridge

11.5.2 Nginx 反向代理配置

# nginx/nginx.conf
events {
    worker_connections 1024;
}

http {
    # HLS 分发
    server {
        listen 80;
        server_name live.example.com;

        # HLS
        location /hls {
            types {
                application/vnd.apple.mpegurl m3u8;
                video/mp2t ts;
            }
            root /usr/share/nginx/html;
            add_header Cache-Control no-cache;
            add_header Access-Control-Allow-Origin *;
        }

        # HTTP-FLV
        location /live {
            add_header Access-Control-Allow-Origin *;
            add_header Cache-Control no-cache;
            proxy_pass http://srs:8080;
        }

        # SRS API 代理
        location /api {
            proxy_pass http://srs:1985;
        }

        # 监控面板
        location /grafana {
            proxy_pass http://grafana:3000;
        }
    }
}

11.5.3 Prometheus 配置

# prometheus/prometheus.yml
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'srs'
    metrics_path: /api/v1/metrics
    static_configs:
      - targets: ['srs:1985']

11.6 部署脚本

一键部署脚本

#!/bin/bash
# deploy.sh - SRS 一键部署脚本

set -e

PROJECT_DIR="$(cd "$(dirname "$0")" && pwd)"
cd "$PROJECT_DIR"

echo "🚀 开始部署 SRS 流媒体服务..."

# 创建必要目录
mkdir -p conf data/hls data/recordings nginx prometheus

# 检查配置文件
if [ ! -f conf/srs.conf ]; then
    echo "📝 生成默认配置..."
    cat > conf/srs.conf << 'EOF'
listen 1935;
max_connections 1000;
srs_log_tank console;

http_api { enabled on; listen 1985; }
http_server { enabled on; listen 8080; }

vhost __defaultVhost__ {
    min_latency on;
    gop_cache on;
    hls {
        enabled on;
        hls_fragment 2;
        hls_window 10;
    }
    http_remux {
        enabled on;
        mount [vhost]/[app]/[stream].flv;
    }
}
EOF
fi

# 启动服务
echo "🐳 启动 Docker 服务..."
docker-compose up -d

# 等待服务启动
echo "⏳ 等待服务启动..."
sleep 5

# 验证服务
echo "🔍 验证服务状态..."
if curl -s http://localhost:1985/api/v1/summaries > /dev/null; then
    echo "✅ SRS 服务正常"
else
    echo "❌ SRS 服务异常,请检查日志"
    docker-compose logs srs
    exit 1
fi

# 获取本机 IP
LOCAL_IP=$(hostname -I | awk '{print $1}')

echo ""
echo "========================================="
echo "  SRS 流媒体服务部署完成!"
echo "========================================="
echo ""
echo "  推流地址: rtmp://${LOCAL_IP}:1935/live/{stream_key}"
echo "  RTMP 播放: rtmp://${LOCAL_IP}:1935/live/{stream_key}"
echo "  HTTP-FLV:  http://${LOCAL_IP}:8080/live/{stream_key}.flv"
echo "  HLS:       http://${LOCAL_IP}:8080/live/{stream_key}.m3u8"
echo "  API 文档:  http://${LOCAL_IP}:1985"
echo ""
echo "  常用命令:"
echo "    查看日志: docker-compose logs -f srs"
echo "    停止服务: docker-compose down"
echo "    重启服务: docker-compose restart"
echo ""

11.7 流媒体架构图

11.7.1 单机架构

┌──────────────────────────────────────────────────────┐
│                    Docker Host                        │
│                                                      │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  │
│  │ SRS Server  │  │   Nginx     │  │  Grafana    │  │
│  │ :1935(RTMP) │  │   :80(HTTP) │  │  :3000      │  │
│  │ :1985(API)  │  │             │  │             │  │
│  │ :8080(HTTP) │  │             │  │             │  │
│  └──────┬──────┘  └──────┬──────┘  └─────────────┘  │
│         │                │                           │
│         └────────┬───────┘                           │
│                  │                                   │
│            ┌─────┴─────┐                            │
│            │  容器网络   │                            │
│            └───────────┘                            │
└──────────────────────────────────────────────────────┘

11.7.2 集群架构

┌────────────────────┐
│   Load Balancer    │
│   (Nginx/HAProxy)  │
└─────────┬──────────┘
          │
    ┌─────┴─────┐
    │  公网      │
    └─────┬─────┘
          │
    ┌─────┴─────────────────────────────────┐
    │            Docker Swarm / K8s          │
    │                                        │
    │  ┌────────────┐  ┌────────────┐       │
    │  │  Origin    │  │  Origin    │       │
    │  │  (Primary) │  │  (Backup)  │       │
    │  └─────┬──────┘  └─────┬──────┘       │
    │        └────────┬──────┘              │
    │                 │                      │
    │    ┌────────────┼────────────┐        │
    │    ▼            ▼            ▼        │
    │  ┌──────┐  ┌──────┐  ┌──────┐       │
    │  │Edge 1│  │Edge 2│  │Edge 3│       │
    │  └──────┘  └──────┘  └──────┘       │
    │                                        │
    │  ┌──────────────────────────────┐    │
    │  │        Shared Storage         │    │
    │  │   (HLS/Recordings/Config)    │    │
    │  └──────────────────────────────┘    │
    └────────────────────────────────────────┘

11.8 常用运维命令

# 查看容器状态
docker-compose ps

# 查看实时日志
docker-compose logs -f srs

# 查看资源使用
docker stats srs-server

# 进入容器
docker exec -it srs-server bash

# 查看 SRS 版本
docker exec srs-server ./objs/srs -v

# 备份配置
tar czf srs-backup-$(date +%Y%m%d).tar.gz conf/ docker-compose.yml

# 清理 HLS 缓存
docker exec srs-server find /data/hls -name "*.ts" -mmin +60 -delete

# 查看网络连接
docker exec srs-server netstat -tlnp

注意事项

  1. 端口冲突:确保宿主机端口未被占用(1935, 8080, 1985)
  2. 磁盘空间:HLS 分片和录制文件会快速占用磁盘,需要定期清理
  3. ulimit 设置:高并发场景需在 docker-compose 中配置 ulimits
  4. GPU 转码:需要 GPU 转码时,需挂载设备(--device /dev/dri--gpus all
  5. 时区设置:容器内时间可能不正确,添加 -e TZ=Asia/Shanghai 或挂载 /etc/localtime
  6. 日志管理:配置日志轮转避免日志文件撑满磁盘

扩展阅读


上一章10 - 流中转与分发 下一章12 - 最佳实践 — RTMP 低延迟优化、安全与监控