使用 Ansible 和 Vagrant 构建 Rails 开发环境(Ubuntu + rbenv + MySQL5.6 + node.js)

版本和源码存储库

versionansible 1.9.1Vagrant 1.7.2VirtualBox 4.3.28

本文只包含了主要的来源。如需查看所有来源,请参考下面的存储库。

    https://github.com/katsuhiko/template-rails-ansible

通过 Ansible 构建的服务器应用的每个版本。

versionUbuntu 14.04.2 LTSruby 2.2.2p95 (rbenv)mysql 5.6.19Rails 4.2.3Bundler 1.10.5nodejs 0.12.5npm 2.11.2bower 1.4.1grunt-cli 0.1.13

总之

通过使用Ansible,我创建了一个Rails开发环境的模板。
我曾经犹豫是否应该使用Docker来构建,但我无法理解为什么应该将Docker作为展开到每个人的本地环境的方式。
我将要开始学习如何在Docker中构建开发环境。

这次使用的是Ubuntu(Vagrant + VirtualBox)来创建,而不是Amazon Linux。

rbenv 和 ruby 的安装

我参考了这个。
由于Ansible没有提供rbenv模块,所以我们将使用shell:和command:来完成。
由于Ansible有很多模块,所以可能会在将来提供rbenv模块。那样的话,我们可以更清晰地编写。

我了解到了一个名为ignore_errors的参数。
Ansible在出现错误时会停止执行,但使用这个参数可以忽略错误。
控制台上会以红色文字显示”failed:…”,下面会显示”…ignoring”。
虽然没有问题,但对于显示”failed”我有些在意。
如果有不使用ignore_errors的方法,我认为最好使用该方法。

---
- name: Install dependencies for rbenv
  apt: name={{ item }} state=latest
  with_items:
    - git

- name: Install rbenv
  sudo: yes
  sudo_user: "{{ rbenv_user }}"
  git: repo=https://github.com/sstephenson/rbenv.git dest=~/.rbenv

- name: Add ~.rbenv/bin to PATH
  sudo: yes
  sudo_user: "{{ rbenv_user }}"
  lineinfile: >
    dest="~/.profile"
    line="export PATH=$HOME/.rbenv/bin:$PATH"

- name: Eval rbenv init in ~/.profile
  sudo: yes
  sudo_user: "{{ rbenv_user }}"
  lineinfile: >
    dest="~/.profile"
    line='eval "$(rbenv init -)"'

- name: Install dependencies for ruby-build (see. https://github.com/sstephenson/ruby-build/wiki)
  apt: name={{ item }} state=latest
  with_items:
    - autoconf
    - bison
    - build-essential
    - libssl-dev
    - libyaml-dev
    - libreadline6-dev
    - zlib1g-dev
    - libncurses5-dev
    - libffi-dev
    - libgdbm3
    - libgdbm-dev

- name: Install ruby-build as rbenv plugin
  sudo: yes
  sudo_user: "{{ rbenv_user }}"
  git: repo=https://github.com/sstephenson/ruby-build.git dest=~/.rbenv/plugins/ruby-build

- name: Check if version is installed ruby
  shell: "sudo -iu {{ rbenv_user }} rbenv versions | grep {{ rbenv_ruby_version }}"
  register: rbenv_check_install
  changed_when: False
  ignore_errors: yes

- name: Install ruby
  command: "sudo -iu {{ rbenv_user }} rbenv install {{ rbenv_ruby_version }}"
  when: rbenv_check_install|failed

- name: Check if version is the default ruby version
  shell: "sudo -iu {{ rbenv_user }} rbenv version | grep {{ rbenv_ruby_version }}"
  register: rbenv_check_default
  changed_when: False
  ignore_errors: yes

- name: Set default ruby version
  command: "sudo -iu {{ rbenv_user }} rbenv global {{ rbenv_ruby_version }}"
  when: rbenv_check_default|failed

安装mysql

我遇到了以下错误,很苦恼。

invoke-rc.d: initscript mysql, action "start" failed.
dpkg: error processing package mysql-server-5.6 (--configure):
 subprocess installed post-installation script returned error exit status 1
Errors were encountered while processing:
 mysql-server-5.6
E: Sub-process /usr/bin/dpkg returned an error code (1)

由于虚拟环境内存不足,导致发生错误。我们确认如果分配超过1G的内存,可以避免错误发生。有关Vagrant文件的详细说明会另外提供。

为了使主机能够连接到 MySQL,我正在取消根据 IP 地址进行限制。这是只在本地开发环境运行时才需要的设置。请确保绝对不要在生产环境中使用这样的设置。

---
- name: Install mysql
  apt: name={{ item }} state=latest
  with_items:
    - mysql-server-5.6
    - python-mysqldb

- name: Set mysql service to start on boot
  service: name=mysql state=started enabled=true

- name: Put my-develop.cnf
  template: src=my-develop.cnf.j2 dest=/etc/mysql/conf.d/my-develop.cnf backup=true mode=0644
  notify: restart mysql

- name: Set the root privileges
  mysql_user:
    user: root
    host: "{{ item }}"
    password: ""
  with_items:
   - "%"
   - 127.0.0.1
   - ::1
   - localhost

以下的模板配置是为了禁止外部连接的本地环境而设定的。这是在生产环境绝对不允许的配置。
通过将配置文件放置在conf.d文件夹下,可以实现覆盖,这样就可以在不修改my.cnf的情况下进行配置更改。
如果要增加要覆盖的配置内容,我们计划对配置信息进行变量化。

# {{ ansible_managed }}

[mysqld]
bind-address = 0.0.0.0

安装 node.js

因为经常使用JavaScript开发工具,所以我会安装node.js,虽然therubyracer也可以使用。

在下载设置用的shell之后,Node.js是一种需要执行的类型。使用模块的shell,在每次执行ansible时都会被判断为修改过的,这是需要改进的地方,但目前还没有想到好的方法。

---
- name: Download setup shell for nodejs
  get_url: url="https://deb.nodesource.com/setup_0.12" dest="/tmp/setup_node.sh" mode=0755

- name: Setup nodejs
  shell: /tmp/setup_node.sh

- name: Install nodejs
  apt: name=nodejs state=latest

安装开发工具

对于 rbenv 的 gem 安装方式,我认为目前(2015.06.28)这种方式是最好的。
虽然也有通过 shell: 或者 command: 来使用模块的方式,但是使用 gem: 模块可以更简洁地书写。

---
- name: Install mysql
  apt: name={{ item }} state=latest
  with_items:
    - libmysqld-dev

- name: Install rails and bundler
  sudo_user: "{{ rbenv_user }}"
  gem: name={{ item }} executable=.rbenv/shims/gem user_install=False
  with_items:
    - rails
    - bundler

- name: Install javascript tools
  npm: name={{ item }} state=latest global=yes
  with_items:
    - bower
    - grunt-cli

“Vagrant和Ansible的文件”

由于这次将roles位置移动到ansible目录下,因此正在ansible.cfg中更改路径。

[defaults]
roles_path = ./ansible/roles/

playbook很简单。它只是调用每个角色。

(playbook非常简单,它只是调用每个角色。)

---
- name: Build a Rails development environment
  hosts: all
  sudo: yes
  sudo_user: root

  roles:
    - apt-upgrade
    - rbenv
    - mysql
    - nodejs
    - env

以下是一个 Vagrant 文件。
为了避免 MySQL5.6 在启动时出现错误,我将内存设置为 1G(vb.memory = “1024”)。
除此之外,没有进行其他特殊的设置。

在2015年7月12日开发过程中发现MySQL进程崩溃的问题。通过将内存增加至2G(vb.memory = “2048”),进一步进行了修改,以便能够稳定地进行开发工作。

2015年07月25日,我们添加了一个设置,用于将虚拟环境的时间与主机同步。

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure(2) do |config|

  config.vm.box = "ubuntu/trusty64"

  config.vm.network "forwarded_port", guest: 3000, host: 3000
  config.vm.network "private_network", ip: "192.168.33.20"

  config.vm.synced_folder "../", "/home/vagrant/projects", type: "nfs"

  config.vm.provider "virtualbox" do |vb|
    # Customize the amount of memory on the VM:
    vb.memory = "2048"
    # Set the time to HOST
    vb.customize ["setextradata", :id, "VBoxInternal/Devices/VMMDev/0/Config/GetHostTimeDisabled", 0]
  end

  config.vm.provision "ansible" do |ansible|
    ansible.playbook = "develop.yml"
  end
end

执行方式

安装VirtualBox、Vagrant和Ansible,然后输入以下命令即可搭建开发环境。

$ git clone https://github.com/katsuhiko/template-rails-ansible.git
$ cd template-rails-ansible
$ vagrant up

想法或感受

通过查找和参考Ansible Galaxy,我渐渐适应了制作流程。这次安装rbenv是我学到最多的。

由於沒有將變量整體化,每個角色無法重複使用。我們希望在此基礎上進行改進,實現可重複使用。

我在Mac上测试了操作。我尚未尝试在Windows上运行。
如果您希望在Windows上运行,与其在Windows上安装Ansible,可能在虚拟环境中运行Ansible会更容易一些。

Ansible不相关,但关于Windows文件共享问题,可以参考这个网站:http://tech.respect-pal.jp/vagrant-synced_folder-type/,它似乎很有用。

广告
将在 10 秒后关闭
bannerAds