NextcloudをDocker上で動かす
更新日:2026/10/6
-
前提
- Cloudflare経由でhttpsでアクセス かつ ローカルではhttpでアクセス可能とする
- Nextcloud、mariadb、redisのDockerイメージのバージョンは指定する
-
docker-compose.ymlの作成
networks: nextcloud-network: driver: bridge services: # ----------------------------------------------------------------------- # データベース(MariaDB 11.4) # ----------------------------------------------------------------------- db: image: mariadb:11.4 container_name: nextcloud-db restart: always command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW --innodb-file-per-table=1 --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci volumes: - ./mariadb_data:/var/lib/mysql environment: - MYSQL_ROOT_PASSWORD=xxxxx - MYSQL_PASSWORD=yyyyy - MYSQL_DATABASE=nextcloud - MYSQL_USER=nextcloud networks: - nextcloud-network labels: jp.hatenablog.owner.inventory.role: "database" jp.hatenablog.owner.inventory.env: "production" jp.hatenablog.owner.inventory.owner: "kazukifu" jp.hatenablog.owner.inventory.port.container: "3306" jp.hatenablog.owner.inventory.port.protocol: "tcp" jp.hatenablog.owner.inventory.description: | Nextcloud用 MariaDB 11.4。 READ-COMMITTED + ROW binlog + utf8mb4 の Nextcloud 推奨構成。 # ----------------------------------------------------------------------- # Redis キャッシュ # ----------------------------------------------------------------------- redis: image: redis:8.4.0-alpine container_name: nextcloud-redis restart: always networks: - nextcloud-network labels: jp.hatenablog.owner.inventory.role: "cache" jp.hatenablog.owner.inventory.env: "production" jp.hatenablog.owner.inventory.owner: "kazukifu" jp.hatenablog.owner.inventory.port.container: "6379" jp.hatenablog.owner.inventory.port.protocol: "tcp" jp.hatenablog.owner.inventory.description: | Nextcloud用 Redis 8.4.0(alpine)。 # ----------------------------------------------------------------------- # Nextcloud 本体 # ----------------------------------------------------------------------- app: image: nextcloud:35 container_name: nextcloud-app restart: always ports: # Cloudflare Tunnel(別コンテナ/別ホスト)等からのアクセス用に 11000 番ポートを開放 - "11000:80" volumes: - ./nextcloud_data:/var/www/html - /mnt/WD-8TB/info-shelf:/WD-8TB-info-shelf # External Storageとしてマウント environment: - MYSQL_HOST=db - MYSQL_PASSWORD=yyyyy - MYSQL_DATABASE=nextcloud - MYSQL_USER=nextcloud - REDIS_HOST=redis # 別 Compose やホスト経由でプロキシされる場合の信頼IP範囲を設定(Dockerネットワーク帯域をカバー) - TRUSTED_PROXIES=172.16.0.0/12 192.168.0.0/16 10.0.0.0/8 depends_on: - db - redis networks: - nextcloud-network labels: jp.hatenablog.owner.inventory.role: "nextcloud-app" jp.hatenablog.owner.inventory.env: "production" jp.hatenablog.owner.inventory.owner: "kazukifu" jp.hatenablog.owner.inventory.port.host: "11000" jp.hatenablog.owner.inventory.port.container: "80" jp.hatenablog.owner.inventory.port.protocol: "tcp" -
起動と動作確認
docker compose up -d -
ローカル直接アクセスとCloudflare経由アクセスの両立の仕組み
- TRUSTED_PROXIES が正しく機能します。Cloudflare 経由でアクセスした場合 (https://your-domain.com)
- Cloudflare Tunnel が Nextcloud へリクエストを転送する際、暗号化通信であることを示す X-Forwarded-Proto: https というヘッダーを付与します
- Nextcloud は TRUSTED_PROXIES(プライベートIP帯)からの通信を信頼するため、このヘッダーを見て自動的に HTTPS 通信として認識し、生成するリンクも https:// になります
- ローカル IP でアクセスした場合
- リバースプロキシを通さない直接の HTTP アクセスとなるため、Nextcloud は普通に HTTP 通信として処理します。前回のような SSL エラー(リダイレクトループ)は発生しません
- Docker コンテナへの通信は、Linux 内部では「転送(FORWARD)」パケットとして処理されます。UFW の設定ファイル(/etc/default/ufw)にある転送ポリシーが標準の DROP になっていると、Docker が追加したルーティングルールよりも UFW の FORWARD ブロックが優先されて通信が切断されます。
sudo ufw allow 11000によりポートを開けることで FORWARD 通信が許可されるようになります
- TRUSTED_PROXIES が正しく機能します。Cloudflare 経由でアクセスした場合 (https://your-domain.com)
-
両立させる際の実践チェックポイント
-
両方のルートからアクセスする場合、Nextcloud の「信頼できるドメイン (trusted_domains)」に両方のホスト名を登録しておく必要があります。もし Cloudflare 経由でアクセスした際に 「信頼できないドメインからのアクセスです (Access through untrusted domain)」 という画面が出た場合は、以下のいずれかの方法でドメインを追加してください。
- コンテナからコマンドで追加する
docker exec -u www-data nextcloud-app php occ config:system:set trusted_domains 2 --value="nextcloud.yourdomain.com"
-