Back-End

22 out, 2012

Desenvolvimento PHP usando máquinas virtuais, FastCGI + FPM

Publicidade

Há algum tempo, tenho realizado meus projetos usando Virtual Machines (VMs) e tem sido bem produtivo, além de eu deixar minha máquina principal livre quando não estou desenvolvendo. Outra vantagem é ter à mão o SO de produção, com suas dependências e problemas. Vou passar uma receitinha de bolo, levantando um ambiente LAMP em um Ubuntu, conectado com a máquina principal (o que nos permite centralizar o código e testar em diferentes ambientes).

Para dar uma apimentada na receita, vou utilizar Fastcgi e PHP-FPM (vale a pena ir mais a fundo no assunto, começando pelo site do projeto), além de revelar alguns truques que me são muito úteis no dia-a-dia de desenvolvedor.

Ingredientes

  • Instalador/pacote do VirtualBox (obtida aqui) – foi utilizada a versão 4.1.8.
  • Uma imagem ISO do Ubuntu Server (obtida aqui) – foi utilizada a versão 11.10.
  • Conexão com a Internet.

Preparando a forma

Instale o Virtualbox de acordo com seu sistema operacional principal (:D). Caso use Linux, peço que não utilize os pacotes dos repositórios (obtidas via apt, yum, zypper, slapt…) – eles geralmente utilizam módulos pré-compilados de kernel e estes não são atualizados com tanta frequência, ou ignoram o kernel que você está utilizando, ou ainda te forçam a mudar o kernel que já está instalado para que você possa usar o VBox; para evitar isso, instale os pacotes build-essentials, dkms e kernel-headers (ou os equivalentes para sua distribuição). Se você fizer dessa maneira, o módulo de kernel do virtualbox será compilado de acordo com seu kernel e, caso você o atualize, o dkms se encarregará de recompilar o módulo deixando seu ambiente sempre estável.

Misturando os ingredientes (preparando a VM)

A partir da interface do Virtualbox, clique em New (Ctrl/Cmd + N) para iniciar o Wizard. Acompanhe a sequência de operações:

  • Welcome to the New Virtual Machine Wizard[1] – Next (:D)
  • VM Name and OS Type – dê um nome para sua máquina, selecione Linux em “Operating System” e Ubuntu ou Ubuntu (64 bit) em “Version”, de acordo com a ISO que você baixou e o suporte que seu computador oferece. Next
  • Memory – deixe como está nesse primeiro momento. Next.
  • Virtual Hard Disk – deixe como está (Start-up Disk e Create new hard disk selecionados). Next. Isso abrirá um novo Wizard.
  • Welcome to the virtual disk creation wizard – Mantenha VDI Selecionado. Next.
  • Virtual disk storage detailsDinamically allocated. Next.
  • Virtual disk file location and size – Nomeie seu disco (o default é o nome selecionado para a VM) e selecione o tamanho do HD virtual. Pela seleção que fizemos no item anterior, mesmo que selecionarmos 200 GB, não será alocado esse espaço no seu HD físico – embora eu sempre deixe os 8 GB default, pois utilizaremos o HD físico como storage principal. Next
  • Summary – Create. Finaliza o 2º Wizard.
  • Summary – Create. Finaliza o 1º Wizard.

Temos uma máquina virtual agora. Antes de ir ao próximo passo, vamos configurar sua interface de rede – selecione-a e clique em Settings. Vá na área Network. Em Adapter 1, mude a opção Attached to de NAT para Bridge Adapter; expanda a aba Advanced e, na opção Promiscuous Mode, selecione Allow All. Selecione Ok.

Mandando para o forno (instalando o sistema)

Com dois cliques na máquina criada, vamos inicializá-la. Na primeira vez, como não temos nenhum sistema instalado, o VBox vai pedir que você informe uma mídia para a instalação.

  • First run wizard – Next
  • Select Instalation Media – Em “Media Source,” selecione a imagem do Ubuntu que você baixou anteriormente (.ISO). Next
  • Summary – Start.

Não vou entrar em detalhes sobre a instalação do Ubuntu Server. Existe conteúdo na web muito bom que pode te dar mais informações e/ou tirar dúvidas. Só peço que se atente na hora de dar um nome à maquina (que será seu hostname – e vamos usá-lo depois de a máquina estar devidamente “cozida”) e, quando o instalador te pedir para selecionar dentre alguns templates de máquinas, NÃO (sentiu o enfoque?) selecionar LAMP Server. Conclua a instalação. Ao concluir, a VM irá reiniciar – nesse ponto, teremos uma máquina virtual com Ubuntu Server pronta para uso.

Após retirar do forno (preparação de ambiente)

Durante a instalação, o próprio Ubuntu já realizou a maioria das atualizações – mas não custa fazer um apt-get update; apt-get upgrade. Vamos começar publicando o host dessa máquina na rede (sim, como deixamos ela em bridge, ela tem um ip válido):

# apt-get install openssh-server avahi-daemon

Isso vai instalar o openssh server (sem o qual não poderíamos acessar a máquina, a não ser pela interface da mesma) e o avahi, que, além de outras coisas, usa um recurso de DNS para redes locais. Entre com mais este comando:

# /etc/init.d/avahi-daemon restart

Agora sua VM pode ser acessada externamente pelo <hostname>.local (não falei que usaríamos o hostname?). Tente dar um ping ou conectar por ssh a partir de sua máquina local.

Agora vamos instalar o guest-tools. Caso você já seja usuário do VirtualBox, provavelmente você já fez isso para poder usar os recursos gráficos de sua máquina real na virtual. Uma das vantagens de ter o guest-tools instalado na virtual é usar um filesystem especial, o vboxsf, que permite a você montar um diretório da maquina real na virtual. Sua instalação é simples de um ambiente gráfico, mas na linha de comando (que é só o que temos agora) temos uma trilha diferente a seguir. Antes de qualquer coisa, vamos instalar uns pacotinhos:

# apt-get install make build-essential dkms

Olha o dkms aí de novo, só que agora para a VM. Esses pacotes serão usados para compilar os módulos do guest-tools e manter isso atualizado através de qualquer atualização de kernel que venha a acontecer. Agora, da janela da máquina virtual, clique em Devices e depois em Install Guest Additions. Em seguida, montamos o “CD” de instalação do guest tools:

# mkdir /mnt/cdrom; mount -t iso9660 /dev/cdrom /mnt/cdrom

Executamos o instalador:

#  /mnt/cdrom/VBoxLinuxAdditions.run

Reinicie a máquina virtual. Após isso, da janela da máquina virtual, clique agora em Machine, depois em Settings e vá até a aba Shared Folders (ou clique no ícone de pasta no canto inferior direito da janela). Lá, acesse a opção de Adicionar no lado direito da janela (Add Shared Folder, [Insert]). Em Folder Path, insira o caminho para seu diretório de projetos, ou outro que desejar, para compartilhar com a máquina virtual; em Folder Name, insira o nome para identificarmos o compartilhamento na máquina virtual – utilizaremos o nome Projects; marque também a opção Make Permanent e clique em OK.

Agora vamos mudar o fstab para montar nosso diretório de Projetos real na máquina virtual, sempre. Adicione a seguinte linha em /etc/fstab (considerando que iremos usar o diretório na VM /mnt/Projects):

Projects /mnt/Projects vboxsf rw,defaults 0 0

E monte então o compartilhamento criado anteriormente:

# mkdir /mnt/Projects; mount -a

Agora verifique o diretório. Esse filesystem virtual vai nos permitir acesso instantâneo de leitura e escrita.

Decorando o bolo (agora o PHP de fato)

Vamos instalar um monte de coisas:

# apt-get install php-pear php5-cli php5-curl php5-dbg php5-dev php5-gd php5-mysql php5-sqlite php5-xsl php-apc php5-fpm apache2 apache2-mpm-event apache2-utils libapache2-mod-fastcgi

Isso instalará o PHP da versão mais estável para a versão corrente do Ubuntu (quando fiz, estávamos com o PHP 5.3.10 lançado, e o Ubuntu disponibilizava a 5.3.6), extensões GD, Mysql, SQLite, XSL, APC, PHP-FPM, o Apache, seus módulos utilitários, fastcgi e o MPM event. Ele é um módulo MPM experimental no Apache 2.2, variante do MPM worker. Temos 4 tipos: event, worker e prefork e itk. Na instalação tradicional, é utilizado o prefork, que nos permite utilizar o PHP no apache como módulo nativo – o que nos impede de usar o fastcgi. No modelo que acabamos de instalar, o Apache funcionará muito mais próximo de outros webservers de mercado, como o nginx. Caso não queira arriscar um módulo experimental, troque apache2-mpm-event por apache2-mpm-worker no comando de instalação acima – em uma máquina virtual para uso de pesquisa, você não terá problemas com qualquer um dos dois – ou aguarde o Apache 2.4 e suas novidades.

Sinta-se à vontade para fazer o ajuste fino que precisar (ou que já esteja acostumado a usar) na instalação do PHP (a configuração padrão fica em /etc/php5).

Eu ultimamente tenho usado o seguinte template de caminho para meus projetos:

/var/lib/<vendor>/<project>/<version>/

Onde <vendor> é o dono do projeto, <project> seu nome ou id e <version> é a versão (Dãã). Nesse último item, eu faço um “truquezinho”: não aponto o diretório web diretamente para uma versão, mas para um link simbólico “current” – este sim é mapeado pelo Apache para publicar. Se for necessário realizar uma troca de versão, ou atualização da mesma, eu nem encosto no servidor web. Dando um exemplo de como fica:

/var/lib/duodraco/teste/12.2
/var/lib/duodraco/teste/current -> /var/lib/duodraco/teste/12.2

Vamos configurar um virtualhost no Apache apontando para um diretório web nessa estrutura. Criem um arquivo /etc/apache2/sites-available/test com o seguinte conteúdo (trocando obviamente o endereço pelo que você vai utilizar):

<VirtualHost *:80>
DocumentRoot /var/lib/duodraco/teste/current/web
ServerName dev.local
<Directory /var/lib/duodraco/teste/current/web>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>
FastCgiExternalServer /var/lib/duodraco/teste/current/web/php5.external -host 127.0.0.1:9000
AddHandler php5-fcgi .php
Action php5-fcgi /usr/lib/cgi-bin/php5.external
Alias /usr/lib/cgi-bin/ /var/lib/duodraco/teste/current/web
</VirtualHost>

Note as ultimas 4 linhas dentro da tag VirtualHost. Elas adicionam um manipulador virtual para que o Apache, ao receber requisições que devam ser tratadas pelo PHP, direcione-as para o FastCGI, que no nosso caso é gerenciado pelo FPM. Agora desabilitamos o site default, habilitamos o teste e ativamos o módulo Actions:

# a2dissite default; a2ensite teste; a2enmod actions

Em seguida, reiniciamos o Apache e o fpm:

# service apache2 restart && sudo service php5-fpm restart

Crie e edite o arquivo /var/lib/duodraco/teste/current/web/index.php e insira o seguinte conteúdo:

<?php
echo "Hello World!";//Só para falar que estamos fazendo um hello world mesmo
phpinfo();

Agora acesse http://<hostname>.local/ pela maquina real e voilá. Dê uma olhada na informação gerada pelo phpinfo e note que o Server API é FPM/FastCGI.

Como queremos que isso seja um ambiente de desenvolvimento, vamos instalar o xdebug:

# pear update-channels
# pecl install -a xdebug

O PECL irá baixar e compilar o xdebug para você. No fim da instalação, você deve adicionar o xdebug à configuração do PHP. Para isso, crie o arquivo /etc/php5/conf.d/xdebug.ini e insira o seguinte conteúdo nele:

zend_extension="/usr/lib/php5/20090626/xdebug.so"

Geralmente, os tutoriais dizem para reiniciar o apache… mas estamos usando o FPM, lembram? Basta executar:

# /etc/init.d/php-fpm/restart

Confira novamente o index de nosso projeto e você verá o xdebug no seu devido lugar. Agora faça a sintonia fina dele para seu uso.

Bom, enquanto estávamos preparando a receita, deixamos um compartilhamento ali prontinho para brincarmos, certo? Digamos que em sua “real machine” você tenha um diretório com um projeto “teste2″… o que aconteceria com a nossa virtual machine se executássemos os seguintes comandos?

# ln -s /mnt/Projects/teste2 /var/lib/duodraco/teste/development
# rm /var/lib/duodraco/teste/current
# ln -s /var/lib/duodraco/teste/development /var/lib/duodraco/teste/current

Sim, você tem o seu projeto da maquina real, na virtual, acessível pela real (e por qualquer máquina em sua rede). Utilize seu IDE ou editor preferido no SO principal para editar o projeto e deixe bancos de dados, Apache e outras coisas que ocupam memória e processamento no sandbox da máquina virtual.

Ao terminar uma versão, crie uma cópia, aponte o “current” para essa cópia e mostre a seu cliente, gerente ou mesmo colega de trabalho sem encostar no /etc/hosts da sua máquina real. Quando estiver desenvolvendo novamente, troque o link. Quando não estiver mexendo no projeto, desligue a VM, encerre a IDE e tenha a máquina para mais coisas… nem passa pela minha cabeça que muita gente deixa o MySQL e o Apache da máquina rodando enquanto tenta jogar no computador.

Sei que o artigo ficou meio extenso, mas queria passar um ambiente não tão básico para desenvolvimento – com a apimentada citada. Temos alguns outros truques ainda para falar como git, jenkins, mongodb … e este artigo serve de base para eles. Até o próximo.

PS: Gracias ao Mr @alganet – sem o qual eu não teria páprica para a receita.