この記事では、Docker をベースにした PHP 開発環境の構築に関する詳細なチュートリアルを主に紹介します。Docker が必要な友人は参照してください。それに
現在、多くの開発者が仮想マシン開発環境の管理に Vagrant を使用していますが、Vagrant には多くの欠点もあります (主な欠点は、リソースを大量に消費することです)。コンテナーテクノロジー、Docker、およびその他の Docker に似たテクノロジーの登場により、この問題の解決は簡単になりました。
免責事項
boot2docker の動作方法により、この記事で説明されている方法は、お使いの環境では正しく動作しない可能性があります。 Linux 以外の環境でフォルダーを Docker コンテナーと共有する必要がある場合は、さらに詳細な点に注意する必要があります。実際に発生した問題を紹介するために、特にフォローアップ記事を書きます。
良い開発環境とは何か
まず第一に、良い開発環境とは何かを知る必要があります。私にとって、良い開発環境には次の特性が必要です。
自由に使えます。自由に環境を削除したり、新しい環境を作成したりできなければなりません。早速スタート。使いたいときにすぐに使えます。
更新が簡単。私たちの業界では物事が非常に早く移り変わり、開発環境を新しいソフトウェア バージョンに更新するのは簡単でなければなりません。
Docker は上記のすべての機能とそれ以上の機能をサポートしています。コンテナーの破棄と再構築はほぼ瞬時に行うことができ、環境を更新するには、現在使用しているイメージを再構築するだけで済みます。
PHP開発環境とは
現在、Web アプリケーションは複雑であり、PHP 開発環境では環境のシンプルさを確保するためにさまざまな制限を設ける必要があります。
今回はNginx、PHP5-FPM、MySQLを使用してSynmfonyプロジェクトを実行します。
ペットと牛
議論したいもう 1 つの重要な点は、開発環境を複数のコンテナーにデプロイするべきか、それとも単一のコンテナーにデプロイするべきかということです。 どちらの方法にも独自の利点があります:
単一のコンテナは配布とメンテナンスが簡単です。これらは独立しているため、すべてが同じコンテナー内で実行され、仮想マシンのようなものになります。ただし、これは、コンテナ内の何か (PHP の新しいバージョンなど) をアップグレードする場合、コンテナ全体を再構築する必要があることも意味します。
複数のコンテナーを使用すると、コンポーネントを追加する際のモジュール性が向上します。各コンテナにはスタックの一部 (Web、PHP、MySQL など) が含まれているため、すべてを再構築することなく、各サービスを個別にスケールしたり追加したりできます。
私はめんどくさいし、ノートに何か他のものを載せる必要があるので、ここでは単一のコンテナの方法のみを紹介します。
初期化プロジェクト
最初に行うことは、新しい Symfony プロジェクトを初期化することです。推奨される方法は、composer の create-project コマンドを使用することです。 Composer をワークステーションにインストールすることもできましたが、それは単純すぎます。今回はDocker経由で利用します。
以前、Docker コマンドに関する記事「make docker コマンド」を投稿しました (嘘です。もともとこの記事に書いたもので、その後、分けたほうがよいと考えました)。
とにかく読めます。次に、コンポーザー コマンドがまだない場合は、独自のコンポーザー エイリアスを作成できます。
?
1
|
$ エイリアスコンポーザー = "docker run -i -t -v $PWD:/srv ubermuda/composer"
|
?
1
|
$composer create-project symfony/framwork-standard-edition SomeProject
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
debian:wheezy から
ENV DEBIAN_FRONTEND 非対話型
apt-get update -y を実行 apt-get install -y nginx php5-fpm php5-mysqlnd php5-cli mysql-server スーパーバイザを実行します
RUN sed -e 's/;daemonize = yes/daemonize = no/' -i /etc/php5/fpm/php-fpm.conf RUN sed -e 's/;listen.owner/listen.owner/' -i /etc/php5/fpm/pool.d/www.conf sed -e 's/;listen.group/listen.group/' -i /etc/php5/fpm/pool.d/www.conf を実行します echo "ndaemon off;" /etc/nginx/nginx.conf
vhost.conf /etc/nginx/sites-available/default を追加します supervisor.conf /etc/supervisor/conf.d/supervisor.conf を追加します init.sh /init.sh を追加
80 3306を公開
ボリューム["/srv"] WORKDIR/srv
CMD ["/usr/bin/supervisord"]
|
コードをコピーします。コードは次のとおりです:
RUN sed -e 's/;daemonize = yes/daemonize = no/' -i /etc/php5/fpm/php-fpm.conf
RUN sed -e 's/;listen.owner/listen.owner/' -i /etc/php5/fpm/pool.d/www.conf
RUN sed -e 's/;listen.group/listen.group/' -i /etc/php5/fpm/pool.d/www.conf
RUN echo "ndaemon off;" /etc/nginx/nginx.conf
ここでやるべきことは2つあります。 まず、PHP5-FPM と Nginx をフォアグラウンドで実行するように設定し、supervisord がそれらを追跡できるようにします。
次に、指定されたユーザーとして Web サーバーを実行し、ファイルのアクセス許可を処理するように PHP5-FPM を設定します。
次に、一連の構成ファイルをインストールする必要があります。最初は、Nginx 仮想ホスト構成ファイル vhost.conf:
です。
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
サーバー{ 80を聞いてください;
サーバー名_;
access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log;
ルート/srv/web; index app_dev.php;
場所 / { try_files $uri $uri/ /app_dev.php?$query_string; }
場所 ~ [^/].php(/|$) { fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_params を含める; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
[監修] ノデーモン=true
[プログラム:nginx] コマンド=/usr/sbin/nginx
[プログラム:php5-fpm] コマンド=/usr/sbin/php5-fpm
[プログラム:mysql] コマンド=/usr/bin/mysqld_safe
[プログラム:初期化] コマンド=/init.sh 自動再起動=false redirect_stderr=true redirect_stdout=/srv/app/logs/init.log
|
この起動スクリプトの問題は、通常、最初にいくつかのサービスを起動する必要があることです。たとえば、最初に MySQL を実行する場合に限り、いくつかのデータベース テーブルを初期化したい場合があります。解決策としては、起動スクリプトで MySQL を起動してからテーブルを初期化し、supervisord のプロセス管理に影響を与えないようにします。 MySQL を停止して、最後に Supervisord を開始する必要があります。
このようなスクリプトは次のようになります:
?
1 2 3 4 5
|
/etc/init.d/mysql start アプリ/コンソールのドクトリン:スキーマ:更新 --force /etc/init.d/mysql stop
exec /usr/bin/supervisord
|
実際の init.sh スクリプトは次のとおりです:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
#!/bin/bash
RET=1
[[ RET -ne 0 ]] をしながら 睡眠 1; mysql -e '終了' >/dev/null 2>RET=$? ; 完了
DB_NAME=${DB_NAME:-symfony}
mysqladmin -u root create $DB_NAME
if [ -n "$INIT" ] then /srv/$INIT フィ
|
イメージをビルドして実行します
準備は万端です、必要なのは東風だけです。また、 docker build コマンドを使用して、Symfony Docker イメージをビルドする必要があります:
?
1 2
|
$ cd docker-symfony $ docker build -t symfony .
|
1 2 |
$ cd SomeProject $ docker run -i -t -P -v $PWD:/srv symfony |
この一連のオプションの機能を見てみましょう:
-i は対話モードを開始します。つまり、STDIO (標準入出力) が現在の端末に接続されます。これは、ログを受信したり、プロセスにシグナルを送信したりする場合に便利です。
-t はコンテナの仮想 TTY を作成します。これは -i の良い友達で、通常は一緒に使用されます。
-P は、指定されたすべてのポート (この場合はポート 80) を公開するように Docker デーモンに指示します。
-v $PWD:/srv 現在のディレクトリをコンテナの /srv ディレクトリにマウントします。ディレクトリをマウントすると、ディレクトリの内容がターゲット マウント ポイントで利用できるようになります。
前に述べた DB_NAME および INIT 環境変数をまだ覚えていますが、それらが使用される理由は、環境をカスタマイズするためです。 基本的に、docker run の -e オプションを使用してコンテナーに環境変数を設定でき、起動スクリプトが環境変数を取得します。したがって、DB の名前が some_project_dev の場合は、次のようにコンテナーを実行できます。
?
1
|
$ docker run -i -t -P -v $PWD:/srv -e DB_NAME=some_project_dev symfony
|
?
1 2 3
|
#!/bin/bash 作曲家のインストール アプリ/コンソールのドクトリン:スキーマ:更新 --force
|
?
1 2 3 4
|
$ docker run -i -t -P -v $PWD:/srv -e DB_NAME=some_project_dev -e INIT=bin/setup
|
ここで、curl 経由でコンテナにリクエストを送信し、すべてが期待どおりに動作しているかどうかを確認します。まず、Docker によってコンテナーにマッピングされたパブリック ポート 80 を取得し、docker port コマンドを使用する必要があります:
?
1 2
|
$ docker ポート $(docker ps -aql 1) 80 0.0.0.0:49153
|
?
1
|
$カール http://localhost:49153
|
1
|
このファイルへのアクセスは許可されていません。詳細については、app_dev.php を確認してください。
|
1 2 3 4 5 6 7 8 9 |
// このチェックにより、運用サーバーに誤ってデプロイされたフロント コントローラーのデバッグへのアクセスが防止されます。 // これを自由に削除したり、拡張したり、より洗練されたものを作成したりしてください。 if (isset($_SERVER['HTTP_CLIENT_IP']) || isset($_SERVER['HTTP_X_FORWARDED_FOR']) || !(in_array(@$_SERVER['REMOTE_ADDR'], array('127.0.0.1', 'fe80::1', '::1')) || php_sapi_name() === 'cli-server ') ){ header('HTTP/1.0 403 禁止'); exit('このファイルへのアクセスは許可されていません。詳細については、'.basename(__FILE__).' を確認してください。'); } |
これらの行は、localhost の外部からの dev コントローラーへのアクセスを防ぎます。
これで、再度カールするか、ブラウザを使用して http://localhost:49153/ にアクセスすると、正常に動作できるようになります。