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

Nextcloud 私有云部署教程 / 13 - Docker 部署

13 - Docker 部署

使用 Docker 和 Docker Compose 部署 Nextcloud,涵盖 AIO (All-in-One) 模式、自定义编排、反向代理与数据持久化。


13.1 Docker 部署方案对比

方案说明适用场景
AIO (All-in-One)官方一站式容器,包含所有组件快速部署、个人使用
Docker Compose 自定义手动编排各组件容器需要精细控制、生产环境
Docker + 外部数据库仅容器化 Nextcloud,数据库外置已有数据库基础设施

13.2 Nextcloud AIO 部署

AIO 是官方推荐的最简部署方式,一个命令启动所有组件。

AIO 包含的组件

组件说明
Nextcloud主应用
PostgreSQL数据库
Redis缓存
Collabora在线 Office
ClamAV病毒扫描
Fulltextsearch全文搜索
Talk视频通话 TURN 服务器
Imaginary图片处理
Backup自动备份

AIO 部署命令

# 创建数据目录
mkdir -p /data/nextcloud-aio

# 启动 AIO 主容器
docker run -d \
  --name nextcloud-aio-mastercontainer \
  --restart always \
  -p 80:80 \
  -p 8080:8080 \
  -p 8443:8443 \
  -v nextcloud_aio_mastercontainer:/mnt/docker-aio-config \
  -v /var/run/docker.sock:/var/run/docker.sock:ro \
  -e APACHE_PORT=443 \
  -e APACHE_IP_BINDING=0.0.0.0 \
  -e NEXTCLOUD_DATADIR=/data/nextcloud-aio \
  nextcloud/all-in-one:latest

AIO 初始设置

1. 浏览器访问: https://your-server-ip:8080
2. 获取初始密码(查看容器日志):
   docker logs nextcloud-aio-mastercontainer
3. 输入初始密码登录
4. 选择域名配置方式
5. 勾选需要的可选组件
6. 点击 "Start containers"

AIO 环境变量

变量说明默认值
APACHE_PORTApache 端口443
APACHE_IP_BINDING绑定 IP0.0.0.0
NEXTCLOUD_DATADIR数据目录内部卷
NEXTCLOUD_MEMORY_LIMIT内存限制512M
COLLABORA_ENABLED启用 Collaborafalse
CLAMAV_ENABLED启用 ClamAVfalse
FULLTEXTSEARCH_ENABLED启用全文搜索false
TALK_ENABLED启用 Talk TURNfalse

13.3 Docker Compose 自定义部署

完整 docker-compose.yml

# docker-compose.yml
version: '3.8'

services:
  # ======== Nextcloud 主应用 ========
  nextcloud:
    image: nextcloud:29-apache
    container_name: nextcloud
    restart: unless-stopped
    ports:
      - "8080:80"
    environment:
      - POSTGRES_HOST=db
      - POSTGRES_DB=nextcloud
      - POSTGRES_USER=ncuser
      - StrongPassword123!
      - REDIS_HOST=redis
      - NEXTCLOUD_ADMIN_USER=admin
      - NEXTCLOUD_ADMIN_PASSWORD=AdminPassword123!
      - NEXTCLOUD_TRUSTED_DOMAINS=cloud.example.com
      - OVERWRITEPROTOCOL=https
      - OVERWRITECLIURL=https://cloud.example.com
      - PHP_MEMORY_LIMIT=512M
      - PHP_UPLOAD_LIMIT=16G
    volumes:
      - nextcloud_html:/var/www/html
      - nextcloud_data:/var/www/html/data
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    networks:
      - nextcloud-net

  # ======== PostgreSQL 数据库 ========
  db:
    image: postgres:16-alpine
    container_name: nextcloud-db
    restart: unless-stopped
    environment:
      - POSTGRES_DB=nextcloud
      - POSTGRES_USER=ncuser
      - POSTGRES_PASSWORD=StrongPassword123!
    volumes:
      - nextcloud_db:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ncuser -d nextcloud"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - nextcloud-net

  # ======== Redis 缓存 ========
  redis:
    image: redis:7-alpine
    container_name: nextcloud-redis
    restart: unless-stopped
    command: redis-server --requirepass RedisPassword123!
    volumes:
      - nextcloud_redis:/data
    networks:
      - nextcloud-net

  # ======== Cron 定时任务 ========
  cron:
    image: nextcloud:29-apache
    container_name: nextcloud-cron
    restart: unless-stopped
    user: www-data
    volumes:
      - nextcloud_html:/var/www/html
      - nextcloud_data:/var/www/html/data
    entrypoint: /cron.sh
    depends_on:
      - nextcloud
    networks:
      - nextcloud-net

volumes:
  nextcloud_html:
  nextcloud_data:
  nextcloud_db:
  nextcloud_redis:

networks:
  nextcloud-net:
    driver: bridge

启动与管理

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

# 查看日志
docker compose logs -f nextcloud

# 停止服务
docker compose down

# 停止并删除数据(危险!)
docker compose down -v

# 更新镜像
docker compose pull
docker compose up -d

运行 occ 命令

# 执行 occ 命令
docker exec -u www-data nextcloud php occ status

# 安装应用
docker exec -u www-data nextcloud php occ app:install talk

# 查看配置
docker exec -u www-data nextcloud php occ config:list system

13.4 Nginx 反向代理配置

# /etc/nginx/sites-available/nextcloud

upstream nextcloud {
    server 127.0.0.1:8080;
}

server {
    listen 80;
    server_name cloud.example.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name cloud.example.com;

    # SSL 证书
    ssl_certificate     /etc/letsencrypt/live/cloud.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/cloud.example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
    ssl_prefer_server_ciphers on;

    # 安全头
    add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header Referrer-Policy "no-referrer" always;

    # 上传大小
    client_max_body_size 16G;
    client_body_timeout 300s;

    # 代理配置
    location / {
        proxy_pass http://nextcloud;
        proxy_http_version 1.1;
        proxy_set_header Host $http_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;
        proxy_set_header X-Forwarded-Host $http_host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_buffering off;
        proxy_request_buffering off;
    }

    # WebSocket 支持(Talk)
    location /ocs/v2.php/apps/spreed/ {
        proxy_pass http://nextcloud;
        proxy_http_version 1.1;
        proxy_set_header Host $http_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;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 86400s;
    }
}

启用并重启 Nginx:

sudo ln -sf /etc/nginx/sites-available/nextcloud /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

13.5 Docker 网络与安全

网络隔离

# docker-compose.yml
services:
  nextcloud:
    networks:
      - frontend     # 可访问外部
      - backend      # 仅内部通信

  db:
    networks:
      - backend      # 不暴露到外部

  redis:
    networks:
      - backend      # 不暴露到外部

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true   # 禁止外部访问

容器安全配置

services:
  nextcloud:
    security_opt:
      - no-new-privileges:true
    read_only: false
    tmpfs:
      - /tmp
      - /var/run

13.6 数据持久化

卷类型对比

类型说明持久性性能
Named VolumeDocker 管理的卷
Bind Mount挂载宿主机目录最好
tmpfs内存文件系统最快

推荐的卷配置

services:
  nextcloud:
    volumes:
      # Nextcloud 应用文件(Named Volume)
      - nextcloud_html:/var/www/html

      # 用户数据(Bind Mount,便于备份)
      - /data/nextcloud-data:/var/www/html/data

      # 自定义配置(Bind Mount,便于编辑)
      - ./config/custom.config.php:/var/www/html/config/custom.config.php:ro

  db:
    volumes:
      # 数据库数据(Bind Mount,便于备份)
      - /data/nextcloud-db:/var/lib/postgresql/data

  redis:
    volumes:
      - nextcloud_redis:/data

volumes:
  nextcloud_html:
  nextcloud_redis:

备份 Docker 卷

# 备份 Named Volume
docker run --rm \
  -v nextcloud_html:/source:ro \
  -v /backup:/backup \
  alpine tar czf /backup/nextcloud_html_$(date +%Y%m%d).tar.gz -C /source .

# 恢复
docker run --rm \
  -v nextcloud_html:/target \
  -v /backup:/backup:ro \
  alpine sh -c "rm -rf /target/* && tar xzf /backup/nextcloud_html_20260510.tar.gz -C /target"

13.7 SSL/TLS 配置

使用 Let’s Encrypt (Certbot)

# 安装 Certbot
sudo apt install -y certbot python3-certbot-nginx

# 获取证书
sudo certbot --nginx -d cloud.example.com

# 自动续期测试
sudo certbot renew --dry-run

使用 Traefik 自动 SSL

# docker-compose.yml (with Traefik)
services:
  traefik:
    image: traefik:v3.0
    container_name: traefik
    restart: unless-stopped
    command:
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
      - "--certificatesresolvers.letsencrypt.acme.email=admin@example.com"
      - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - traefik_certs:/letsencrypt

  nextcloud:
    image: nextcloud:29-apache
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.nextcloud.rule=Host(`cloud.example.com`)"
      - "traefik.http.routers.nextcloud.entrypoints=websecure"
      - "traefik.http.routers.nextcloud.tls.certresolver=letsencrypt"
      - "traefik.http.services.nextcloud.loadbalancer.server.port=80"
    # ...

13.8 Docker 环境变量参考

环境变量说明默认值
POSTGRES_HOST数据库主机db
POSTGRES_DB数据库名nextcloud
POSTGRES_USER数据库用户nextcloud
POSTGRES_PASSWORD数据库密码
MYSQL_HOSTMySQL 主机db
MYSQL_DATABASEMySQL 数据库名nextcloud
MYSQL_USERMySQL 用户nextcloud
MYSQL_PASSWORDMySQL 密码
REDIS_HOSTRedis 主机redis
NEXTCLOUD_ADMIN_USER管理员用户名admin
NEXTCLOUD_ADMIN_PASSWORD管理员密码
NEXTCLOUD_TRUSTED_DOMAINS可信域名
OVERWRITEPROTOCOL强制协议
OVERWRITECLIURLCLI URL
PHP_MEMORY_LIMITPHP 内存限制512M
PHP_UPLOAD_LIMIT上传大小限制16G
SMTP_HOSTSMTP 主机
SMTP_SECURESMTP 加密方式tls
SMTP_PORTSMTP 端口587
SMTP_NAMESMTP 用户名
SMTP_PASSWORDSMTP 密码
MAIL_FROM_ADDRESS发件人地址nextcloud
MAIL_DOMAIN发件人域名

13.9 Docker 更新策略

更新流程

# 1. 备份数据
docker exec -u www-data nextcloud php occ maintenance:mode --on
docker exec nextcloud-db pg_dump -U ncuser nextcloud | gzip > /backup/db-$(date +%Y%m%d).sql.gz

# 2. 拉取新镜像
docker compose pull

# 3. 停止旧容器(保留数据卷)
docker compose down

# 4. 启动新容器
docker compose up -d

# 5. 运行升级
docker exec -u www-data nextcloud php occ upgrade
docker exec -u www-data nextcloud php occ maintenance:mode --off

# 6. 验证
docker exec -u www-data nextcloud php occ status

自动更新脚本

#!/bin/bash
# nextcloud-docker-update.sh

set -euo pipefail

COMPOSE_DIR="/opt/nextcloud"
BACKUP_DIR="/backup/nextcloud"

echo "=== Nextcloud Docker Update ==="

# 备份
echo "1. Backing up..."
cd "$COMPOSE_DIR"
docker exec -u www-data nextcloud php occ maintenance:mode --on
docker compose exec -T db pg_dump -U ncuser nextcloud | gzip > "$BACKUP_DIR/db-$(date +%Y%m%d).sql.gz"

# 更新
echo "2. Pulling new images..."
docker compose pull

echo "3. Restarting containers..."
docker compose down
docker compose up -d

echo "4. Running upgrade..."
sleep 10
docker exec -u www-data nextcloud php occ upgrade
docker exec -u www-data nextcloud php occ maintenance:mode --off

echo "5. Verification..."
docker exec -u www-data nextcloud php occ status

echo "=== Update Complete ==="

13.10 注意事项

  1. 数据卷: 用户数据务必使用 Bind Mount 挂载到宿主机,不要依赖 Named Volume
  2. 备份: 更新前必须备份数据库和数据目录
  3. 网络隔离: 数据库和 Redis 不应暴露到外部网络
  4. 日志管理: 配置日志驱动和日志轮转,防止日志占满磁盘
  5. 资源限制: 为每个容器设置 CPU 和内存限制
  6. 健康检查: 为所有服务配置 healthcheck
services:
  nextcloud:
    deploy:
      resources:
        limits:
          cpus: '2.0'
          memory: 2G
        reservations:
          cpus: '0.5'
          memory: 512M

13.11 扩展阅读


上一章: 12 - 备份恢复 下一章: 14 - 故障排查 — 常见问题诊断与解决方案。