Ubuntu 14.04でAnsibleを使用して基本的なPHPアプリケーションをデプロイする方法
紹介
このチュートリアルでは、Ansibleを使用して基本的なPHPアプリケーションをプロビジョニングするプロセスを説明します。このチュートリアルの最後の目標は、新しいWebサーバーがターゲットDroplet上で1つのSSH接続や手動コマンドを実行することなく、基本的なPHPアプリケーションを提供することです。
私たちは、例としてLaravelフレームワークを使用しますが、これらの指示は、すでに自分のフレームワークやアプリケーションがある場合には、他のフレームワークやアプリケーションをサポートするように簡単に修正できます。
前提条件
このチュートリアルでは、Ansibleを使用してUbuntu 14.04のDropletにNginx、PHP、およびその他のサービスをインストールおよび構成します。このチュートリアルは基本的なAnsibleの知識に基づいていますので、Ansibleが初めての方は、最初にこの基本的なAnsibleチュートリアルを読むことができます。
このチュートリアルに従うためには、次のものが必要です:
-
私たちがPHPアプリケーションを構成しデプロイするために使用する任意のサイズのUbuntu 14.04のDropletが1つ必要です。このマシンのIPアドレスは、チュートリアルの全体を通じて
your_server_ipと呼ばれます。 Ansibleに使用されるUbuntu 14.04のDropletが1つあります。これがこのチュートリアル全体にわたってログインするDropletです。
両方のドロップレットに設定された非ルートユーザーがsudo権限を持っています。
PHPデプロイメントドロップレットへのログインを認証するためのAnsibleドロップレット用のSSHキーは、あなたのAnsibleドロップレットでこのチュートリアルに従ってセットアップできます。
ステップ1 — Ansibleのインストール
最初のステップはAnsibleをインストールすることです。これはPPA(パーソナルパッケージアーカイブ)をインストールし、aptを使用してAnsibleパッケージをインストールすることで簡単に実行できます。
まず、apt-add-repositoryコマンドを使ってPPAを追加します。
- sudo apt-add-repository ppa:ansible/ansible
それが終了したら、apt キャッシュを更新してください。
- sudo apt-get update
最後に、Ansibleをインストールします。
- sudo apt-get install ansible
Ansibleがインストールされたら、新しい作業用のディレクトリを作成し、基本的な設定を行います。デフォルトでは、Ansibleは/etc/ansible/hostsにあるホストファイルを使用し、管理しているすべてのサーバーが含まれています。そのファイルは一部の使用例には適していますが、グローバルであるため、ここでは望ましくありません。
このチュートリアルでは、ローカルのホストファイルを作成し、それを使用します。作業ディレクトリ内に新しいAnsible設定ファイルを作成することで、Ansibleに同じディレクトリ内のホストファイルを探すように指示できます。
新しいディレクトリを作成します(これをこのチュートリアルの残りで使用します)。
- mkdir ~/ansible-php
新しいディレクトリに移動してください。
- cd ~/ansible-php/
新しいファイルを作成してansible.cfgと名付け、nanoやお気に入りのテキストエディタで編集のために開きます。
- nano ansible.cfg
ansible.cfgファイルに以下をコピーして、[defaults]グループのhostsの値でhostfile構成オプションを追加してください。
[defaults]
hostfile = hosts
このansible.cfgファイルを保存して閉じます。次に、アプリケーションをデプロイするPHP DropletのIPアドレスを含むhostsファイルを作成します。
- nano hosts
以下をコピーして、phpのセクションを追加します。your_server_ipをあなたのサーバーのIPアドレスに、sammyをPHP Dropletの事前準備で作成したsudoの非rootユーザーに置き換えてください。
[php]
your_server_ip ansible_ssh_user=sammy
ホストファイルを保存して閉じます。新しいphpグループにpingモジュールを呼び出して、Ansibleがホストに期待通り接続できるかどうかを確認するための簡単なチェックを実行しましょう。
- ansible php -m ping
これまでにそのホストにログインしたことがあるかどうかに応じて、SSHホスト認証チェックが表示されることがあります。pingは成功した応答を返すべきで、以下のようになります:
111.111.111.111 | success >> {
"changed": false,
"ping": "pong"
}
Ansibleは現在インストールされ、構成されています。次に、ウェブサーバーの設定に進むことができます。
ステップ2 — 必要なパッケージのインストール
このステップでは、Ansibleとaptを使用して、いくつかの必要なシステムパッケージをインストールします。特に、git、nginx、sqlite3、mcrypt、およびいくつかのphp5-*パッケージをインストールします。
パッケージをインストールするためにaptモジュールを追加する前に、基本的なプレイブックを作成する必要があります。このチュートリアルを進める中で、このプレイブックを発展させていきます。php.ymlという名前の新しいプレイブックを作成してください。
- nano php.yml
次の構成を貼り付けてください。最初の2行は、使用したいホストグループ(php)を指定し、デフォルトでsudoを使用してコマンドを実行するようにしています。残りの部分では、必要なパッケージを含むモジュールを追加しています。これは、あなた自身のアプリケーションに合わせてカスタマイズすることもできますし、例のLaravelアプリケーションに従っている場合は、以下の構成を使用することもできます。
---
- hosts: php
sudo: yes
tasks:
- name: install packages
apt: name={{ item }} update_cache=yes state=latest
with_items:
- git
- mcrypt
- nginx
- php5-cli
- php5-curl
- php5-fpm
- php5-intl
- php5-json
- php5-mcrypt
- php5-sqlite
- sqlite3
php.ymlファイルを保存します。最後に、ansible-playbookを実行してDropletにパッケージをインストールします。PHP Dropletのsudoユーザーがパスワードを必要とする場合は、--ask-sudo-passオプションを使用するのを忘れないでください。
- ansible-playbook php.yml --ask-sudo-pass
ステップ3 — システム構成ファイルの修正
このセクションでは、PHP ドロップレットのいくつかのシステム構成ファイルを修正します。変更する最も重要な構成オプションは、php5-fpm の cgi.fix_pathinfo オプションです。これは、デフォルト値がセキュリティリスクであるためです。
最初に、追加するすべてのセクションについて説明し、その後にコピーして貼り付けるための全体のphp.ymlファイルを含めます。
lineinfileモジュールは、ファイル内の設定値が私たちの期待通りであることを保証するために使用できます。これは、Ansibleがパラメータがありそうなほとんどの形式を理解できるように、一般的な正規表現を使用して行うことができます。また、変更を有効にするためにphp5-fpmとnginxを再起動する必要があるため、新しいhandlersセクションで2つのハンドラーを追加する必要があります。ハンドラーはこれに最適で、タスクが変更されたときにのみ発動します。また、ハンドラーはプレイブックの最後に実行されるため、複数のタスクが同じハンドラーを呼び出しても、ハンドラーは1回だけ実行されます。
上記を行うセクションはこのようになります:
- name: ensure php5-fpm cgi.fix_pathinfo=0
lineinfile: dest=/etc/php5/fpm/php.ini regexp='^(.*)cgi.fix_pathinfo=' line=cgi.fix_pathinfo=0
notify:
- restart php5-fpm
- restart nginx
handlers:
- name: restart php5-fpm
service: name=php5-fpm state=restarted
- name: restart nginx
service: name=nginx state=restarted
注意: Ansible バージョン 1.9.1 のバグ
Ansibleバージョン1.9.1には、serviceモジュールを使用してphp5-fpmを再起動できないバグがあります。これは私たちのハンドラーで使用しています。
修正がリリースされるまでの間、service コマンドを使用する代わりに shell コマンドを使って restart php5-fpm ハンドラを変更することで、この問題を回避できます。次のようにします:
- name: restart php5-fpm
shell: service php5-fpm restart
これにより問題が回避され、php5-fpmが正しく再起動されます。
次に、php5-mcrypt モジュールが有効になっていることも確認する必要があります。これは、シェルタスクで php5enmod スクリプトを実行して行い、有効になっているときに 20-mcrypt.ini ファイルが正しい場所にあることを確認します。このタスクが特定のファイルを作成することを Ansible に伝えていることに注意してください。そのファイルが存在する場合、タスクは実行されません。
- name: enable php5 mcrypt module
shell: php5enmod mcrypt
args:
creates: /etc/php5/cli/conf.d/20-mcrypt.ini
さあ、再び php.yml を編集のために開いてください。
- nano php.yml
上記のタスクとハンドラーを追加して、ファイルが以下に一致するようにしてください。
---
- hosts: php
sudo: yes
tasks:
- name: install packages
apt: name={{ item }} update_cache=yes state=latest
with_items:
- git
- mcrypt
- nginx
- php5-cli
- php5-curl
- php5-fpm
- php5-intl
- php5-json
- php5-mcrypt
- php5-sqlite
- sqlite3
- name: ensure php5-fpm cgi.fix_pathinfo=0
lineinfile: dest=/etc/php5/fpm/php.ini regexp='^(.*)cgi.fix_pathinfo=' line=cgi.fix_pathinfo=0
notify:
- restart php5-fpm
- restart nginx
- name: enable php5 mcrypt module
shell: php5enmod mcrypt
args:
creates: /etc/php5/cli/conf.d/20-mcrypt.ini
handlers:
- name: restart php5-fpm
service: name=php5-fpm state=restarted
- name: restart nginx
service: name=nginx state=restarted
最後に、プレイブックを実行してください。
- ansible-playbook php.yml --ask-sudo-pass
ドロップレットには必要なすべてのパッケージがインストールされ、基本的な設定が完了し、準備が整いました。
ステップ4 — Gitリポジトリのクローン作成
このセクションでは、Gitを使用してLaravelフレームワークのリポジトリをDropletにクローンします。ステップ3と同様に、プレイブックに追加するセクションのすべてを説明し、その後、あなたがコピー&ペーストできるように全体のphp.ymlファイルを含めます。
Gitリポジトリをクローンする前に、/var/wwwが存在することを確認する必要があります。これをファイルモジュールを使用してタスクを作成することで実行できます。
- name: create /var/www/ directory
file: dest=/var/www/ state=directory owner=www-data group=www-data mode=0700
上記のように、リポジトリをドロップレットにクローンするためにGitモジュールを使用する必要があります。このプロセスは簡単で、通常、git cloneコマンドに必要なのはソースリポジトリだけです。この場合、移動先も定義し、リポジトリが既に存在する場合には更新しないようにAnsibleに指示します。このためにupdate=noを設定します。Laravelを使用しているため、使用するgitリポジトリのURLはhttps://github.com/laravel/laravel.gitです。
しかし、正しい権限を確保するために、タスクをwww-dataユーザーとして実行する必要があります。これを行うために、sudoを使って特定のユーザーとしてコマンドを実行するようにAnsibleに指示することができます。最終的なタスクは次のようになります:
- name: Clone git repository
git: >
dest=/var/www/laravel
repo=https://github.com/laravel/laravel.git
update=no
sudo: yes
sudo_user: www-data
注: SSHベースのリポジトリの場合、SSHホスト検証がタスクを停止するのを防ぐために、accept_hostkey=yesを追加できます。
以前と同様に、php.ymlファイルを編集するために開いてください。
- nano php.yml
上記のタスクをプレイブックに追加してください。ファイルの終わりは次の内容と一致する必要があります。
...
- name: enable php5 mcrypt module
shell: php5enmod mcrypt
args:
creates: /etc/php5/cli/conf.d/20-mcrypt.ini
- name: create /var/www/ directory
file: dest=/var/www/ state=directory owner=www-data group=www-data mode=0700
- name: Clone git repository
git: >
dest=/var/www/laravel
repo=https://github.com/laravel/laravel.git
update=no
sudo: yes
sudo_user: www-data
handlers:
- name: restart php5-fpm
service: name=php5-fpm state=restarted
- name: restart nginx
service: name=nginx state=restarted
プレイブックを保存して閉じてから、それを実行します。
- ansible-playbook php.yml --ask-sudo-pass
ステップ5 — Composerを使ったアプリケーションの作成
このステップでは、Composerを使用してPHPアプリケーションとその依存関係をインストールします。
Composerには、すべての必要な依存関係をインストールし、その後、composer.jsonファイルのpost-create-project-cmdセクションで定義されたプロジェクト作成手順を実行するcreate-projectコマンドがあります。これは、アプリケーションが初めて使用されるために正しく設定されることを保証する最良の方法です。
以下のAnsibleタスクを使用して、Composerをグローバルにダウンロードしてインストールし、/usr/local/bin/composerとして配置できます。これにより、Dropletを使用する誰でも、Ansibleを含めてアクセスできるようになります。
- name: install composer
shell: curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
args:
creates: /usr/local/bin/composer
Composerがインストールされていると、使用できるComposerモジュールがあります。この場合、私たちはComposerにプロジェクトの場所を伝えたい(working_dirパラメーターを使用)し、create-projectコマンドを実行したいと思います。また、create-projectコマンドに対応していないため、optimize_autoloader=noパラメーターも追加する必要があります。gitコマンドと同様に、このコマンドをwww-dataユーザーとして実行し、権限が有効であることを確認したいと思います。すべてをまとめると、次のタスクが得られます:
- name: composer create-project
composer: command=create-project working_dir=/var/www/laravel optimize_autoloader=no
sudo: yes
sudo_user: www-data
注意: create-project タスクは、新しい Droplet で時間がかかる場合があります。なぜなら、Composer は空のキャッシュを持っていて、すべてを新たにダウンロードする必要があるからです。
今、php.ymlファイルを編集のために開いてください。
- nano php.yml
tasks セクションの最後に、handlers の上に上記のタスクを追加してください。これにより、プレイブックの最後が以下の内容と一致します:
...
- name: Clone git repository
git: >
dest=/var/www/laravel
repo=https://github.com/laravel/laravel.git
update=no
sudo: yes
sudo_user: www-data
- name: install composer
shell: curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
args:
creates: /usr/local/bin/composer
- name: composer create-project
composer: command=create-project working_dir=/var/www/laravel optimize_autoloader=no
sudo: yes
sudo_user: www-data
handlers:
- name: restart php5-fpm
service: name=php5-fpm state=restarted
- name: restart nginx
service: name=nginx state=restarted
最後に、プレイブックを実行してください。
- ansible-playbook php.yml --ask-sudo-pass
Ansibleを再度実行した場合、何が起こるでしょうか?composer create-projectが再度実行され、Laravelの場合、これは新しいAPP_KEYを意味します。したがって、私たちが望むのは、新しいクローンの後にのみそのタスクを実行するように設定することです。git cloneタスクの結果に変数を登録することで、それが1回だけ実行されるように確認できます。そして、その結果をcomposer create-projectタスク内で確認します。git cloneタスクが変更された場合はcomposer create-projectを実行し、そうでない場合はスキップします。
注意: Ansible composer モジュールのいくつかのバージョンにバグがあるようで、依存関係がインストールされていなくてもスクリプトが実行されたことを無視して、Changed の代わりに OK と出力する可能性があります。
php.ymlファイルを編集のために開いてください。
- nano php.yml
git clone タスクを見つけてください。タスクの結果を cloned 変数に保存するために register オプションを追加してください。次のように:
- name: Clone git repository
git: >
dest=/var/www/laravel
repo=https://github.com/laravel/laravel.git
update=no
sudo: yes
sudo_user: www-data
register: cloned
次に、composer create-projectタスクを見つけます。whenオプションを追加して、cloned変数が変更されているかどうかを確認します。
- name: composer create-project
composer: command=create-project working_dir=/var/www/laravel optimize_autoloader=no
sudo: yes
sudo_user: www-data
when: cloned|changed
プレイブックを保存して、実行してください。
- ansible-playbook php.yml --ask-sudo-pass
これでコンポーザは実行されるたびに APP_KEY を変更しなくなります。
ステップ6 — 環境変数の更新
このステップでは、私たちのアプリケーションの環境変数を更新します。
Laravelはデフォルトの.envファイルを提供しており、APP_ENVをlocalに、APP_DEBUGをtrueに設定します。私たちはそれらをそれぞれproductionとfalseに入れ替えたいと思います。これは、次のタスクでlineinfileモジュールを使用することで簡単に実行できます。
- name: set APP_DEBUG=false
lineinfile: dest=/var/www/laravel/.env regexp='^APP_DEBUG=' line=APP_DEBUG=false
- name: set APP_ENV=production
lineinfile: dest=/var/www/laravel/.env regexp='^APP_ENV=' line=APP_ENV=production
php.ymlファイルを編集のために開いてください。
- nano php.yml
このタスクをプレイブックに追加してください; ファイルの最後は以下のように一致する必要があります:
...
- name: composer create-project
composer: command=create-project working_dir=/var/www/laravel optimize_autoloader=no
sudo: yes
sudo_user: www-data
when: cloned|changed
- name: set APP_DEBUG=false
lineinfile: dest=/var/www/laravel/.env regexp='^APP_DEBUG=' line=APP_DEBUG=false
- name: set APP_ENV=production
lineinfile: dest=/var/www/laravel/.env regexp='^APP_ENV=' line=APP_ENV=production
handlers:
- name: restart php5-fpm
service: name=php5-fpm state=restarted
- name: restart nginx
service: name=nginx state=restarted
プレイブックを保存して実行します:
- ansible-playbook php.yml --ask-sudo-pass
lineinfileモジュールは、任意のテキストファイルを迅速に調整するのに非常に便利で、これのような環境変数が正しく設定されていることを確実にするのに優れています。
ステップ7 — Nginxの設定
このセクションでは、PHPアプリケーションを提供するためにNginxを設定します。
今、ウェブブラウザであなたのDropletにアクセスすると(すなわちhttp://your_server_ip/)、Laravelの新しいプロジェクトページの代わりにNginxのデフォルトページが表示されます。これは、アプリケーションを/var/www/laravel/publicディレクトリから提供できるように、Nginxウェブサーバーをまだ設定していないからです。これを行うには、そのディレクトリを使用してNginxのデフォルト設定を更新し、PHPスクリプトを処理できるようにphp-fpmのサポートを追加する必要があります。
nginx.confという新しいファイルを作成します:
- nano nginx.conf
このサーバーブロックをそのファイル内に保存してください。このNginxの設定に関する詳細は、このチュートリアルのステップ4を参照できます。以下の変更は、Laravelの公開ディレクトリの場所を指定し、Nginxがhostsファイルで定義したホスト名をserver_nameとしてinventory_hostname変数を使用することを確実にします。
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
root /var/www/laravel/public;
index index.php index.html index.htm;
server_name {{ inventory_hostname }};
location / {
try_files $uri $uri/ =404;
}
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /var/www/laravel/public;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
nginx.confファイルを保存して閉じてください。
さて、テンプレートモジュールを使用して新しい設定ファイルを配布できます。template モジュールは copy モジュールと非常に似ているように見え、聞こえますが、大きな違いがあります。copy は、何の変更も加えずに1つ以上のファイルをコピーしますが、template は単一のファイルをコピーし、そのファイル内のすべての変数を解決します。設定ファイル内で {{ inventory_hostname }} を使用したため、template モジュールを使用して、hosts ファイルで使用したIPアドレスに解決されるようにします。これにより、Ansibleが使用する設定ファイルをハードコーディングする必要がなくなります。
ただし、通常のタスクを書くときと同様に、Droplet上で何が起こるかを考慮する必要があります。Nginx設定を変更するため、Nginxとphp-fpmを再起動する必要があります。これはnotifyオプションを使用して行われます。
- name: Configure nginx
template: src=nginx.conf dest=/etc/nginx/sites-available/default
notify:
- restart php5-fpm
- restart nginx
php.ymlファイルを開いてください:
- nano php.yml
このnginxタスクをタスクセクションの最後に追加してください。全体のphp.ymlファイルは次のようになります:
---
- hosts: php
sudo: yes
tasks:
- name: install packages
apt: name={{ item }} update_cache=yes state=latest
with_items:
- git
- mcrypt
- nginx
- php5-cli
- php5-curl
- php5-fpm
- php5-intl
- php5-json
- php5-mcrypt
- php5-sqlite
- sqlite3
- name: ensure php5-fpm cgi.fix_pathinfo=0
lineinfile: dest=/etc/php5/fpm/php.ini regexp='^(.*)cgi.fix_pathinfo=' line=cgi.fix_pathinfo=0
notify:
- restart php5-fpm
- restart nginx
- name: enable php5 mcrypt module
shell: php5enmod mcrypt
args:
creates: /etc/php5/cli/conf.d/20-mcrypt.ini
- name: create /var/www/ directory
file: dest=/var/www/ state=directory owner=www-data group=www-data mode=0700
- name: Clone git repository
git: >
dest=/var/www/laravel
repo=https://github.com/laravel/laravel.git
update=no
sudo: yes
sudo_user: www-data
register: cloned
- name: install composer
shell: curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
args:
creates: /usr/local/bin/composer
- name: composer create-project
composer: command=create-project working_dir=/var/www/laravel optimize_autoloader=no
sudo: yes
sudo_user: www-data
when: cloned|changed
- name: set APP_DEBUG=false
lineinfile: dest=/var/www/laravel/.env regexp='^APP_DEBUG=' line=APP_DEBUG=false
- name: set APP_ENV=production
lineinfile: dest=/var/www/laravel/.env regexp='^APP_ENV=' line=APP_ENV=production
- name: Configure nginx
template: src=nginx.conf dest=/etc/nginx/sites-available/default
notify:
- restart php5-fpm
- restart nginx
handlers:
- name: restart php5-fpm
service: name=php5-fpm state=restarted
- name: restart nginx
service: name=nginx state=restarted
プレイブックを保存して再実行します:
- ansible-playbook php.yml --ask-sudo-pass
完了したら、ブラウザに戻ってリフレッシュしてください。これでLaravelの新しいプロジェクトページが表示されるはずです!
結論
このチュートリアルでは、公開リポジトリを使ったPHPアプリケーションのデプロイについて説明します。Ansibleがどのように機能するかを学ぶには最適ですが、常にオープンソースプロジェクトや公開リポジトリで作業するわけではありません。つまり、ステップ3で私用リポジトリとともにgit cloneを認証する必要があります。これはSSHキーを使って非常に簡単に行うことができます。
例えば、SSHデプロイキーを作成してリポジトリに設定したら、Ansibleを使用してサーバーにコピーし、git cloneタスクの前にそれらを設定できます:
- name: create /var/www/.ssh/ directory
file: dest=/var/www/.ssh/ state=directory owner=www-data group=www-data mode=0700
- name: copy private ssh key
copy: src=deploykey_rsa dest=/var/www/.ssh/id_rsa owner=www-data group=www-data mode=0600
それにより、サーバーはあなたのアプリケーションを正しく認証し、展開できるようになるはずです。
あなたは、Composerを使用して依存関係を管理することで、UbuntuベースのNginxウェブサーバー上に基本的なPHPアプリケーションを展開しました!すべては、あなたのPHPドロップレットに直接ログインして手動のコマンドを1つも実行することなく完了しました。
