使用 ansible 将自定义 LAMP 项目包装到 Vagrant 中





5.00/5 (2投票s)
作为一名合同软件开发人员,我时不时会被要求审计 LAMP 项目。由于项目配置各不相同,我使用所谓的“伞形存储库环境”,它允许我将此类项目打包到可重用的 vagrant 环境中,而无需修改被审计项目的 c
背景
作为一名合同软件开发人员,我时不时会被要求审计 LAMP 项目。由于项目配置各不相同,我使用所谓的“伞形存储库环境”,它允许我将此类项目打包到可重用的 vagrant 环境中,而无需修改被审计项目的代码库本身。
让我与您分享这种方法。
工具很简单:Oracle Virtual Box、带有几个附加插件的 Vagrant、Git、“Ansible Developer recipes”项目集合。Windows 也支持,如果您安装了 Git For Windows(前身为 MSysGit)。Vagrant box 使用 Ansible 进行配置,因为此配置工具的运行依赖性最少。
需要解决的挑战
- 在本地机器上配置 vagrant 环境
- 使用 LAMP 堆栈配置虚拟机操作系统(我通常使用 Ubuntu 14.04 LTS 发行版)
- 将虚拟机项目签出到工作区并映射到 vagrant
- 根据虚拟机项目的要求配置虚拟机操作系统
- 确保可以从本地机器访问虚拟机项目
- 完成您的工作
准备 vagrant 环境
有大量的 vagrant 插件。其中一些非常方便。我通常会使用三个插件与 vagrant 一起使用
- vagrant-vbguest:同步虚拟机内部的 guest additions 版本与主 Oracle VirtualBox 版本。这有助于防止共享文件夹出现随机问题。
- vagrant-hostsupdater:自动更新主机文件,其中包含使用的开发别名。重要提示:此插件会请求您提供特权访问权限才能写入 /etc/hosts。
- vagrant-auto_network:此插件会注册一个内部地址范围,并为每个连续的请求分配唯一的 IP 地址,从而使网络配置完全自动化。它比运行 DNS 服务器轻量得多,并且隐藏了手动分配地址的底层工作。
有了上述插件,我的 Vagrantfile 通常包含:添加到 /etc/hosts 的开发网站的别名 + 我更喜欢所有 Vagrant box 都具有相同的 IP 地址子网。
config.vm.hostname = "www.local.dev" config.hostsupdater.aliases = ["alias.local.dev", "alias2.local.dev"] config.vm.network :private_network, :auto_network => true
我最喜欢的:坚持使用 33.* 子网/p>
AutoNetwork.default_pool = "192.168.33.0/24"
存储库中提供的 init_vagrant.sh 会安装提到的插件。
在 Vagrant 中获取 LAMP
为了在 vagrant 中配置 LAMP 堆栈,我使用 Ansible provisioner 和一套 provisioning recipes。
让我们看看 deployment/vagrant.yml 部分
vars: ... mysql_root_user: root mysql_root_password: devroot apache_mode: prefork # use prefork or worker variables java_version: 8 mailhog_version: 0.1.6 mongo_version: 3 nodejs_version: "0.12" # 0.10 0.12 php_family: default # 5.4 | 5.5 | 5.6 | default php_xdebug_version: 2.3.3 ... php_extensions: - { name: "php5-curl" } - { name: "php5-xsl" } - { name: "php5-memcache" } - { name: "php5-memcached" } ... tasks: # MySQL 5.5 - include: "{{root_dir}}/tasks_mysql.yml" # apache prefork|worker - include: "{{root_dir}}/tasks_apache.yml" - include: "{{root_dir}}/tasks_php_apt_switchversion.yml" # php 5.5 for apache - include: "{{root_dir}}/tasks_php_apache.yml" # node 0.12.* - include: "{{root_dir}}/tasks_nodejs.yml" # installs memcached service - include: "{{root_dir}}/tasks_memcached.yml" # Installs custom php extensions - include: "./tasks_phpextensions.yml" # (re)imports databases from db folder - include: "{{root_dir}}/vagrant/tasks_vagrant_import_mysqldb_databag.yml" # register apache websites on vagrant - include: "{{root_dir}}/vagrant/tasks_vagrant_apache2_devsites.yml"
这会安装典型的 LAMP 堆栈:Apache 2.4 和 PHP 5.5(或 5.4 或 5.6,取决于 php_family 设置)。此外,还会安装 composer 和 bower 工具。Gulp、grunt 也可用。如果我需要更具体的版本设置,我在这里进行调整。
将虚拟机项目放入 vagrant
为了将项目放入 vagrant,让我们将它们签出到 public 文件夹。然后将 Public 文件夹映射到 vagrant box 中的 /vagrant/public。由于一些权限限制,我们将文件夹映射为 777 访问权限,文件映射为 666。
c.vm.synced_folder ".", "/vagrant", mount_options: ['dmode=777','fmode=666']
通常虚拟机项目托管在自己的存储库中。为了在这种情况下加快签出速度,引入了一个名为 .projmodules 的特殊文件。格式与 gitmodules 文件格式兼容,通常看起来像项目定义系列
[submodule "public/ansible_developer_recipes"] path = public/ansible_developer_recipes url = git@github.com:Voronenko/ansible-developer_recipes.git
每个子项目将克隆到*path*,使用存储库地址*url*
存储库中提供的 init.sh 会安装或重新安装虚拟机项目。
覆盖虚拟机项目的配置。
这可能非常棘手。我的建议是,将需要用于与 vagrant 配合使用的文件保留在 local/ 子文件夹下。例如,如果虚拟机项目在 public/proj1/config/ 中有配置,我们可以在 local/proj1/config/local_config_file_adjusted_for_vagrant.php 中进行覆盖;在这种情况下,调整代码库以在 vagrant 下工作就像将 local 文件夹的内容复制到 public 文件夹一样简单。如果虚拟机项目的架构允许使用环境或基于开发的配置,那是最好的情况。
例如,我通常有一个 vagrant-tools 项目,其中包含一些小的 PHP 帮助程序来检查 vagrant box 状态(如 Adminer、memcache.php 工具)。
使本地机器可以访问虚拟机项目。
看看 vagrant.yml 中的以下部分
vagrant_lvh_sites: - { type: "web", # WSGI & LAMP sites supported name: "tools", # Name of the dev website path: "/vagrant/public/vagrant-tools", # Path to site home folder # Provide custom template, if builtin is not good # template: "{{playbook_dir}}/files/apache2/website.yml", aliases: [ "tools.vagrant.dev" ] # These will be additional aliases to <<name>>.lvh.me # These lines will be added to website configuration file. vhost_overrides: ["SetEnv no-gzip 1", "RequestHeader unset Accept-Encoding"] } </name>
配置变量*vagrant_lvh_sites*包含需要在 Vagrant 中配置的站点列表。让我指导您完成参数:- type:可以是 web 或 wsgi - 指定使用哪个 vhost 模板。'web' 适用于大多数 lamp 项目。- name:唯一的字母数字站点名称。站点将通过名称 <site name="">.lvh.me 访问- path:站点存储库根文件夹的路径- dest:可选,如果存储库根文件夹不是网站根目录。在此指定到 Web 根目录的相对路径- template:可选,如果默认的 apache 虚拟主机模板不适合您的需求,您可以在此处覆盖它- aliases:可选,域名数组。将用作虚拟主机别名。适用于您计划在 .dev 域上访问 vagrant-domain- vhost_overrides:可选,字符串数组,Apache 配置列表将注入到 Apache vhost 模板中。
<site name="">.lvh.me 技巧:*.lvh.me 始终解析到 127.0.0.1;这允许开发人员在 vagrant 和开发人员的本地机器上使用相同的域名。优点 - 端口转发效果极佳。您可以实现此效果:通过导航到 website.lvh.me,您可以访问在 vagrant 上托管和配置的网站。
导入 mysql 数据库转储
有两种方法
- 选项 A:vagrant 连接到您本地计算机/网络上运行的 mysql。这是最简单的方法,在这种情况下,无需在 Vagrant 中安装 mysql。
- 选项 B:mysql 安装在 vagrant 中,我们需要一种方法来导入数据库。
为了在 vagrant 中运行 mysql:将您的 sql 转储文件放在 databag/db/*<database name=""><database dump="">.sql 下;例如,databag/db/website/dump.sql
Provisioning recipe 会将每个可用的数据库转储导入为一个新数据库,假设文件夹名称等于数据库名称。如果 .nodbs 标志文件位于 databag/db 根目录下,则会跳过导入,以防止意外覆盖数据库。
下面的脚本可以做到这一点
#!/bin/sh
HOMEDIR=${PWD}
if [ -f .nodbs ] ; then
echo ".nodbs flag present, db import skipped";
exit 0
fi
for d in */ ; do
DBNAME="$(echo $d | cut -d '=' -f 2 | sed 's/\/$//')"
echo "IMPORTING DB: $DBNAME"
cd "$HOMEDIR/$DBNAME"
mysql -u{{mysql_root_user}} -p{{mysql_root_password}} -e "drop database if exists $DBNAME"
mysql -u{{mysql_root_user}} -p{{mysql_root_password}} -e "create database if not exists $DBNAME CHARACTER SET utf8 COLLATE utf8_general_ci"
last_dump=$(find ./*.sql -type f -exec stat -c "%n" {} + | sort -r | head -n1)
mysql -u{{mysql_root_user}} -p{{mysql_root_password}} $DBNAME< $last_dump
done
touch "$HOMEDIR/.nodbs"
故障排除邮件
通常网站会发送邮件。为了调试这部分,我通常使用 mailhog。这是一个带有 WebUI 界面的 SMTP 调试工具,也适用于自动测试。项目网站:https://github.com/mailhog/MailHog
调试
出于某种原因,这通常会引起困难。XDebug 安装在 lamp box 中。它被配置为轮询回原始主机,所以在大多数情况下,您只需要监听传入的调试连接(phpstorm 中的绿色电话)。此外,您还需要一个书签小工具或类似 XDebug Helper 的扩展来开启调试会话。
vagrant 中的站点可用
- 在 lvh.me 域上,端口 9080(如果您使用的是 Windows 或特权用户 - 您甚至可以将 80 映射到 80)
- 在 vagrant.dev 域上,端口 80
使用 phpstorm 进行调试的典型步骤包括
-
配置解释器(您可以使用本地或远程解释器)。PHPStorm 9.0.2 会自动检测 vagrant。
-
开启监听调试连接(phpstorm)+ 确保在浏览器中设置调试会话
-
在代码中设置断点并实际调试。注意:lamp-box 存储库的根目录映射到 /vagrant/
代码实战
代码可从存储库下载 https://github.com/Voronenko/lamp-box
准备
签出或 fork 存储库。运行 ./init_vagrant.sh 来安装 vagrant 插件(如果您还没有的话)。
调整 .projmodules 以包含您将要打包的项目存储库。如有必要,实现 ansible recipe 以配置一些超出安装 php 扩展的项目特定环境。
运行 ./init.sh 来克隆必要的项目存储库。不要删除 "public/ansible_developer_recipes" 项目,因为它对环境设置是必需的。
查看 deployment/vagrant.yml 以确保它包含您计划安装的所有内容。
配置环境
运行 vagrant up 并保持耐心。您正在配置一个新的 box,所以可能需要一些时间。速度取决于您的互联网连接。在极少数情况下,配置可能会中断。在这种情况下,请使用 vagrant provision 命令手动重新配置。
最后您应该看到类似这样的内容
PLAY RECAP ******************************************************************** default : ok=46 changed=16 unreachable=0 failed=0
此时,您将拥有额外的帮助程序,并且希望有一个完全可用的虚拟机站点
- Mailhog Web UI 界面,地址为 https://:9025/ 或 http://tools.vagrant.dev:8025/
- PHPMyAdmin Web UI:在每个站点的 /phpmyadmin/ 子文件夹下。使用 root / devroot 登录。(您还记得,您的项目 dbs 在初始配置时会自动导入)
- WebGrind profiler:在每个站点的 /webgrind/ 子文件夹下。
- 已配置的调试器
在 vagrant box 启动时定期配置
默认情况下,provisioners 只运行一次,除非您使用 vagrant provision 强制执行它们。很多时候您可能需要每次 vagrant up 运行时执行一些 recipes。幸运的是,这也可以通过 ansible 实现:添加带有 run:"always" 修饰符的 provision 步骤。在下面的示例中,只有标记为 update 的任务会被执行。这允许跳过原始 provision 的大部分内容。
c.vm.provision "ansible_update", type: "ansible", run: "always" do |ansible| ansible.playbook = "./deployment/vagrant.yml" ansible.tags = "update" end
关注点
每个人都有自己构建世界上最好的 Web 开发环境的经验。最好的环境是适合您需求的。我更喜欢在我的工作 PC 上只安装最少的软件,所以我广泛采用 Vagrant 和 ESXi 进行虚拟化。目标是有一个健壮的方法来在我的主机上运行多个项目而不会发生干扰。通过 ESZXi 和 Vagrant,我可以成功实现这一目标。