如何部署在Ubuntu 14.04使用Ansible基本PHP应用程序

本教程介绍供应使用Ansible基本PHP应用程序的过程。在本教程的最后的目标是让新的Web服务器,而目标Droplet一个单一的SSH连接或手动运行命令提供一个基本的PHP应用程序。

介绍

本教程介绍使用Ansible提供基本PHP应用程序的过程。 本教程结束时的目标是让您的新Web服务器提供基本PHP应用程序,而无需在目标Droplet上运行单个SSH连接或手动命令。

我们将使用Laravel框架,作为一个例子PHP应用程序,但这些指令可以很容易地修改,以支持其他架构和应用程序,如果你已经有了自己的。

先决条件

对于本教程,我们将使用Ansible在Ubuntu 14.04 Droplet上安装和配置Nginx,PHP和其他服务。 本教程建立在基础知识Ansible,所以如果你是新来Ansible,你可以通过阅读这个基本Ansible教程第一。

要遵循本教程,您需要:

  • 一个Ubuntu 14.04任何大小的Droplet,我们将使用它来配置和部署我们的PHP应用程序。 本机的IP地址将被称为your_server_ip整个教程。

  • 一个Ubuntu 14.04 Droplet将用于Ansible。 这是您将登录的整个本教程的Droplet。

  • Sudo非root用户配置为Droplet。

  • 对于AnsibleDropletSSH密钥授权的PHP部署Droplet,您可以通过以下设置登录本教程你AnsibleDroplet。

第1步 - 安装Ansible

第一步是安装Ansible。 这是很容易通过安装PPA(个人包存档),并与安装Ansible包完成apt

首先,使用添加PPA apt-add-repository的命令。

sudo apt-add-repository ppa:ansible/ansible

一旦完成,更新apt缓存。

sudo apt-get update

最后,安装Ansible。

sudo apt-get install ansible

一旦安装了Ansible,我们将创建一个新的目录,并设置基本配置。 默认情况下,Ansible使用位于主机文件/etc/ansible/hosts ,其中包含所有它管理的服务器。 虽然那个文件在一些用例是罚款,它是全球的,这不是我们想要的。

对于本教程,我们将创建一个本地hosts文件,并使用它。 我们可以通过在我们的工作目录中创建一个新的Ansible配置文件来实现,我们可以使用它来告诉Ansible在同一目录中查找一个hosts文件。

创建一个新目录(我们将在本教程的其余部分使用)。

mkdir ~/ansible-php

移动到新目录。

cd ~/ansible-php/

创建一个新的文件名为ansible.cfg并打开它使用编辑nano或您喜爱的文本编辑器。

nano ansible.cfg

添加在hostfile与价值配置选项hosts将在[defaults]组通过复制下面进入ansible.cfg文件。

ansible.cfg
[defaults]
hostfile = hosts

保存并关闭ansible.cfg文件。 接下来,我们将创建hosts文件,其中将包含PHPDroplet的IP地址,我们将部署我们的应用程序。

nano hosts

复制下面为部分添加php ,更换your_server_ip您的服务器的IP地址和sammy与你在你的PHPDroplet的先决条件创建的Sudo非root用户。

主机
[php]
your_server_ip ansible_ssh_user=sammy

保存并关闭hosts文件。 让我们运行一个简单的检查,以确保Ansible能够通过调用如预期的那样连接到主机ping的新模块php组。

ansible php -m ping

您可能会获得SSH主机身份验证检查,具体取决于您以前是否曾登录过该主机。 ping应该回来一个成功的响应,看起来像这样:

输出端
111.111.111.111 | success >> {
    "changed": false,
    "ping": "pong"
}

Ansible现在已安装和配置; 我们可以继续设置我们的网络服务器。

第2步 - 安装必需的软件包

在这一步中,我们将使用安装和Ansible需要一些系统软件包apt 特别是,我们将安装gitnginxsqlite3mcrypt ,和一对夫妇的php5-*包。

在我们的中添加apt模块安装我们想要的包,我们需要创建一个基本的剧本。 当我们完成教程时,我们将在这本手册上建立。 创建一个名为新剧本php.yml

nano php.yml

粘贴在以下配置中。 前两行指定我们希望使用(主机组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安装软件包。 不要忘记使用--ask-sudo-pass ,如果你的PHPDroplet你的sudo用户需要密码的选项。

ansible-playbook php.yml --ask-sudo-pass

第3步 - 修改系统配置文件

在本节中,我们将修改PHP Droplet上的一些系统配置文件。 最重要的配置选项来改变(除了Nginx的的文件,这将在后续步骤中被覆盖)是cgi.fix_pathinfo在选项php5-fpm ,因为默认值是一个安全隐患。

我们先解释所有我们要添加到该文件中的部分,则包括整个php.yml供您复制并粘贴在文件。

lineinfile模块可以用来确保文件中的配置值与我们期望的完全一致。 这可以使用一个通用的做正则表达式这样Ansible能理解大多数形式的参数很可能是。我们还需要重新启动php5-fpmnginx ,以确保更改生效,所以我们需要在两个处理程序添加还有,在一个新的handlers部分。 处理程序是完美的,因为它们只有在任务更改时触发。 他们也在剧本的结尾运行,所以多个任务可以调用相同的处理程序,它只会运行一次。

执行上述操作的部分将如下所示:

  - 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,防止错误php5-fpm从与正在重新启动service模块,我们在处理用过。

直到补丁发布之后,你可以解决这个问题,通过改变restart php5-fpm从使用handler service命令使用shell命令,如下所示:

    - 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

Droplet现在已安装所有必需的软件包,并且已设置好基本配置并准备就绪。

第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模块将存储库克隆到我们的Droplet上。 这个过程很简单,因为所有我们通常需要一个git clone命令是源代码库。 在这种情况下,我们也将定义目标,并且告诉Ansible如果它已经通过将存在于未更新资源库update=no 因为我们使用Laravel,我们将使用Git仓库URL是https://github.com/laravel/laravel.git

但是,我们需要运行任务为www-data的用户,以确保权限正确。 要做到这一点,我们可以告诉Ansible为使用特定的用户身份运行命令sudo 最后的任务将如下所示:

- 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-库,你可以添加accept_hostkey=yes ,以防止SSH主机验证从挂的任务。

和以前一样,打开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有一个create-project的安装所有需要的依赖,然后运行在定义该项目创建步骤的命令post-create-project-cmd的部分composer.json文件。 这是确保应用程序正确设置首次使用的最佳方法。

我们可以使用下面的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的命令。 我们还需要添加optimize_autoloader=no参数,因为该标志没有被支持create-project命令。 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的任务,然后检查内的那些结果composer create-project任务。 如果git clone任务改变 ,那么我们运行composer create-project ,如果没有,那就跳过。

注:似乎有在Ansible的某些版本的bug composer模块,并且可以输出,而不是确定改变 ,因为它忽略了脚本,即使安装了不依赖被处决。

打开php.yml文件进行编辑。

nano php.yml

找到git clone任务。 添加register选项的任务的结果保存到了cloned变量,就像这样:

- 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

现在,Composer将停止改变APP_KEY每次运行的时间。

第6步 - 更新环境变量

在这一步中,我们将更新我们的应用程序的环境变量。

Laravel带有一个默认.env这台文件APP_ENVlocalAPP_DEBUGtrue 我们希望交换他们productionfalse分别。 这可以简单地用做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

在本节中,我们将配置一个Nginx来为PHP应用程序提供服务。

如果你现在访问您的Droplet在你的网页浏览器(如http:// your_server_ip / ),你会看到Nginx的默认页面,而不是Laravel新的项目页面。 这是因为我们还需要配置我们的Nginx Web服务器,用于为这些应用程序/var/www/laravel/public目录。 要做到这一点,我们需要更新我们的那个目录Nginx的默认配置,并添加支持php-fpm ,因此它可以处理PHP脚本。

创建一个名为新文件nginx.conf

nano nginx.conf

将该服务器块保存在该文件中。 您可以检查出的第4步本教程中有关此Nginx的配置的详细信息; 下面的修改规定,其中Laravel公开目录,并确保Nginx的使用,我们已经在定义的主机名hosts文件的server_nameinventory_hostname变量。

nginx.conf
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将复制一个或多个文件跨越而不做任何改变 ,而template拷贝一个文件,并解决文件中的所有变量。 因为我们已经使用{{ inventory_hostname }}我们的配置文件中,我们使用template模块,因此被分解成,我们在使用的IP地址hosts文件。 这样,我们不需要硬编码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文件现在应该是这样的:

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如何工作的完美,你不会总是在开放源代码项目与开放存储库。 这意味着你将需要验证git clone与您的私人资料库中的第3步。 这可以很容易地使用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

这应该允许服务器正确地认证和部署您的应用程序。


你刚刚在基于Ubuntu的Nginx Web服务器上部署了一个基本的PHP应用程序,使用Composer来管理依赖项! 所有这一切都已经完成,无需直接登录到您的PHP Droplet并运行一个手动命令。