独立站のコンテナ化:Docker設定、イメージ最適化、オーケストレーションとリソース制限

独立站でDockerを使う目的はK8s導入ではなく、「このサーバーで動く」を「どのマシンでも動く」に変えることです。合格基準は、本番イメージを200MB以内に収める、マルチステージビルドを使う、各コンテナにCPUとメモリ制限を明示する、単一VPSならdocker composeで十分です。直感に反するのは、イメージ肥大化の原因がほぼ常にコード量ではなく、ビルドツール、npmキャッシュ、ソースコードを実行イメージに残してしまうことです。この3つでイメージは200MBから1.5GBまで膨らみます。

独立站Docker镜像:从1.2GB臃肿镜像到180MB生产镜像Independent-site Docker: from 1.2GB bloated image to 180MB prod 反直觉:镜像大不是因为代码多,而是因为把构建工具和源码全塞进了运行层Counter-intuitive: bloat comes from build tools shipped into runtime 错误做法:单阶段构建Wrong: single-stage build 正确做法:多阶段构建Right: multi-stage build Ubuntu基础镜像 500MBUbuntu base 500MB Node/PHP 全量 200MBFull runtime 200MB 源码 + node_modules 300MBSource + node_modules 300MB 编译工具链 200MBBuild toolchain 200MB alpine 基础 5MBalpine base 5MB 运行时 40MBRuntime 40MB 系统库 20MBSystem libs 20MB 应用代码 30MBApp code 30MB 静态资源 80MBAssets 80MB PHP扩展/依赖 50MBPHP ext 50MB 合计 ≈ 225MBTotal ≈ 225MB 资源限制:CPU 1至2核、内存512MB至1GB是独立站容器的甜蜜点;不设限制会把宿主机内存吃光Limits: 1-2 CPU, 512MB-1GB RAM; without limits host starves 编排选择:单台VPS用docker compose即可,3台以上再考虑Swarm;K8s对独立站是过度设计Compose for 1 box, Swarm for 3+, K8s overkill
シングルステージとマルチステージビルドのイメージサイズ比較

独立站のコンテナ化:Docker設定、イメージ最適化、オーケストレーションとリソース制限

結論から言うと:独立站でDockerを使う目的はK8s導入ではなく、「このサーバーで動く」を「どのマシンでも動く」に変えることです。合格基準は、本番イメージを200MB以内に収める、マルチステージビルドを使う、各コンテナにCPUとメモリ制限を明示する、単一VPSならdocker composeで十分です。直感に反するのは、イメージ肥大化の原因がほぼ常にコード量ではなく、ビルドツール、npmキャッシュ、ソースコードを実行イメージに残してしまうことです。この3つでイメージは200MBから1.5GBまで膨らみます。

一、独立站はなぜサーバーに直接インストールせずコンテナ化するのか

VPSにPHP、Nginx、MySQLを直接インストールしても動きますが、半年後に3つの問題が噴出します。第一に、新しい担当者が環境構築に2日かかる。第二に、Alibaba CloudからTencent Cloudへ移行する際に依存関係を再インストールする。第三に、セキュリティパッチ適用時に本番バージョンを触れない。Dockerはアプリと依存関係を不変のイメージとしてパッケージ化し、この3つを解決します。

判断基準が一つあります。デプロイ手順書に「まずapt install php8.3-fpm、次にこの12個の拡張をインストール、その後php.iniの8項目を変更」と書いてあれば、コンテナ化が必要です。この12個の拡張と8項目の設定をDockerfileに書けば、以後どのマシンでもdocker runを一度実行するだけで再現できます。CDNと静的リソースの連携はCDNグローバル高速化。

実装方法 環境再現コスト サーバー移行 ロールバック速度 適した規模
VPSに直接インストール 2人日 依存関係を再インストール スナップショットで30分 プロトタイプ期
Shellスクリプトで環境構築 0.5人日 スクリプト実行、差異は残る 15分 単一サイト運用1年
Dockerイメージ 5分 イメージを取得すれば即起動 イメージタグを切り替え、3分 本番サイト、マルチ環境
Docker Composeオーケストレーション 5分 yamlをコピーすれば即起動 ワンクリックロールバック アプリ+データベース+キュー

二、Dockerfileをどう書けば肥大化しないか

独立站で最も多いDockerfileの誤りはシングルステージビルドです。FROM ubuntuでPHPをインストール、Composerをインストール、composer install、ソースコードをCOPY、ポートを公開。この方法で作ったイメージは通常1GB以上になります。ビルドツール、npmキャッシュ、.gitディレクトリが含まれるからです。正しい方法はマルチステージビルドです。第一段階でbuilderイメージを使いフロントエンドをビルドしcomposer依存関係をインストール、第二段階でビルド成果物とランタイムだけをalpineイメージにコピーします。

いくつかの鉄則:ベースイメージはubuntuではなくalpineを選ぶ。.dockerignoreではnode_modules、.git、.env、アップロードディレクトリを必ず除外する。npm/composer install時は–no-devと–no-cacheを付ける。実行時は非rootユーザーを使う。イメージサイズの目標:純粋なPHP/Nodeアプリは200MB以内、静的アセットを含む場合は400MB以内。イメージスキャンとセキュリティベースラインは次を参照サイトのバックアップと復元演習。

ある実例:とあるチームがリリースから半年後、イメージが1.4GBになっていることに気づき、docker historyでレイヤーごとに調べたところ、composer installに–no-devを付け忘れてphpunitや開発依存を大量に本番イメージへ含めてしまっていた。さらにCOPY . .で.gitディレクトリまでコピーされていた。マルチステージビルドに変更し、builderステージで依存をインストール、実行ステージではvendorディレクトリとpublicディレクトリだけをコピーするようにしたところ、イメージは180MBまで削減され、デプロイ時間も3分から40秒に短縮された。

階層 よくある誤った書き方 最適化の書き方 サイズ削減
ベースイメージ FROM ubuntu:22.04 FROM php:8.3-fpm-alpine 約400MB
システム依存 apt-get install build-essential マルチステージビルド、builderステージでインストール 約200MB
PHP依存 composer install composer install –no-dev –no-cache 約80MB
フロントエンド依存 COPY . . builderステージでnpm ci && npm run build 約300MB
ソースディレクトリ COPY . /var/www COPY –from=builder /app/public ./public 約100MB
実行ユーザー rootで直接実行 RUN adduser -D app セキュリティ上の利点、サイズ増なし

三、docker composeで独立サイトをどう構成するか

独立サイトの典型的な構成は4つのコンテナ:Nginxリバースプロキシ、PHP-FPMまたはNodeアプリ、MySQL/PostgreSQL、Redis。1つのdocker-compose.ymlでこの4サービスをつなぎ、データボリュームをマウントしてMySQLデータを永続化し、ポートはNginxの80と443だけを公開、他のサービスは内部ネットワーク経由にする。MySQLのポートをインターネットに公開してはいけない。

実行可能な設定の抜粋:Nginxはphpにdepends_on、phpはdbとredisにdepends_on。ヘルスチェックはコマンドcurl -fsS http://localhost/healthを30秒ごとに実行。再起動ポリシーは一律unless-stopped。バックアップ戦略はMySQLデータボリュームを定期的にホストのバックアップディレクトリへマウントし、rsyncで遠隔地へ同期する。マルチコンテナ構成の監視については次を参照サイト監視とアラート。

シナリオ例:4コア8GのAlibaba Cloud軽量アプリケーションサーバー1台で、WordPressとMySQLとRedisの3コンテナを動かす。MySQLコンテナはnamed volumeをマウントしてデータを保存し、Nginxは80と443をホストにマッピング、WordPressコンテナはポートを公開せず内部ネットワークのみを通す。ホストを再起動してもdocker compose up -dで3サービスが自動的に起動し、その間ログインして手動で何かを起動する必要はない。これがcomposeの最も素朴な価値だ。

サービス ベースイメージ CPU制限 メモリ制限 永続化の有無
nginx nginx:1.27-alpine 0.5コア 128MB 不要
php-fpm / node php:8.3-fpm-alpine 1〜2コア 512MB至1GB なし(アップロードディレクトリはボリュームをマウント)
mysql mysql:8.4 1〜2コア 1至2GB あり(dataディレクトリ)
redis redis:7-alpine 0.5コア 256MB あり(AOF永続化)
cron/キュー アプリと同じイメージ 0.5コア 256MB 不要

四、リソース制限:制限のないコンテナはマシン全体を巻き込んで落とす

Dockerを手軽に使いたいあまり、起動時に–cpusや–memoryを書かない人が多い。その結果、PHP-FPMが一度遅いクエリに当たるとメモリが512MBから4GBまで膨らみ、同じマシンのMySQLをOOMに追い込む。すべてのコンテナでリソース上限を明示する。これは必須だ。

独立サイトのリソース割り当ての目安:アプリコンテナはCPU1〜2コア、メモリ512MB〜1GB。MySQLコンテナはデータ量に応じて、10GB以下なら1コア1GBで十分。NginxとRedisはそれぞれ0.5コア、128〜256MB。ホストマシンにはDocker daemonとシステム用に20%を残す。判断基準は一つ:ホストの総メモリの80%をコンテナに、20%をシステムに割り当て、この比率を超えたらマシンを増やす。CPUは平均ではなくピークで割り当てる。独立サイトのトラフィックは平日のピークと夜間の谷があるため、平均で見積もるとピーク時に待ち行列ができる。

独立サイトの規模 推奨構成 CPU割り当て メモリ割り当て 月間訪問数の目安
立ち上げ検証期 2コア2GB VPS 1台 アプリ1コア+DB 0.5コア アプリ512MB+DB 1GB 5万未満
安定成長期 4コア8GB VPS 1台 アプリ2コア+DB 1.5コア アプリ2GB+DB 4GB 5万〜30万
多言語のピーク期 4コア8GB 2台 アプリ各2コア 各2GB、DBは別途4GB 30万〜100万
独立記念日のピーク アプリを3〜4台に横展開 各2コア 各2GB セール・展示会のトラフィック

五、いつSwarmやK8sに移行すべきか

直感に反する結論だが、独立サイトの90%の場面でK8sは不要だ。docker composeは1台のVPSで4〜8個のコンテナを動かせ、日次訪問10万以内のB2Bサイトなら十分支えられる。次の3つの兆候のどれかが出たときだけ、Swarmへの移行を検討する:アプリを2台以上のVPSにまたがって動かす必要がある、ブルーグリーン配備で自動的にトラフィックを切り替えたい、ヘルスチェックで落ちたコンテナを自動再起動したい。

判断基準は簡単だ。docker-compose.ymlのサービスが30を超える、あるいは5人以上のチームが同時にこの環境を保守するなら、オーケストレーションを検討する。そうでなければcomposeが最適解であり、K8sの保守に費やす労力はコンテンツとSEOに回したほうがリターンが大きい。

K8sの壁は、etcd、ネットワークプラグイン、Ingressコントローラを専任で保守する人が必要になり、トラブル対応だけで週に1日を奪われることだ。小規模チームなら、その時間をコンテンツとSEOに回したほうがリターンは大きい。将来本当にマルチインスタンス配備が必要になったら、ロードバランシングの設計はこちらを参照。ロードバランシングとマルチインスタンス配備。

オーケストレーションツール 学習コスト 維持コスト 対象ノード数 選ぶ条件
docker compose 1〜2日 極めて低い 1台 独立サイトの90%はこれ
docker swarm 3〜5日 低 2〜10台 マシンをまたぐ編成とローリング更新が必要
K8s 2〜4週間 高 5台以上 複数チーム、複数サービス、自動スケーリング
クラウド事業者のマネージドK8s 1〜2週間 中 10台以上 専任のDevOpsがいる

FAQ よくある質問

独立サイトでDockerを使うと、サーバーに直接入れるより遅くなるのか?
コンテナ自体の性能劣化は2%以内で、ほとんど体感できません。本当に遅くなる原因は、MySQLまでコンテナに入れてしまうこと、またはデータボリュームを設定せずoverlay層に書き込んでいることです。正しいやり方は、MySQLとRedisのコンテナはnamed volumeで永続化し、アプリはステートレスにすること。こうすればサーバーに直接インストールするよりクリーンで、性能も同等です。
イメージのサイズはどのくらいが適正ですか?
PHPやNodeの実行イメージだけなら200MB以内、フロントエンドのビルド成果物を含めても400MB以内です。1GBを超えたら、ビルドツールやソースコードまで入れていると判断していいでしょう。docker imagesでサイズを確認し、docker historyでどの層が一番大きいかを見ます。よくある原因は、マルチステージビルドでnode_modulesを削除していない、またはapt-get installの後にapt-get cleanをしていないことです。
docker composeで日間10万アクセスに耐えられますか?
4コア8GBのVPS1台でcomposeを動かすなら、日間10万アクセス以内なら問題ありません。ボトルネックは通常NginxではなくMySQLです。日間20万アクセス以上になったら、まずMySQLを別マシンに切り出し、アプリはcomposeで2台のVPSに載せれば十分です。本当に日間50万アクセスになったらロードバランサーとマルチインスタンスを検討しましょう。存在しないトラフィックのために最初から複雑さを買う必要はありません。
コンテナ内のログとアップロードファイルはどう扱いますか?
ログはコンテナ層に書かず、ホストのディレクトリにマウントするか、そのままstdoutに出力してdocker json-fileで収集させます。アップロードファイル(問い合わせの添付、顧客がアップロードしたPDF)は必ずホストのvolumeにマウントしてください。そうしないとコンテナ再作成時にファイルがすべて消えます。uploadsディレクトリは独立したボリュームにマウントし、定期的にrsyncでオブジェクトストレージへ転送することをおすすめします。データベースのdumpとバックアップの完全な手順はこちらサイトのバックアップと復元演習。
いつK8sを使い、いつcomposeを使い続けるべきですか?
次の3つのシグナルのうち2つが出たらK8sを検討します。アプリのインスタンスが3台以上のマシンにまたがる必要がある、自動スケーリングの明確な要件がある、チームにK8sの日常的な保守とトラブルシューティングができる人がいる。それまではcomposeで十分です。K8sの隠れたコストは、etcd、CNI、Ingress、証明書管理といったコンポーネントのトラブルシューティングに毎週少なくとも1人1日分の時間を取られることです。
alpineイメージは依存関係が足りず動かないことはありますか?
あります。最もよくある落とし穴は、PHP拡張のコンパイル時にbuild-baseが必要で、実行時には不要なことです。マルチステージビルドで解決できます。builderステージでbuild-baseやlibpng-devといったビルド依存をインストールし、実行ステージではlibpngのような実行ライブラリだけをインストールします。面倒なら、php:8.3-fpm-alpineの公式イメージをそのまま使えば、よく使う拡張はすでにインストール済みです。undefined symbolが出たら、足りないものをその都度インストールしてください。

最後に

コンテナ化が独立系サイトにもたらす価値は、80%が「環境の一貫性」、20%が「オーケストレーション能力」です。まずDockerfileを正しく書き、イメージを200MBまで抑え、composeファイルで4つのサービスを適切に管理すれば、独立系サイトの技術スタックで最も痛い環境ドリフトの問題は解決します。最初からK8sを追いかけてはいけません。それはまた別のフルタイムの仕事です。

導入ロードマップ:1週目はマルチステージDockerfileを書いて、イメージを1GBから200MBまで削減。2週目はcomposeでNginx+アプリ+MySQL+Redisを構成し、データボリュームをしっかりマウント。3週目はCI/CDパイプラインをイメージレジストリに接続し、コードをプッシュすれば自動でイメージがビルドされる仕組みに。この3ステップで、サーバー移行は2日から2時間に短縮できます。CDNや監視との連携はCDNグローバル高速化をご覧ください。日々の運用では、週に一度docker system dfでダングリングイメージを確認・削除すると、不要なイメージにディスクをじわじわ圧迫されるのを防げます。

覚えておきたい一言:コンテナ化の第一歩はK8s導入ではなく、どんなクリーンなサーバーでもコマンド1つでサイトを起動できるようにすることです。

环形山
环形山 クレーター専門家

公式アカウント · 環形山 Crater

環形山(Crater)は、WordPress独立サイト開発+Google SEO+GEO全域成長に特化した海外展開支援会社で、スマートハードウェア、産業機器、SaaS、新エネルギーなどの分野を手がけています。

プロダクト能力方法論ホワイトペーパー業界レポート
965件のシェア
78件のナレッジベース