PHPアプリケーションを安全にDocker化する方法
James Olaogun
2023年8月2日
0 分で読めます編集者注:2023年8月10日
この記事は更新され、チュートリアルでより新しいバージョンのPHPを使用しています。
PHPアプリケーションを開発したものの、軽量で持ち運びやすく、安全性も保てる方法で、アプリケーションをサポートするインフラから切り離したいとします。ほかの開発者が環境全体を再構築せずに作業できるようにしたいでしょう。つまり、アプリケーションをコンテナ化し、依存関係とともにコンテナにパッケージ化して、さまざまな環境で簡単に共有できるようにします。
現在、最も広く使われているコンテナ化ソリューションはDockerです。2013年に初めて公開されたオープンソースプラットフォームです。以来、アプリケーションの分離、再利用可能なCI/CDコンポーネントの作成、迅速なデプロイを可能にするテクノロジーとして、ソフトウェア開発で広く採用されてきました。
このチュートリアルでは、PHPアプリケーションを安全にコンテナ化、つまり「Docker化」する方法を手順に沿って解説します。また、最新のアプリケーション向けセキュリティツールを提供する開発者向けセキュリティプラットフォーム、Snykを使って、脆弱性を検出し、自動で修正します。
前提条件と推奨事項
以下のチュートリアルを始める前に、次のツールが揃っていることを確認してください。
お使いのマシンにDockerがインストールされていること。PHPコンテナの実行と管理に使用します。
Snykの無料アカウント。Snykのセキュリティスキャンツールを使って、コンテナの脆弱性を検出し、修正します。
Snyk CLIのインストールと実行に必要なNPMまたはYarn。
基本的なPHPアプリケーション。このチュートリアルでは、新規作成したLaravelプロジェクトを使用します。
これらの要件を満たしていることを確認したら、チュートリアルに進む前に、次のヒントも参考にしてください。PHPアプリケーションをスムーズかつ安全にDocker化するための推奨事項です。
特定のイメージバージョンをベースにビルドする
アプリケーションのビルドには、必ずDockerイメージの特定のバージョンを使用してください。たとえば、PHP-FPMを取得する代わりに、イメージのバージョンを指定してPHP:8.0-fpmを取得できます。使用するベースイメージは、アプリケーションのバージョン要件によって異なる点に注意してください
そうすることで、既知のテスト済みで安定したリリースをベースにアプリケーションを構築できます。また、異なる環境でもイメージが同じ基盤プラットフォームと依存関係を使用できるため、再現性と一貫性が向上します。
リモートの依存関係にADDを使わない
ADDコマンドは任意のURLからファイルをダウンロードできるため、Docker化したアプリケーションにセキュリティ上の脆弱性を持ち込むおそれがあります。そのため、リモートの依存関係を追加する目的でDockerfileに`ADD`コマンドを使うことは避けることをおすすめします。
代わりにCOPYコマンドを使って、ローカルファイルシステムからファイルをコピーしてください。COPYコマンドを使えば、アプリケーションに必要なファイルだけがDockerイメージに含まれます。これも脆弱性のリスク低減につながります。
docker-compose YAMLファイルを使う
Docker Composeを使うと、YAMLファイルでDockerアプリケーションを定義し、アプリケーションのビルド方法や実行方法を指定して、Dockerコンテナを管理・オーケストレーションできます。Docker Composeを使うメリットには、次のようなものがあります。
アプリケーションのコンポーネントを分離。Docker Composeを使うと、アプリケーションのコンポーネントを別々のコンテナに分離できます。各コンテナの攻撃対象領域を限定し、単一障害点のリスクを軽減できます。
環境変数を使用。Docker Composeでは環境変数を使ってアプリケーションを設定できるため、データベースのパスワードなどの機密情報を安全に管理できます。
ネットワーク接続を管理。Docker Composeでは、コンテナ間のネットワーク接続を管理できます。これにより、コンテナ同士が安全なチャネル経由でのみ通信するようにできます。
Windows、Mac、またはLinux向けにDocker Desktopをインストールしていれば、Docker Composeもすでに利用できます。
mod_phpではなくPHP-FPMを使う
PHP-FPMとmod_phpは、どちらもWebサーバー上でPHPアプリケーションを実行する方法ですが、仕組みには違いがあります。mod_phpはApache WebサーバーがPHPファイルを処理できるようにするApacheモジュールです。一方、PHP-FPMは、NGINXやApacheなど、さまざまなWebサーバーと連携するPHPプロセスマネージャーです。
PHP-FPMは、特にトラフィックの多い環境において、PHPアプリケーションをより効率的かつスケーラブルに実行できる方法と一般に考えられています。
マルチステージビルドを使う
マルチステージビルドは、Dockerでより小さく安全なイメージを作成するための手法です。Dockerfile内にそれぞれ独自の手順を持つ複数のステージを作成すれば、変更のたびにイメージ全体を最初から再構築する必要がありません。その結果、Dockerのビルドプロセスの効率と速度が向上します。
Docker化したアプリケーションのセキュリティを必ずテストする
アプリケーションの安全性を確保し、向上させるには、定期的なセキュリティテストが欠かせません。Dockerはアプリケーションを実行するための隔離環境を提供しますが、それだけでアプリケーションの安全性が保証されるわけではありません。攻撃者に悪用される前に潜在的な脆弱性を特定して対処するため、定期的にセキュリティチェックを実施してください。
PHPアプリケーションを安全にDocker化する5つのステップ
それでは実践編に進みましょう。ここからは、先ほどのヒントも取り入れながら、Laravel PHPアプリケーションを安全にDocker化する5つのステップを解説します。
1. Apacheを使ってDockerfileを設定する
まだプロジェクトがない場合は新しいLaravelプロジェクトを作成し、cdコマンドで新しいLaravelプロジェクトのディレクトリに移動します。たとえば、次のコマンドでは{{laravel-application-directory}}をLaravelアプリケーションのディレクトリ名に置き換えてください。
Laravelアプリケーションのルートディレクトリに、Dockerfileという名前の新しいファイルを作成します。
作成したDockerfileに、次のコードをコピーして貼り付けます。
前述のとおり、スケーラブルなソリューションを構築するにはPHP-FPMのほうが適していますが、このチュートリアルではアプリケーションが小規模なためmod_phpを使用します。
また、上記のDockerfileではマルチステージビルドを使用しています。最初のステージでは公式Composerイメージを使って、アプリケーションの依存関係をインストールし、オートローダーをビルドします。2番目のステージでは公式PHP/Apacheイメージを使ってアプリケーションを実行します。Composerのビルドファイルをローカルファイルシステムからコピーするには、COPYコマンドを使い、ADDコマンドを使わない点に注意してください。
Laravelアプリケーションのルートディレクトリに、docker-compose.ymlという名前の新しいファイルを作成します。
作成したdocker-compose.ymlに、次のコードをコピーして貼り付けます。
前述のコードでは、snykdemoappサービスがPHPアプリケーション用のコンテナです。また、networksセクションでは、Docker Composeが通信に使用するapp-networkを定義しています。
2. docker-compose.ymlにMySQLデータベースコンテナを設定する
docker-compose.ymlファイルにMySQLコンテナを追加しましょう。このコンテナがLaravelアプリケーションのデータベースをホストします。
ステップ1で作成したdocker-compose.ymlファイルに、次のコードを新しいサービスとして追加し、MySQLコンテナ用のサービスを作成します。
前述のコードでは、次のようになっています。
app_dbは、MySQLバージョン5.7のイメージを使って構築されるデータベースサービスの名前です。名前は自由に変更できますが、関連付けられている他のサービスでも変更してください。{{database_name}}は、任意のデータベース名です。{{database_user}}は、任意のデータベースユーザー名です。{{dbuser_password}}は、データベースユーザーに設定する任意のパスワードです。
これで、Docker環境にMySQLコンテナを追加できました。
3. docker-compose.ymlにPHPMyAdminコンテナを設定する
次に、LaravelコンテナとMySQLコンテナに加えて、ローカル開発やテスト用のPHPMyAdminコンテナを追加しましょう。PHPMyAdminは、MySQLとMariaDBを管理するための無料のオープンソースツールです。データベースを管理するためのWebインターフェースを提供します。PHPMyAdminは開発環境のみで使用し、本番環境では使用しないことをおすすめします。
以下のコードをdocker-compose.ymlに新しいサービスとして追加し、PHPMyAdminコンテナ用のサービスを作成します。
前述のコードでは、phpmyadminはphpmyadmin/phpmyadminイメージを使って構築されるPHPMyAdminサービスの名前です。environmentセクションでは、PMA_HOST変数をapp_dbに設定しています。これは、同じdocker-compose.ymlファイル内のMySQLサービスの名前です。
これで、LaravelコンテナおよびMySQLコンテナと連携するPHPMyAdminコンテナを設定できました。PHPMyAdminイメージは開発目的でのみ使用してください。本番環境で使用すると、アプリケーションのセキュリティリスクになります。
4. DockerでLaravel PHPアプリケーションをビルドして実行する
Dockerfileとdocker-compose.ymlの設定ができたら、Dockerサービスを起動し、実行中であることを確認します。その後、次のコマンドでLaravel PHPアプリケーションをビルドして実行できます。
docker-compose build:Dockerイメージをビルドします。docker-compose up -d:コンテナを起動します。docker ps:コンテナのステータスを確認します。
上記のコマンドがすべて正常に実行されたら、Webブラウザーを開いてhttp://localhost:8000/にアクセスし、Laravelアプリケーションのトップページを表示します。

http://localhost:8080/にアクセスすると、PHPAdminインターフェースも表示できます。docker-compose.ymlファイルで設定したMYSQL_USERとMYSQL_PASSWORDを使ってログインしてください。

5. SnykでPHPアプリケーションをテストして保護する
Dockerアプリケーションのビルドが完了し、ブラウザーからアプリケーションとPHPMyAdminの両方にアクセスできたら、次はDocker化したアプリケーションのセキュリティをテストします。このチュートリアルでは、Snykを使ってDocker化したアプリケーションをテストし、安全性を確保します。
ページに表示されている任意のSSOを使ってログインするか、新しいSnykアカウントを作成します。記事の「前提条件」セクションで説明したとおり、Snyk CLIをインストールし、お使いのマシンを認証してください。

Snykの設定が完了したら、Snyk CLIを使ってDocker化したアプリケーションのセキュリティを評価します。Laravelアプリケーションのルートディレクトリで次のコマンドを実行してください。
前述のコマンドの{{your-image}}は、テストするイメージの名前です。`docker ps`コマンドを使うと、アプリケーション内のDockerイメージ一覧を取得できます。
このチュートリアルのsnykdemoappという名前のベースPHP 8.2イメージに対して前述のコマンドを実行すると、次の結果が得られます。

PHP 8.2は最新の長期サポート(LTS)バージョンです。このコンテナのベースイメージで69件のセキュリティ問題が見つかりましたが、すべて深刻度は低いものでした。
PHP 7.4など古いバージョンを本番アプリケーションで使用している場合、対処が必要な、より重大で緊急性の高いセキュリティ脆弱性が見つかるでしょう。そのような場合、脆弱性の件数が少ない代替イメージを提示するSnykが、さらに役立ちます。
snyk container testコマンドで確認できるのは、その時点での結果のみです。より効果的な方法は、container monitorコマンドを実行してコンテナをスキャンすることです。
container monitorコマンドを実行すると、コンテナイメージのテスト情報がSnykに送信されます。Snykはその情報をダッシュボードに表示し、今後イメージで発生する可能性のある脆弱性を通知します。
container monitorを、このチュートリアルのsnykdemoappという名前のベースPHP 7.4イメージに対して実行します。

PHPアプリケーションで検出された脆弱性を修正する方法
PHPコンテナのテストが完了したら、検出された脆弱性を修正する際に役立つポイントをいくつかご紹介します。
イメージを再ビルドして、上流のDockerベースイメージから最新のセキュリティ更新を取得しましょう。 これにより、セキュリティ更新がアプリケーションに確実に反映されます。再ビルド後、もう一度セキュリティスキャンを実行し、ベースイメージの最新のセキュリティ更新に伴って発生する可能性のある脆弱性を特定して修正します。
Snykが提供する脆弱性評価を確認してください。 このリストは、アプリケーションの依存関係に潜むセキュリティ上の問題を把握するうえで役立ちます。
脆弱性はさまざまな要因から生じる可能性があることを念頭に置きましょう。 PHPランタイムや、ベースイメージにインストールされているツールやライブラリもその要因に含まれます。アプリケーションスタックのすべてのコンポーネントを定期的に更新・監視し、セキュリティの脆弱性を速やかに特定して対処することが重要です。
まとめ
いくつかのベストプラクティスに従うことで、脆弱性の少ないアプリケーションを開発できます。手順に沿ったチュートリアルを最後まで進めた方は、Snykセキュリティプラットフォームを使って脆弱性を検出・修正しながら、安全なDocker化PHPアプリケーションを開発できるはずです。
このチュートリアルで使用したDocker化Laravelアプリケーションのコードは、GitHubでご覧いただけます。
開発者ファーストのコンテナセキュリティ
Snykは、コンテナイメージとKubernetesワークロードの脆弱性を検出し、自動的に修正します。



