20年モノのレンタルサーバをDockerに移行した話 ─ Claude Codeと2時間で乗り越えた地雷だらけの引っ越し
はじめに
今回対象にしたのは、キャンピングカー愛好者向けのSNSサイトだ。約20年前に OpenPNE 2.x(PHPベースのSNSフレームワーク)で構築され、ずっと同じレンタルサーバで動き続けてきた。
今回、そのサーバが老朽化したため、新しいVPSへの移行が必要になった。
旧サーバ環境:
- OS: CentOS 5(2007年リリース、2017年にEOL)
- Web: Apache + PHP 5.x
- DB: MySQL 5.5(MyISAMエンジン、データ量 約26GB)
- アプリ: OpenPNE 2.x(19GB)
新サーバ環境:
- OS: Ubuntu 24.04 LTS
- 構成: Docker Compose(nginx + Apache/CentOS5 + MySQL 5.5)
ポイントは「新サーバで同じCentOS 5 + Apache環境をDockerコンテナとして動かす」という方針だ。OpenPNEは非常に古いフレームワークのため、PHPバージョンやモジュール構成を完全に一致させるのが現実的だった。
この移行作業を Claude Code と一緒に進めた。その過程で何度も「詰まり」が発生したが、AIがリアルタイムで原因調査・解決策提示・コード修正までやってくれた体験を記録しておきたい。
Docker Compose構成の設計
Claude Codeに「CentOS 5ベースのDockerfileを作りたい」と伝えると、まずArchiveリポジトリへの対応が必要だと指摘してくれた。CentOS 5はすでにEOLで通常のyumリポジトリが使えないため、archive.kernel.org/centos-vault/ を使う設定を自動で組み込んでくれた。
FROM centos:5
# fastestmirrorプラグインを無効化
RUN sed -i 's/enabled=1/enabled=0/g' /etc/yum/pluginconf.d/fastestmirror.conf || true
# 既存repoを削除してCentOS Vaultに切り替え
RUN rm -f /etc/yum.repos.d/* && \
cat > /etc/yum.repos.d/CentOS-Vault.repo <<'EOF'
[base]
name=CentOS-5.11 - Base
baseurl=http://archive.kernel.org/centos-vault/5.11/os/$basearch/
enabled=1
gpgcheck=0
EOF
RUN yum clean all && \
yum -y install httpd php php-mysql php-gd php-mbstring php-xml php-cli && \
yum clean all
MySQLはそのまま mysql:5.5 イメージを使うが、Apple Silicon(ARM64)のMacで開発している場合は platform: linux/amd64 の指定が必要なことも自動で考慮してくれた。
docker-compose.yml、Dockerfile、ディレクトリ構成のひな形を5分以内に用意してもらった。手で調べていたら半日かかっていたと思う。
最初の壁:mysqldumpが26GBで詰まる
データ移行で最初に試みたのは定番の mysqldump だ。ところが、c_image テーブルには画像データをLONGBLOBカラムに格納している行が51,966件あり、合計データ量が26GBにもなっていた。
mysqldump: Error 2006: MySQL server has gone away
タイムアウト設定を変えても、パケットサイズを調整しても、何度やっても途中で切れる。
ここでClaude Codeに状況を伝えると、即座に代替案を提示してくれた。
「MyISAMエンジンのテーブルなので、生ファイル(.MYD / .MYI / .frm)を直接コピーする方法が確実です。」
具体的な手順も含めて提示してくれた:
# 旧サーバ側: MyISAMファイルをtarで固める
tar czf /tmp/mysql_files.tar.gz -C /var/lib/mysql rvnavi/
# rsyncで新サーバへ転送
rsync -avz --progress root@旧サーバIP:/tmp/mysql_files.tar.gz /tmp/
# Dockerボリュームに直接コピー
docker cp mysql_files/ mysite-db-1:/var/lib/mysql/mysite/
mysqldumpで詰まっていた時間が合計1時間以上あったが、この方法に切り替えたら一発で全テーブルが揃った。
パーミッション地獄との戦い
MySQLファイルをDockerコンテナに投入した後、コンテナが起動しない問題が発生した。
[ERROR] /usr/sbin/mysqld: Can't create/write to file '/var/lib/mysql/rvnavi/c_image.MYD'
Claude Codeはすぐに原因を特定してくれた。
「MySQLコンテナはUID 999のユーザーで動作しています。コピーしたファイルの所有者をDocker外から変更する必要があります。」
sudo chown -R 999:999 /var/lib/mysql/
同様のパーミッション問題は、OpenPNEのファイル転送時にも発生した。Dockerが作成したディレクトリがrootオーナーになっていてrsyncができなかった。
sudo chown -R pdadm:pdadm ~/mysite/OpenPNE_mysite/
こういった「なぜかうまくいかない」系の問題は、原因がわかれば一行で解決するのだが、わかるまでが大変だ。Claude Codeはエラーメッセージを見せるだけで即座に原因と解決コマンドを返してくれた。
config.phpの修正:ホスト名とパスの切り替え
OpenPNEの設定ファイル config.php は、旧サーバの環境に依存した設定が複数箇所に散らばっていた。Docker環境に合わせて変更が必要な箇所をClaude Codeが洗い出してくれた。
| 設定項目 | 旧サーバ | 新Docker環境 |
|---|---|---|
| DB接続ホスト | localhost or 127.0.0.1 | db(Composeサービス名) |
| セッション保存パス | /home/site01/OpenPNE_mysite/tmp | /var/www/OpenPNE_mysite/tmp |
| サイトURL | http://www.example.com/ | そのまま(変更不要) |
「全部変えて」と頼んだら、ファイルを読み込んでsedコマンドではなくEditツールで正確に修正してくれた。変更箇所の確認も一緒にやってくれるので安心感がある。
Apacheの設定:.htaccessを有効化
OpenPNEはURLルーティングに .htaccess の mod_rewrite を使っている。DockerのCentOS 5環境では AllowOverride None がデフォルトだったため、URLアクセスが全部404になっていた。
この問題もエラーログを見せると即座に原因を特定。Dockerfileに以下の修正を加えてくれた。
RUN sed -i '/<Directory "\/var\/www\/html">/,/<\/Directory>/ s/AllowOverride None/AllowOverride All/' /etc/httpd/conf/httpd.conf
sed の正規表現でブロック内の設定を書き換えるワンライナー。自分では考えつかなかった。
SSL/Let’s Encryptの準備
最後に、DNS切り替え後に即座にHTTPS化できるよう、nginx + certbotの構成を事前に準備してもらった。
Internet → nginx (443/80) → web (Apache/CentOS5)
↑
certbot (証明書管理)
Docker Composeにnginxとcertbotのサービスを追加し、2段階の設定ファイルを用意してもらった。
Phase 1(DNS切り替え直後・HTTP only):
server {
listen 80;
server_name www.example.com example.com;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
proxy_pass http://web:80;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Phase 2(証明書取得後・HTTPS):
server {
listen 80;
server_name www.example.com;
location / { return 301 https://www.example.com$request_uri; }
}
server {
listen 443 ssl;
server_name www.example.com example.com;
ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
location / {
proxy_pass http://web:80;
...
}
}
さらに、DNS切り替え当日に実行するだけでよい init-letsencrypt.sh スクリプトも自動生成してくれた。certbotの自動更新コンテナ起動、cronへの登録まで全部含まれている。
Claude Codeが効率化した作業の一覧
今回の移行で、Claude Codeが実際に行った作業をまとめると:
| 作業 | 従来の所要時間(推定) | Claude Code使用時 |
|---|---|---|
| Dockerfile作成(CentOS 5 Vault対応) | 2〜3時間 | 5分 |
| docker-compose.yml設計 | 1時間 | 5分 |
| mysqldump失敗の原因調査 | 1〜2時間 | 即座に特定 |
| MyISAMファイル直接コピー手順 | 調査1時間 | 即座に提示 |
| パーミッション問題の解決 | 30分〜1時間 | 即座に特定 |
| config.php修正箇所の洗い出し | 30分 | 5分 |
| AllowOverride設定のDockerfile修正 | 30分 | 即座 |
| nginx + certbot設定ファイル一式 | 2〜3時間 | 15分 |
| init-letsencrypt.sh作成 | 1時間 | 10分 |
合計で10〜15時間以上かかっていたと思われる作業を、実質2〜3時間で完了できた。
使い方のコツ
今回の作業を通じて感じたClaude Codeの効果的な使い方:
1. エラーメッセージをそのまま貼る
「うまくいかない」ではなく、ターミナルのエラーメッセージをそのままコピペする。原因特定の精度が全然違う。
2. 「変更していいです」「確認してから変更して」を使い分ける
SQLの最適化など、本番DBに影響する変更は「EXPLAINで確認してから変更して」と事前に指示した。一方、設定ファイルの修正は「変更していいです」とすることで作業がスムーズになった。
3. 全体文脈を把握させた状態を維持する
「このMacの作業ディレクトリにあるから見てください」と言うだけでファイルを読んで文脈を掴んでくれる。都度説明し直す必要がない。
おわりに
今回の移行は、独力でやっていたら丸2日以上かかっていたと思う。それが実質半日で完了できた。
特に印象的だったのは「地雷を踏む前に教えてくれる」ことだ。たとえばMySQLのファイルコピー時のUID問題、ARM64環境でのDockerビルド問題など、「自分で調べたらStack Overflowで1時間さまよう」系の問題をサクッと解決してくれた。
AIが「コードを書く」だけでなく、「システム全体を理解した上で何が問題かを診断する」という使い方が特に価値を発揮すると感じた。
DNS切り替えとHTTPS化は近日実施予定。そちらも記事にしたい。