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_PORT | Apache 端口 | 443 |
| APACHE_IP_BINDING | 绑定 IP | 0.0.0.0 |
| NEXTCLOUD_DATADIR | 数据目录 | 内部卷 |
| NEXTCLOUD_MEMORY_LIMIT | 内存限制 | 512M |
| COLLABORA_ENABLED | 启用 Collabora | false |
| CLAMAV_ENABLED | 启用 ClamAV | false |
| FULLTEXTSEARCH_ENABLED | 启用全文搜索 | false |
| TALK_ENABLED | 启用 Talk TURN | false |
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 Volume | Docker 管理的卷 | ✅ | 好 |
| 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_HOST | MySQL 主机 | db |
| MYSQL_DATABASE | MySQL 数据库名 | nextcloud |
| MYSQL_USER | MySQL 用户 | nextcloud |
| MYSQL_PASSWORD | MySQL 密码 | — |
| REDIS_HOST | Redis 主机 | redis |
| NEXTCLOUD_ADMIN_USER | 管理员用户名 | admin |
| NEXTCLOUD_ADMIN_PASSWORD | 管理员密码 | — |
| NEXTCLOUD_TRUSTED_DOMAINS | 可信域名 | — |
| OVERWRITEPROTOCOL | 强制协议 | — |
| OVERWRITECLIURL | CLI URL | — |
| PHP_MEMORY_LIMIT | PHP 内存限制 | 512M |
| PHP_UPLOAD_LIMIT | 上传大小限制 | 16G |
| SMTP_HOST | SMTP 主机 | — |
| SMTP_SECURE | SMTP 加密方式 | tls |
| SMTP_PORT | SMTP 端口 | 587 |
| SMTP_NAME | SMTP 用户名 | — |
| SMTP_PASSWORD | SMTP 密码 | — |
| 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 注意事项
- 数据卷: 用户数据务必使用 Bind Mount 挂载到宿主机,不要依赖 Named Volume
- 备份: 更新前必须备份数据库和数据目录
- 网络隔离: 数据库和 Redis 不应暴露到外部网络
- 日志管理: 配置日志驱动和日志轮转,防止日志占满磁盘
- 资源限制: 为每个容器设置 CPU 和内存限制
- 健康检查: 为所有服务配置 healthcheck
services:
nextcloud:
deploy:
resources:
limits:
cpus: '2.0'
memory: 2G
reservations:
cpus: '0.5'
memory: 512M
13.11 扩展阅读
上一章: 12 - 备份恢复
下一章: 14 - 故障排查 — 常见问题诊断与解决方案。