Usando o Vagrant como ambiente de desenvolvimento no Windows

Vagrant O Vagrant é um projeto que permite virtualizar o ambiente de desenvolvimento de forma simples. No caso específico do Windows, você precisava instalar algo como o Cygwin (que convenhamos, não funciona tão bem assim) se quisesse usar alguma ferramenta do Unix.

Com o Vagrant você pode executar máquinas virtuais utilizando o VirtualBox. Estas máquinas virtuais podem ter qualquer configuração e programas instalados e você pode, inclusive, criar a sua própria configuração com muita facilidade. Isso ajuda bastante quando um novo funcionário é contratado, por exemplo. Se todo o seu ambiente de desenvolvimento for baseado em boxes (box é o nome que o Vagrant utilizada para definir cada máquina virtual) personalizados, tudo o que ele precisa fazer é instalar o Vagrant e executar um único comando. Simples assim.

Voltemos ao Windows. Todo mundo que já tentou desenvolver com Ruby/Rails no Windows sabe o quão lento ele é. Não é um pouquinho lento. É muuuuuuuuuuito lento. Em uma das turmas do curso de Ruby on Rails um dos alunos usava Windows. Enquanto todos os que usavam Macs e Linux rodavam 100 testes em 4 segundos, esta mesma suíte de testes demorava mais do que 4 minutos para ser executada no Windows.

Além disso, o Windows é um péssimo sistema operacional para quem precisa trabalhar constantemente na linha de comando. O PowerShell, que é infinitamente melhor que a versão anterior da linha de comando, ainda não chega nem perto de um Bash.

Com o Vagrant você consegue resolver todos estes problemas. No fim das contas, você irá executar uma distribuição Linux.

O fluxo de desenvolvimento com o Vagrant muda um pouco, mas não muito. Você usará a máquina virtual como um terminal. Em vez de abrir o PowerShell, por exemplo, você irá se conectar através de SSH. Uma grande vantagem do Vagrant é que ele compartilha um diretório entre o host (a máquina real, neste caso um Windows) e o guest (a máquina virtual). Qualquer alteração realizada em uma das pontas será imediatamente refletida na outra. Você pode continuar utilizando o seu editor de texto (ou IDE) favorito no Windows, e executar o projeto no Linux. Mais fácil impossível.

Agora que você já sabe como tudo isso funciona, vamos configurar o seu sistema. Para este artigo, utilizei um servidor Windows configurado na Amazon EC2, mas o processo não muda nada para a sua instalação real.

NOTA: Estas dicas também servem para quem trabalha com Linux e Mac, mas não quer configurar as instalações na máquina real. Estou considerando trabalhar desta forma assim que fizer uma nova instalação no meu Macbook Air que deve chegar em breve! :)

Instalando o VirtualBox

O primeiro passo é instalar o VirtualBox. Acesse a página de downloads e baixe a versão própria para o seu sistema operacional. Inicie a instalação, e avance todos os passos como nas imagens abaixo.

Após finalizar a instalação, você poderá instalar o Vagrant.

Instalando o Vagrant

Agora é a vez do Vagrant. Ele pode ser instalado de duas formas diferentes. Se você já possui uma instalação do Ruby em seu sistema operacional, basta instalar a gem vagrant. A outra forma, mais simples, é instalar o binário do Vagrant, que já traz tudo embutido.

Acesse o site do Vagrant e faça o download da versão para o seu sistema operacional. Inicie a instalação, e avance todos os passos como nas imagens abaixo.

Agora, precisamos adicionar um novo box ao Vagrant. Para os cursos de Rails, decidi por criar um box com tudo instalado, para que os alunos não precisem se preocupar em fazer isso manualmente. Este box já vem com uma série de configurações e programas, dentre eles:

Para adicionar o box, abra o seu terminal e execute o comando vagrant box add hellobits http://hellobits.com/vagrant/hellobits.box. Isso pode demorar algum tempo, já que a imagem com 559MB precisará ser baixada.

Antes de iniciar uma nova máquina virtual, você precisa fazer uma coisa: baixar um programa chamado PuTTY, que permitirá a conexão através do SSH. Se você usa Mac ou Linux, pode pular este passo.

Acesse a página de downloads do PuTTy e baixe os programas putty.exe e puttygen.exe. Execute o programa puttygen.exe; nós iremos gerar uma chave privada de SSH que possa ser utilizada no PuTTY.

Criando a chave Privada de SSH com o PuTTYgen

Clique no botão “Load”, selecione o arquivo C:/Users/<seu usuário>/.vagrant.d/insecure_private_key e clique em “Open”.

Criando a chave Privada de SSH com o PuTTYgen

Isso irá carregar a chave privada de SSH utilizada pelo Vagrant.

Criando a chave Privada de SSH com o PuTTYgen

Clique no botão “Save private key”. Uma janela perguntando se você quer continuar sem uma senha irá aparecer. Clique no botão “Yes”.

Criando a chave Privada de SSH com o PuTTYgen

Salve este arquivo com o nome “vagrant.ppk” no mesmo diretório do arquivo “insecure_private_key”.

Criando a chave Privada de SSH com o PuTTYgen

Pronto! Agora podemos criar uma nova máquina virtual.

Iniciando uma nova máquina com o Vagrant

Para iniciar uma nova máquina virtual, volte ao terminal e crie um novo diretório. Eu usei “myapp”, mas prefira algo mais útil como “Projetos”. De dentro deste diretório, execute o comando vagrant init hellobits.

Criando o arquivo de configuração Vagrantfile

Abra o arquivo “Vagrantfile”, gerado com o comando anterior. Para editá-lo como o exemplo abaixo.

Vagrant::Config.run do |config|
  config.vm.box = "hellobits"
  config.vm.box_url = "http://hellobits.com/vagrant/hellobits.box"
  config.vm.forward_port 3000, 3000
end

Este arquivo de configuração é utilizado para iniciar uma nova máquina. Aqui, estamos especificando o nome do box utilizado, e em qual URL ele pode ser encontrado caso ele ainda não tenha sido adicionado. Já a linha config.vm.forward_port 3000, 3000 especifica o número da porta do servidor Rails, que por padrão é iniciado na porta 3000. Essa configuração permite que você acesse o servidor à partir de seu navegador local.

Se quiser, pode criar um arquivo mais completo, que mapeia mais portas, como no exemplo à seguir:

Vagrant::Config.run do |config|
  config.vm.box = "hellobits"
  config.vm.box_url = "http://hellobits.com/vagrant/hellobits.box"

  config.vm.forward_port 1080, 1080   # mailcatcher
  config.vm.forward_port 1234, 1234   # node.js
  config.vm.forward_port 3000, 3000   # rails
  config.vm.forward_port 3306, 3306   # mysql
  config.vm.forward_port 4567, 4567   # sinatra
  config.vm.forward_port 80, 8080     # apache/nginx
  config.vm.forward_port 8888, 8888   # jasmine
  config.vm.forward_port 9292, 9292   # rack
end

Agora, você já pode iniciar o servidor. Isso pode ser feito com o comando vagrant up. Este comando pode demorar um pouco na primeira vez que é executado.

Iniciando o servidor virtual

O próximo passo é acessar o seu servidor por SSH.

Iniciando uma conexão com SSH

Para conectar ao servidor que você acabou de adicionar, vai precisar conectar através de SSH. Para isso, execute o comando vagrant ssh. Infelizmente, este comando, que inicia uma conexão automática com o servidor, não funciona no Windows. Para isso, nós iremos utilizar um programa chamado PuTTY.

Resposta do comando <code>vagrant ssh</code>

Abra o PuTTY. O endereço de conexão é "vagrant@127.0.0.1" e a porta utilizada é a "2222". Perceba que a porta que você precisa conectar pode mudar dependendo de quantas máquinas virtuais você já está executando.

Conectando ao servidor com o PuTTY

Selecione a seção "Connection > SSH > Auth". Clique no botão "Browse" e selecione o arquivo "vagrant.ppk". Se você seguiu todas as instruções corretamente, ele deve ter sido salvo em "C:/Users/<seu usuário>/.vagrant.d/vagrant.ppk".

Conectando ao servidor com o PuTTY

Como você irá utilizar estas configurações constantemente, salve-as. Para isso, volte até a seção "Session", digite um nome no campo "Saved Sessions" e clique no botão "Save".

Salvando as configurações do PuTTY

Para iniciar a conexão, clique no botão "Open", presente na seção "Session" . Se tudo der certo, uma janela perguntando se quer conectar no servidor irá aparecer. Clique no botão "Yes".

Confirmando a conexão com o servidor

Sua conexão com o servidor foi iniciada! Agora, você já pode configurar o Rails.

Acesso ao servidor

Configurando o Ruby on Rails

Para instalar o Ruby on Rails, basta executar o comando gem install rails. Isso instalará o Rails e todas as suas dependências.

Instalando o Rails

Depois de instalado, você poderá criar o seu primeiro app. Para isso, acesse o diretório “/vagrant”. Este diretório é compartilhado entre o servidor virtual e sua máquina. Qualquer alteração realizada em qualquer uma das pontas será imediatamente refletida na outra. Atenção: se você remover qualquer arquivo deste diretório, ele também será imediatamente removido de sua máquina local.

Execute o comando rails new myapp -d mysql para iniciar um novo app configurado para o MySQL.

Gerando um novo app

O MySQL pode ser acessado com o usuário root, sem nenhuma senha.

Para ver como os arquivos são sincronizados, abra o diretório na sua máquina local. Melhor ainda. Nós precisaremos configurar uma coisa antes de podermos iniciar o servidor Rails. Abra o diretório “myapp” em seu editor de texto preferido. Altere o arquivo “Gemfile”, presente na raíz do projeto. Descomente a linha gem 'therubyracer', :platforms => :ruby para ativar esta dependência.

Ativando a dependência therubyracer

Agora, volte ao terminal remoto (aquele iniciado através do PuTTY) e execute o comando bundle install, para instalar esta dependência.

Executando o comando <code>bundle install</code>

Pronto! Seu servidor Rails já pode ser executado. Execute o comando rails s.

Executando o comando <code>rails s</code>

O seu app Rails já está rodando! Para saber se está tudo funcionando corretamente, abra o seu navegador e acesse o endereço http://127.0.0.1:3000. Você deverá ver a página inicial do Rails.

Página inicial do Rails

Alguns comandos úteis

Quando você não quiser mais trabalhar (todo mundo precisa de uma pausa de vez em quando), pode pausar a execução de sua máquina virtual com o comando vagrant suspend. Para reiniciar a máquina virtual, execute o comando vagrant resume. Estes dois comandos permitirão reiniciar a sua máquina virtual no exato ponto onde ela estava antes de ser pausada.

Se você decidir que quer recomeçar um novo ambiente, pode simplesmente remover a máquina virtual existente. Para isso, execute o comando vagrant destroy e inicie uma nova com o comando vagrant up. Os arquivos compartilhados não serão removidos, mas todo o resto sim! Isso inclui dados salvos no banco e arquivos de configuração adicionados no próprio servidor.

E lembre-se! Se você está em um outro sistema operacional como Mac OS X ou Linux, acesse sua máquina virtual com o comando vagrant ssh.

É uma ótima ideia dar uma lida na documentação. Ela é bem completa, com uma leitura fácil, mas está disponível apenas em inglês (o que não deve ser um problema, certo?).

Manutenção de sua máquina virtual

Esta máquina virtual nada mais é que um Ubuntu Linux Server 12.04 LTS 64-bits. Por isso, todas as coisas que você faria normalmente em um Ubuntu Server, podem ser feitas aqui também.

Vez ou outra é bom você atualizar os pacotes. Para fazer isso, execute os comandos abaixo como sudoer (o usuário vagrant não possui senha para executar o comando sudo).

sudo apt-get update
sudo apt-get upgrade
sudo apt-get dist-upgrade
sudo apt-get autoremove
sudo apt-get clean

Sobre o Ruby

O Ruby está instalado através do pacote Debian que mantenho em um repositório da Hellobits. Sempre que uma nova versão é lançada, eu atualizo este pacote. Então, para atualizar para a versão mais recente, basta executar os comandos apt-get.

sudo apt-get update
sudo apt-get upgrade

Se você precisa trabalhar com versões mais antigas, ou até mesmo com mais de uma versão em diferentes projetos, instale o RVM ou rbenv.

Atualizando o VirtualBox e o Guest Additions

Toda vez que você atualizar a versão do VirtualBox, precisará atualizar o VirtualBox Guest Additions, que é o módulo que permite compartilhar diretórios entre sua máquina real e a máquina virtual, dentre outras funcionalidades.

A maneira mais simples de fazer isso é instalando um plugin chamado vagrant-vbguest. Para instalá-lo, execute o comando abaixo:

$ vagrant gem install vagrant-vbguest

Agora, toda vez que sua máquina for iniciada com o comando vagrant up, ele irá verificar se o Guest Additions precisa ser atualizado e, em caso positivo, fará isso automaticamente.

Outras configurações do Vagrant

Existem algumas outras configurações do Vagrant muito interessantes. Por exemplo, para controlar a quantidade de memória que sua máquina virtual terá, não é necessário usar a interface do VirtualBox. Basta adicinar a configuração abaixo ao seu arquivo Vagrantfile que, neste caso, dedica 2GB de memória.

Vagrant::Config.run do |config|
  config.vm.box = "hellobits"

  config.vm.customize [
   "modifyvm", :id,
   "--memory", "2048"
  ]
end

Se você precisa criar links simbólicos (por exemplo, se estiver instalando pacotes com NPM, o gerenciador de dependências do Node.js), precisará da configuração abaixo.

Vagrant::Config.run do |config|
  config.vm.box = "hellobits"

  config.vm.customize [
    "setextradata", :id,
    "VBoxInternal2/SharedFoldersEnableSymlinksCreate/v-root", "1"
  ]
end

Também é possível definir o diretório raíz mapeado pelo Vagrant. Além disso, você também pode mapear outros diretórios que não precisam estar criados relativamente ao arquivo Vagrantfile.

Vagrant::Config.run do |config|
  config.vm.box = "hellobits"

  config.vm.share_folder "v-root", "/Projects"
  config.vm.share_folder "v-repos", "/Repos", "~/projects"
end

Finalmente, uma opção que venho usando em vez de mapear todas as portas que quero deixar disponíveis é definir um IP fixo para a máquina virtual.

Vagrant::Config.run do |config|
  config.vm.box = "hellobits"
  config.vm.network :hostonly, "192.168.33.2"
end

Isso fará com que esta máquina virtual seja acessível através do endereço IP 192.168.33.2. Então, em vez de mapear a porta do Rails, por exemplo, posso simplesmente acessar o endereço http://192.168.33.2:3000. Como este IP não muda, você pode adicionar um hostname ao seu arquivo /etc/hosts ou equivalente (isso deve ser feito no host, ou seja, a sua máquina real). Desse modo, posso acessar a minha máquina virtual através do endereço http://dev:3000, em vez de decorar o endereço IP.

127.0.0.1 localhost
192.168.33.2 dev

Para ver a lista completa de opções que o Vagrant suporta, acesse a documentação. Outras opções podem ser definidas seguindo a API do VirtualBox.

Perguntas frequentes

Qual a senha de root do servidor?

O usuário vagrant é sudoer e não possui senha. Isso significa que você pode executar tarefas que exigem permissões de administrador com o comando sudo [comando] e não será perguntado sobre a senha deste usuário.

Como faço para acessar o MySQL usando uma interface gráfica?

Primeiro, você precisará configurar o MySQL para que ele ouça as conexões originadas por outros endereços IP que não 127.0.0.1. Abra o arquivo "/etc/mysql/my.cnf" e comente a linha que contém a configuração bind-address. Se você está usando o box da Hellobits, isso já vem comentado por padrão.

Agora, execute o comando abaixo para permitir que o usuário root possa conectar nessa máquina.

mysql -u root -e "CREATE USER 'root'@'%'; GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;"

Finalmente, faça o mapeamento da porta 3306 no arquivo Vagrantfile.

Vagrant::Config.run do |config|
  config.vm.box = "hellobits"
  config.vm.forward_port 3306, 3306   # mysql
end

Configure o seu cliente com o host 127.0.0.1 e usuário root, sem senha. Se você está usando a configuração hostonly no Vagrantfile, use o endereço IP que você definiu.

Configurando o Sequel Pro com o Vagrant

Como configuro o arquivo database.yml com o PostgreSQL?

Para usar o PostgreSQL, basta utilizar os dados de conexão abaixo.

defaults: &defaults
  adapter: postgresql
  encoding: unicode
  pool: 5
  username: vagrant
  password:
  min_messages: warning

development:
  <<: *defaults
  database: sample_development

test:
  <<: *defaults
  database: sample_test

production:
  <<: *defaults
  database: sample_production

Estou recebendo um erro "Vagrant cannot forward the specified ports on this VM...". O que está acontecendo?

Este erro significa que uma porta que você está mapeando já está em uso. Este erro acontece frequentemente quando você tenta mapear a porta do MySQL mas ele também está rodando no host. Neste caso, altere o arquivo Vagrantfile, mudando a porta mapeada para uma outra qualquer, ou pare a execução do programa que está usando a porta que você quer mapear.

Vagrant::Config.run do |config|
  config.vm.box = "hellobits"

  # Use the port 3307 for connecting to MySQL.
  config.vm.forward_port 3306, 3307
end

Estou enfrentando uma lentidão muito grande. O que posso fazer?

Às vezes, operações que envolvem o filesystem podem ser muito lentas. Esse problema raramente acontece se você tem SSD, mas pode acontecer esporadicamente. Você pode tentar usar o compartilhamento de diretórios como NFS.

Vagrant::Config.run do |config|
  config.vm.box = "hellobits"
  config.vm.share_folder "v-root", "/vagrant", ".", :nfs => true
end

Próximos passos

Embora pareça um processo complicado, ele é bastante simples. É muito melhor do que configurar o seu ambiente como neste outro artigo que escrevi. E se você usa um outro sistema operacional, dê uma olhada também. Na minha opinião, é muito mais fácil de manter um ambiente coeso, com instalações muito próximas de um servidor real.

Se você pretende ter um box por cada projeto, você pode definir como sua máquina será provisionada. Você pode configurar a sua máquina usando Puppet, Chef ou até mesmo um script shell. A grande vantagem é que os mesmos scripts usados para configurar o servidor de produção podem ser usados em desenvolvimento, e vice-versa.

Se você quer aprender mais sobre Rails, não deixe de conhecer o meu curso de Ruby on Rails. Ele é apresentado nas modalidades presencial e online e, com certeza, irá dar um conhecimento muito bom sobre este framework.