如何:在 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。
  • 创建独角兽初始化脚本:复制提供的配置,但是:

    1. USER 将永远是 vagrant
    2. 我们必须从 APP_ROOT 路径中删除 /home,同时只留下 /$USER/$APP_NAME
    3. 最后,鉴于 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: 复制提供的配置,但是:
    1. 我们将路径更改为 unicorn.sock,因此将路径修改为 server unix:/home/tmp/sockets/unicorn.sock fail_timeout=0;
    2. root 配置行确保将 deploy 替换为 vagrant,生成:root /home/vagrant/APPNAME/public;
    3. 最后,Nginx 可能无法正确找到 Rails 应用程序,因此我们将 proxy_pass 设置为 http://localhost:3000;

由于我们将 unicorn.sock 文件位置更改为 /tmp/ 文件夹中的一个文件夹(每次我们 halt 我们的机器时都会删除该文件夹),我们将不得不设置一些shell provisions 通过 vagrant 确保每次我们为这个项目发出 vagrant up 命令 mkdir /tmp/sockets 是 运行。

只需在 Vagrantfileconfigure 块下添加以下内容即可:

# 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,也在我们的主机。这样我们可以:

  1. 在我们的主机上访问 localhost...
  2. 这将转发到我们主机上的 localhost:8080...
  3. 这将被转发到我们的访客(虚拟)机器上的 localhost:80

最后,我们可以访问我们的应用程序 localhost!

5.1 - 主机到来宾的端口转发

主机是您的物理机,来宾是您的虚拟机。我们要将主机上的 8080 端口转发到来宾上的 80。

  1. 打开你的 Vagrantfile 并找到其中包含 config.vm.network 的行。
  2. 取消注释并编辑它,同时添加另一行,使其类似于:

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 被告知要执行的命令在主机上执行命令。

  1. 通过在与 Vagrantfile 相同的目录中执行以下命令来安装 vagrant-triggersvagrant plugin install vagrant-triggers.
  2. 将以下配置粘贴到 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 映射的链接。

如果您发现本指南有任何问题,请给我发消息,以便我进行调查并在需要时进行修改!

编码愉快,

通关