目次
はじめに
QNAPのContainerStationでDockerを使って複数のWordPressサイトを運用していると、最初は1つのdocker-compose.ymlにまとめた「統合構成」で始めることが多いです。
しかしサイト数が増えたり、管理者が異なるサイトを運用するようになると、1つのコンテナが止まると全サイトに影響するという問題が出てきます。
この記事では、統合構成からサイトごとに独立した分離構成への移行手順を解説します。
適宜自分の構成、サイト名など書き換えて使ってください。
統合構成と分離構成の違い
統合構成(移行前)
site_folder/
├── wordpress_site1
├── wordpress_site2
├── mariadb_site1
├── mariadb_site2
├── nginx_reverse_proxy ← 全サイト共通
├── phpmyadmin
└── cloudflared ← 全サイト共通
問題点:
- 1サイトのコンテナ障害が全サイトに影響する
- サイトが増えるとdocker-compose.ymlが肥大化する
- 管理者が異なるサイトを同一ファイルで管理しにくい
分離構成(移行後)
shared/ ← 新規作成
├── nginx_reverse_proxy ← 全サイト共通
├── cloudflared ← 全サイト共通
└── phpmyadmin
site1/ ← WordPressとDBのみ
├── wordpress_site1
└── mariadb_site1
site2/ ← WordPressとDBのみ
├── wordpress_site2
└── mariadb_site2
メリット:
- 1サイトを停止しても他サイトに影響しない
- サイトごとにdocker-compose.ymlが独立して管理しやすい
- サイトの追加・削除が簡単
この記事でわかること
- 共有ネットワークの作成方法
- NginxとCloudflaredをsharedフォルダに分離する方法
- 各サイトのdocker-compose.ymlをWordPress+DBのみに縮小する方法
- 移行時に起きやすいトラブルと解決方法
環境
- QNAP NAS(ContainerStation インストール済み)
- SSH接続ソフト:TeraTerm
- 運用中サイト:2サイト(your-site1.com、your-site2.com)
- 共通コンテナ:Nginx、Cloudflare Tunnel、phpMyAdmin
事前準備
バックアップを取る
必ずバックアップを取ってから作業してください。WordPressのファイルとデータベースの両方が必要です。
SSHを有効にする
SSHの有効化手順はこちら [QNAPのCloudflaredをSSHでアップデートする方法]
Step 1:共有ネットワークを作成する
全コンテナが通信できる共有ネットワークを作成します。これはサイトに影響しない安全な作業です。
docker network create shared_proxy
実行結果:
04886ddca261d315fbcaxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Step 2:sharedフォルダを作成する
NginxとCloudflaredを管理するsharedフォルダを作成します。
mkdir -p /share/CACHEDEV4_DATA/docker/shared/nginx/conf.d
mkdir -p /share/CACHEDEV4_DATA/docker/shared/cloudflared
mkdir -p /share/CACHEDEV4_DATA/docker/shared/certs

Step 3:設定ファイルをコピーする
既存の設定ファイルをsharedフォルダにコピーします。
cp /share/CACHEDEV4_DATA/docker/your_app/nginx/nginx.conf \
/share/CACHEDEV4_DATA/docker/shared/nginx/nginx.conf
cp /share/CACHEDEV4_DATA/docker/your_app/nginx/conf.d/*.conf \
/share/CACHEDEV4_DATA/docker/shared/nginx/conf.d/
cp /share/CACHEDEV4_DATA/docker/your_app/cloudflared/config.yml \
/share/CACHEDEV4_DATA/docker/shared/cloudflared/config.yml
cp /share/CACHEDEV4_DATA/docker/your_app/cloudflared/credentials.json \
/share/CACHEDEV4_DATA/docker/shared/cloudflared/credentials.json
cp /share/CACHEDEV4_DATA/docker/your_app/certs/* \
/share/CACHEDEV4_DATA/docker/shared/certs/

コピーされたか確認します:
ls /share/CACHEDEV4_DATA/docker/shared/nginx/conf.d/
ls /share/CACHEDEV4_DATA/docker/shared/cloudflared/
ls /share/CACHEDEV4_DATA/docker/shared/certs/

Step 4:shared用docker-compose.ymlを作成する
vimやnanoで作成しても構いません。
cat > /share/CACHEDEV4_DATA/docker/shared/docker-compose.yml << 'EOF'
services:
nginx_reverse_proxy:
container_name: nginx_reverse_proxy_shared
image: nginx:latest
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./certs:/etc/certs:ro
- ./nginx/conf.d:/etc/nginx/conf.d:ro
networks:
- shared_proxy
cloudflared:
image: cloudflare/cloudflared:latest
container_name: cloudflared_shared
restart: unless-stopped
command: tunnel --config /etc/cloudflared/config.yml run your-tunnel-name
volumes:
- ./cloudflared/config.yml:/etc/cloudflared/config.yml:ro
- ./cloudflared/credentials.json:/etc/cloudflared/credentials.json:ro
networks:
- shared_proxy
phpmyadmin:
image: phpmyadmin:latest
container_name: phpmyadmin
restart: always
ports:
- "8081:80"
environment:
PMA_HOST: mariadb_site1
networks:
- shared_proxy
networks:
shared_proxy:
external: true
EOF

⚠️ 重要:config.ymlの
commandにも--configオプションを追加するtunnel run your-tunnel-nameだけではconfig.ymlが読み込まれません。 必ずtunnel --config /etc/cloudflared/config.yml run your-tunnel-nameと記述してください。
Step 5:既存ファイルをバックアップする
既存のdocker-compose.ymlを書き換える前にバックアップを取ります。
cp /share/CACHEDEV4_DATA/docker/your_app/docker-compose.yml \
/share/CACHEDEV4_DATA/docker/your_app/docker-compose.yml.bak

Step 6:site1のdocker-compose.ymlをWordPress+DBのみに縮小する
cat > /share/CACHEDEV4_DATA/docker/site1/docker-compose.yml << 'EOF'
services:
mariadb_site1:
image: mariadb:10.11
container_name: mariadb_site1
restart: always
environment:
MYSQL_ROOT_PASSWORD: your_root_password
MYSQL_DATABASE: your_database
MYSQL_USER: your_user
MYSQL_PASSWORD: your_password
volumes:
- ./db_data:/var/lib/mysql
networks:
- shared_proxy
wordpress_site1:
image: wordpress:php8.2-apache
container_name: wordpress_site1
restart: unless-stopped
environment:
WORDPRESS_DB_HOST: mariadb_site1
WORDPRESS_DB_USER: your_user
WORDPRESS_DB_PASSWORD: your_password
WORDPRESS_DB_NAME: your_database
volumes:
- ./html:/var/www/html
networks:
- shared_proxy
networks:
shared_proxy:
external: true
EOF

site2も同様に作成します。
Step 7:切り替え作業(ダウンタイムあり)
ここからは数分のダウンタイムが発生します。
旧コンテナを停止
cd /share/CACHEDEV4_DATA/docker/your_app
docker compose down
新コンテナを起動(site1)
cd /share/CACHEDEV4_DATA/docker/site1
docker compose up -d

新コンテナを起動(site2)
旧コンテナが残っている場合はエラーが出ることがあります:
Error response from daemon: Conflict. The container name "/mariadb_site2" is already in use
その場合は旧コンテナを削除してから起動します:
docker rm -f mariadb_site2 wordpress_site2
docker compose up -d
sharedを起動
cd /share/CACHEDEV4_DATA/docker/shared
docker compose up -d
ポート80が既存のNginxに使われている場合はエラーが出ます:
Bind for 0.0.0.0:80 failed: port is already allocated
旧Nginxを削除してから再起動します:
docker rm -f nginx_reverse_proxy
docker compose up -d
Step 8:動作確認
全コンテナが起動しているか確認します:
docker ps --format "table {{.Names}}\t{{.Status}}"

各サイトにアクセスして表示を確認してください。
トラブルシューティング
502 Bad Gateway が出る
原因①:config.ymlのコンテナ名が古いまま
config.ymlのserviceに旧コンテナ名が残っている場合に発生します。
# 修正前(古い名前)
service: https://nginx_reverse_proxy:443
# 修正後(新しい名前)
service: https://nginx_reverse_proxy_shared:443
修正後にCloudflaredを再起動します:
cd /share/CACHEDEV4_DATA/docker/shared
docker compose up -d --force-recreate cloudflared
原因②:旧cloudflaredコンテナが生き残っている
旧コンテナが残っているとリクエストを横取りされます。
docker ps | grep cloudflared
旧コンテナが残っている場合は削除します:
docker stop cloudflared
docker rm cloudflared
--remove-orphansでphpmyadminが消えた
docker compose up -d --remove-orphansを実行すると、新しいdocker-compose.ymlに含まれていないコンテナが削除されます。
phpmyadminをshared/docker-compose.ymlに追加して再起動することで復旧できます。
起動後に「その他」状態から変わらない
ブラウザをF5で更新すると「実行中」に変わります。
まとめ
今回実施したコマンドをまとめます:
# 1. 共有ネットワーク作成
docker network create shared_proxy
# 2. フォルダ作成
mkdir -p /share/CACHEDEV4_DATA/docker/shared/nginx/conf.d
mkdir -p /share/CACHEDEV4_DATA/docker/shared/cloudflared
mkdir -p /share/CACHEDEV4_DATA/docker/shared/certs
# 3. 設定ファイルコピー
cp -r /share/CACHEDEV4_DATA/docker/your_app/nginx/nginx.conf \
/share/CACHEDEV4_DATA/docker/shared/nginx/
cp /share/CACHEDEV4_DATA/docker/your_app/nginx/conf.d/*.conf \
/share/CACHEDEV4_DATA/docker/shared/nginx/conf.d/
cp /share/CACHEDEV4_DATA/docker/your_app/cloudflared/* \
/share/CACHEDEV4_DATA/docker/shared/cloudflared/
cp /share/CACHEDEV4_DATA/docker/your_app/certs/* \
/share/CACHEDEV4_DATA/docker/shared/certs/
# 4. 旧コンテナ停止
cd /share/CACHEDEV4_DATA/docker/your_app
docker compose down
# 5. 新コンテナ起動
cd /share/CACHEDEV4_DATA/docker/site1 && docker compose up -d
cd /share/CACHEDEV4_DATA/docker/site2 && docker compose up -d
cd /share/CACHEDEV4_DATA/docker/shared && docker compose up -d
# 6. 確認
docker ps --format "table {{.Names}}\t{{.Status}}"
関連記事
- QNAPのCloudflaredをSSHでアップデートする方法【Docker Compose対応】
- QNAPのContainerStationでDockerイメージを管理する方法【確認・プル・削除】
- docker-compose.ymlの
version属性の警告を修正する方法 - NginxリバースプロキシをQNAPのDockerで設定する完全ガイド
