ウェブサイト検索

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を追加します。

  1. sudo apt-add-repository ppa:ansible/ansible

それが終了したら、apt キャッシュを更新してください。

  1. sudo apt-get update

最後に、Ansibleをインストールします。

  1. sudo apt-get install ansible

Ansibleがインストールされたら、新しい作業用のディレクトリを作成し、基本的な設定を行います。デフォルトでは、Ansibleは/etc/ansible/hostsにあるホストファイルを使用し、管理しているすべてのサーバーが含まれています。そのファイルは一部の使用例には適していますが、グローバルであるため、ここでは望ましくありません。

このチュートリアルでは、ローカルのホストファイルを作成し、それを使用します。作業ディレクトリ内に新しいAnsible設定ファイルを作成することで、Ansibleに同じディレクトリ内のホストファイルを探すように指示できます。

新しいディレクトリを作成します(これをこのチュートリアルの残りで使用します)。

  1. mkdir ~/ansible-php

新しいディレクトリに移動してください。

  1. cd ~/ansible-php/

新しいファイルを作成してansible.cfgと名付け、nanoやお気に入りのテキストエディタで編集のために開きます。

  1. nano ansible.cfg

ansible.cfgファイルに以下をコピーして、[defaults]グループのhostsの値でhostfile構成オプションを追加してください。

[defaults]
hostfile = hosts

このansible.cfgファイルを保存して閉じます。次に、アプリケーションをデプロイするPHP DropletのIPアドレスを含むhostsファイルを作成します。

  1. nano hosts

以下をコピーして、phpのセクションを追加します。your_server_ipをあなたのサーバーのIPアドレスに、sammyをPHP Dropletの事前準備で作成したsudoの非rootユーザーに置き換えてください。

[php]
your_server_ip ansible_ssh_user=sammy

ホストファイルを保存して閉じます。新しいphpグループにpingモジュールを呼び出して、Ansibleがホストに期待通り接続できるかどうかを確認するための簡単なチェックを実行しましょう。

  1. 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という名前の新しいプレイブックを作成してください。

  1. 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オプションを使用するのを忘れないでください。

  1. 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 を編集のために開いてください。

  1. 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

最後に、プレイブックを実行してください。

  1. 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ファイルを編集するために開いてください。

  1. 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

プレイブックを保存して閉じてから、それを実行します。

  1. 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ファイルを編集のために開いてください。

  1. 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

最後に、プレイブックを実行してください。

  1. 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ファイルを編集のために開いてください。

  1. 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

プレイブックを保存して、実行してください。

  1. 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ファイルを編集のために開いてください。

  1. 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

プレイブックを保存して実行します:

  1. 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という新しいファイルを作成します:

  1. 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ファイルを開いてください:

  1. 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

プレイブックを保存して再実行します:

  1. 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つも実行することなく完了しました。

関連記事: