如何:在 Rails 4 上使用 VirtualBox 运行 Ruby 设置 Vagrant,在 OS X 10.10+ 上设置 Postgres、Unicorn、Nginx 和端口转发
HOW TO: Setup Vagrant with VirtualBox running Ruby on Rails 4, Postgres, Unicorn, Nginx, and port forward on OS X 10.10+
我post将此作为我遇到的资源的汇编,因为那里的指南不适合 Vagrant 提供的虚拟化以及由此可能发生的错误。
因此,我将参考很多 material,因为其他人已经比我更好地解释和格式化它,同时仅替换所述 material 中的步骤,使其在 Vagrant 下工作。
在实际部署环境中链接的资源是足够的(这个post只针对Vagrant):
第 1 步:安装 Vagrant 和 VirtualBox
您可以使用 Homebrew 或来自其各自网站的安装程序,here and here。
通过自制软件:
brew cask install vagrant
brew cask install virtualbox
第 2 步:设置 Vagrant
2.2 - 首先我们添加一个 Vagrant Box
Vagrant boxes 是由 Vagrant 克隆到虚拟机中的图像,我们将使用 Ubuntu repository 中的 Ubuntu 14.04 来创建我们的虚拟机。
vagrant box add ubuntu/trusty64
2.3 - 其次我们初始化我们的 Vagrantfile
Vagrants 的默认虚拟化提供程序是 VirtualBox,因此我们无需在这方面进行任何配置。我们需要做的就是在我们的项目根文件夹中或旁边创建一个 Vagrantfile
。
Vagrantfile
将用作我们虚拟机中 /vagrant
文件夹的 'location marker',因此与我们的 Vagrantfile
相同的文件夹中包含的任何内容都可以访问在我们的虚拟机中。
确保你 cd
到你想要共享目录的任何地方,然后我们需要做的就是 运行 vagrant init
使用我们的 Ubuntu 14.04 图像.
vagrant init ubuntu/trusty64
哒哒!我们现在已准备好在我们的虚拟机中启动和运行。
第 3 步:启动并通过 SSH 连接到我们的虚拟机
要引导然后通过 ssh 进入我们的虚拟机,我们必须与我们的 Vagrantfile
和 运行:
在同一目录中
vagrant up
vagrant ssh
现在我们可以安装 Ruby、Postgres、Rails、Unicorn 和 Nginx。
第 4 步:安装软件包和配置我们的虚拟机
4.1 - 按照 DigitalOcean 的指南在 Rails 上安装 Ruby 和 Ruby,直到到达可选步骤 here。
- 注意: 在
Install rbenv
下务必将文件保留为 .bash_profile
。
4.2 - 在 Ubuntu 14.04.
上安装 Postgresql
更新 apt-get,然后安装 Postgres 及其依赖项:
sudo apt-get update
sudo apt-get install postgresql postgresql-contrib libpq-dev
4.3 - 遵循 DigitalOcean 的 Rails、Unicorn 和 Nginx 部署设置指南,here。
- 注意:请务必参考以下要替换的内容。
- 在第一步之前确保您在共享目录中,这样您就可以从主机访问文件,例如使用 Sublime Text。要访问您的共享目录,请输入
cd /vagrant
.
- 配置 Unicorn: 复制提供的配置,但是 "Unicorn can't store a .sock file on a Virtual Box Shared Folder, so what you'll have to do is modify for the socket [...]" solution at source。感谢 Dave Long。
创建独角兽初始化脚本:复制提供的配置,但是:
USER
将永远是 vagrant
。
- 我们必须从
APP_ROOT
路径中删除 /home
,同时只留下 /$USER/$APP_NAME
。
最后,鉴于 1024 以下的端口在 OS X 上享有特权,我们将不得不强制我们的 Rails 应用程序 运行 在更高的东西上所以,:
- 更改此行:
CMD="cd $APP_ROOT && bundle exec unicorn -c config/unicorn.rb -E $ENV -D"
- 进入这个:
CMD="cd $APP_ROOT && bundle exec unicorn -c config/unicorn.rb -E $ENV -D -l 0.0.0.0:3000"
- 安装和配置 Nginx: 复制提供的配置,但是:
- 我们将路径更改为
unicorn.sock
,因此将路径修改为 server unix:/home/tmp/sockets/unicorn.sock fail_timeout=0;
。
- 在
root
配置行确保将 deploy
替换为 vagrant
,生成:root /home/vagrant/APPNAME/public;
。
- 最后,Nginx 可能无法正确找到 Rails 应用程序,因此我们将
proxy_pass
设置为 http://localhost:3000;
。
由于我们将 unicorn.sock
文件位置更改为 /tmp/ 文件夹中的一个文件夹(每次我们 halt
我们的机器时都会删除该文件夹),我们将不得不设置一些shell provisions 通过 vagrant 确保每次我们为这个项目发出 vagrant up
命令 mkdir /tmp/sockets
是 运行。
只需在 Vagrantfile
的 configure
块下添加以下内容即可:
# Create the /tmp/sockets folder we need every time on startup
config.vm.provision "shell",
inline: "mkdir /tmp/sockets"
现在,我们必须 运行 vagrant up --provision
而不是 vagrant up
每次启动虚拟机时都会为我们创建 /tmp/sockets 文件夹。如果我们不创建此文件夹,Unicorn 将无法启动!
第 5 步:端口转发
此时,如果您在 Vagrantfile 中设置了端口转发,您应该能够在 http://localhost:8080/tasks
上访问您的应用程序。不过,实际上,您永远无法通过末端的端口访问您的应用程序,因此我们需要转发端口并修复此问题。如前所述,Vagrant 无法转发到 1024 以下的端口,因为它们在 OS X 上享有特权。运行 sudo
下的 Vagrant 也无济于事,因为此特权未传递给 VBoxManage 进程 Vagrant生成。
因此,我们会将主机上的端口 8080 转发到虚拟机(来宾)的端口 80。同样,我们会将主机的端口 80 上的所有流量转发到端口 8080,也在我们的主机。这样我们可以:
- 在我们的主机上访问
localhost
...
- 这将转发到我们主机上的
localhost:8080
...
- 这将被转发到我们的访客(虚拟)机器上的
localhost:80
。
最后,我们可以访问我们的应用程序 localhost
!
5.1 - 主机到来宾的端口转发
主机是您的物理机,来宾是您的虚拟机。我们要将主机上的 8080 端口转发到来宾上的 80。
- 打开你的
Vagrantfile
并找到其中包含 config.vm.network
的行。
- 取消注释并编辑它,同时添加另一行,使其类似于:
config.vm.network "forwarded_port", guest: 80, host: 8080
config.vm.network "forwarded_port", guest: 443, host: 8443
您现在已将主机的默认 http 和 https 端口转发到来宾。
5.2 - 端口映射主机的端口
现在我们需要把宿主机的80和443端口映射到宿主机的8080和8443端口上,这样vagrant就可以接了!我们将使用一个名为 vagrant-triggers
的漂亮插件,因为我们不希望这种情况一直发生。我们只有在 运行 设置 Vagrant 实例时才需要它。使用 vagrant-triggers
将允许我们根据 Vagrant 被告知要执行的命令在主机上执行命令。
- 通过在与
Vagrantfile
相同的目录中执行以下命令来安装 vagrant-triggers
:vagrant plugin install vagrant-triggers
.
- 将以下配置粘贴到
configure
块内的 Vagrantfile
中,随心所欲。
config.trigger.after [:provision, :up, :reload] do
system('echo "
rdr pass inet proto tcp from any to any port 80 -> 127.0.0.1 port 8080
rdr pass inet proto tcp from any to any port 443 -> 127.0.0.1 port 8443
" | sudo pfctl -ef - > /dev/null 2>&1; echo "==> Fowarding Ports: 80 -> 8080, 443 -> 8443"')
end
config.trigger.after [:halt, :destroy] do
system("sudo pfctl -ef /etc/pf.conf > /dev/null 2>&1; echo '==> Removing Port Forwarding'")
end
因此,运行ning vagrant up
将设置端口映射,运行ning vagrant halt
将删除它。
您现在可以从 http://localhost/tasks
访问您的应用程序。
希望这篇攻略对大家有所帮助。我不得不经历一些麻烦才能找到有关为什么这在 Vagrant 下不起作用的信息。
非常感谢 DigitalOcean 和这个社区,他们的成员为本指南提供了内容,包括指向 Yosemite 和 Unicorn 套接字配置下的 pfctl
映射的链接。
如果您发现本指南有任何问题,请给我发消息,以便我进行调查并在需要时进行修改!
编码愉快,
通关
我post将此作为我遇到的资源的汇编,因为那里的指南不适合 Vagrant 提供的虚拟化以及由此可能发生的错误。
因此,我将参考很多 material,因为其他人已经比我更好地解释和格式化它,同时仅替换所述 material 中的步骤,使其在 Vagrant 下工作。
在实际部署环境中链接的资源是足够的(这个post只针对Vagrant):
第 1 步:安装 Vagrant 和 VirtualBox
您可以使用 Homebrew 或来自其各自网站的安装程序,here and here。
通过自制软件:
brew cask install vagrant
brew cask install virtualbox
第 2 步:设置 Vagrant
2.2 - 首先我们添加一个 Vagrant Box
Vagrant boxes 是由 Vagrant 克隆到虚拟机中的图像,我们将使用 Ubuntu repository 中的 Ubuntu 14.04 来创建我们的虚拟机。
vagrant box add ubuntu/trusty64
2.3 - 其次我们初始化我们的 Vagrantfile
Vagrants 的默认虚拟化提供程序是 VirtualBox,因此我们无需在这方面进行任何配置。我们需要做的就是在我们的项目根文件夹中或旁边创建一个 Vagrantfile
。
Vagrantfile
将用作我们虚拟机中/vagrant
文件夹的 'location marker',因此与我们的Vagrantfile
相同的文件夹中包含的任何内容都可以访问在我们的虚拟机中。
确保你 cd
到你想要共享目录的任何地方,然后我们需要做的就是 运行 vagrant init
使用我们的 Ubuntu 14.04 图像.
vagrant init ubuntu/trusty64
哒哒!我们现在已准备好在我们的虚拟机中启动和运行。
第 3 步:启动并通过 SSH 连接到我们的虚拟机
要引导然后通过 ssh 进入我们的虚拟机,我们必须与我们的 Vagrantfile
和 运行:
vagrant up
vagrant ssh
现在我们可以安装 Ruby、Postgres、Rails、Unicorn 和 Nginx。
第 4 步:安装软件包和配置我们的虚拟机
4.1 - 按照 DigitalOcean 的指南在 Rails 上安装 Ruby 和 Ruby,直到到达可选步骤 here。
- 注意: 在
Install rbenv
下务必将文件保留为.bash_profile
。
4.2 - 在 Ubuntu 14.04.
上安装 Postgresql更新 apt-get,然后安装 Postgres 及其依赖项:
sudo apt-get update
sudo apt-get install postgresql postgresql-contrib libpq-dev
4.3 - 遵循 DigitalOcean 的 Rails、Unicorn 和 Nginx 部署设置指南,here。
- 注意:请务必参考以下要替换的内容。
- 在第一步之前确保您在共享目录中,这样您就可以从主机访问文件,例如使用 Sublime Text。要访问您的共享目录,请输入
cd /vagrant
. - 配置 Unicorn: 复制提供的配置,但是 "Unicorn can't store a .sock file on a Virtual Box Shared Folder, so what you'll have to do is modify for the socket [...]" solution at source。感谢 Dave Long。
创建独角兽初始化脚本:复制提供的配置,但是:
USER
将永远是vagrant
。- 我们必须从
APP_ROOT
路径中删除/home
,同时只留下/$USER/$APP_NAME
。 最后,鉴于 1024 以下的端口在 OS X 上享有特权,我们将不得不强制我们的 Rails 应用程序 运行 在更高的东西上所以,:
- 更改此行:
CMD="cd $APP_ROOT && bundle exec unicorn -c config/unicorn.rb -E $ENV -D"
- 进入这个:
CMD="cd $APP_ROOT && bundle exec unicorn -c config/unicorn.rb -E $ENV -D -l 0.0.0.0:3000"
- 更改此行:
- 安装和配置 Nginx: 复制提供的配置,但是:
- 我们将路径更改为
unicorn.sock
,因此将路径修改为server unix:/home/tmp/sockets/unicorn.sock fail_timeout=0;
。 - 在
root
配置行确保将deploy
替换为vagrant
,生成:root /home/vagrant/APPNAME/public;
。 - 最后,Nginx 可能无法正确找到 Rails 应用程序,因此我们将
proxy_pass
设置为http://localhost:3000;
。
- 我们将路径更改为
由于我们将 unicorn.sock
文件位置更改为 /tmp/ 文件夹中的一个文件夹(每次我们 halt
我们的机器时都会删除该文件夹),我们将不得不设置一些shell provisions 通过 vagrant 确保每次我们为这个项目发出 vagrant up
命令 mkdir /tmp/sockets
是 运行。
只需在 Vagrantfile
的 configure
块下添加以下内容即可:
# Create the /tmp/sockets folder we need every time on startup
config.vm.provision "shell",
inline: "mkdir /tmp/sockets"
现在,我们必须 运行 vagrant up --provision
而不是 vagrant up
每次启动虚拟机时都会为我们创建 /tmp/sockets 文件夹。如果我们不创建此文件夹,Unicorn 将无法启动!
第 5 步:端口转发
此时,如果您在 Vagrantfile 中设置了端口转发,您应该能够在 http://localhost:8080/tasks
上访问您的应用程序。不过,实际上,您永远无法通过末端的端口访问您的应用程序,因此我们需要转发端口并修复此问题。如前所述,Vagrant 无法转发到 1024 以下的端口,因为它们在 OS X 上享有特权。运行 sudo
下的 Vagrant 也无济于事,因为此特权未传递给 VBoxManage 进程 Vagrant生成。
因此,我们会将主机上的端口 8080 转发到虚拟机(来宾)的端口 80。同样,我们会将主机的端口 80 上的所有流量转发到端口 8080,也在我们的主机。这样我们可以:
- 在我们的主机上访问
localhost
... - 这将转发到我们主机上的
localhost:8080
... - 这将被转发到我们的访客(虚拟)机器上的
localhost:80
。
最后,我们可以访问我们的应用程序 localhost
!
5.1 - 主机到来宾的端口转发
主机是您的物理机,来宾是您的虚拟机。我们要将主机上的 8080 端口转发到来宾上的 80。
- 打开你的
Vagrantfile
并找到其中包含config.vm.network
的行。 - 取消注释并编辑它,同时添加另一行,使其类似于:
config.vm.network "forwarded_port", guest: 80, host: 8080
config.vm.network "forwarded_port", guest: 443, host: 8443
您现在已将主机的默认 http 和 https 端口转发到来宾。
5.2 - 端口映射主机的端口
现在我们需要把宿主机的80和443端口映射到宿主机的8080和8443端口上,这样vagrant就可以接了!我们将使用一个名为 vagrant-triggers
的漂亮插件,因为我们不希望这种情况一直发生。我们只有在 运行 设置 Vagrant 实例时才需要它。使用 vagrant-triggers
将允许我们根据 Vagrant 被告知要执行的命令在主机上执行命令。
- 通过在与
Vagrantfile
相同的目录中执行以下命令来安装vagrant-triggers
:vagrant plugin install vagrant-triggers
. - 将以下配置粘贴到
configure
块内的Vagrantfile
中,随心所欲。
config.trigger.after [:provision, :up, :reload] do
system('echo "
rdr pass inet proto tcp from any to any port 80 -> 127.0.0.1 port 8080
rdr pass inet proto tcp from any to any port 443 -> 127.0.0.1 port 8443
" | sudo pfctl -ef - > /dev/null 2>&1; echo "==> Fowarding Ports: 80 -> 8080, 443 -> 8443"')
end
config.trigger.after [:halt, :destroy] do
system("sudo pfctl -ef /etc/pf.conf > /dev/null 2>&1; echo '==> Removing Port Forwarding'")
end
因此,运行ning vagrant up
将设置端口映射,运行ning vagrant halt
将删除它。
您现在可以从 http://localhost/tasks
访问您的应用程序。
希望这篇攻略对大家有所帮助。我不得不经历一些麻烦才能找到有关为什么这在 Vagrant 下不起作用的信息。
非常感谢 DigitalOcean 和这个社区,他们的成员为本指南提供了内容,包括指向 Yosemite 和 Unicorn 套接字配置下的 pfctl
映射的链接。
如果您发现本指南有任何问题,请给我发消息,以便我进行调查并在需要时进行修改!
编码愉快,
通关