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.1db(Composeサービス名)
セッション保存パス/home/site01/OpenPNE_mysite/tmp/var/www/OpenPNE_mysite/tmp
サイトURLhttp://www.example.com/そのまま(変更不要)

「全部変えて」と頼んだら、ファイルを読み込んでsedコマンドではなくEditツールで正確に修正してくれた。変更箇所の確認も一緒にやってくれるので安心感がある。


Apacheの設定:.htaccessを有効化

OpenPNEはURLルーティングに .htaccessmod_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化は近日実施予定。そちらも記事にしたい。