Docker para o ambiente de desenvolvimento

William
phpzm
Published in
10 min readFeb 2, 2017

--

Neste artigo não vou me atrever a adentrar no mundo da virtualização ou falar de devops; vou narrar minha jornada. Antes do Docker toda vez que eu iniciava uma instalação nova de um S.O. tinha náuseas só de pensar no trabalho que ia ter para fazer tudo funcionar. Atualmente eu só me preocupo com a banda que vou gastar para baixar as coisas que preciso.

Objetivo deste artigo

Meu ambiente de desenvolvimento é o Ubuntu, meu desktop é o Ubuntu, quando subo uma VPS e tenho a opção de escolher o S.O. vou de Ubuntu Server ou Debian. Os exemplos que vou usar serão todos relacionados a essas plataformas, então, se precisar porte-os para o seu universo.

Ao final do artigo teremos um projeto simples em PHP que usará serviços que não estarão instalados na sua máquina, e, sim, no Docker. Para colocar todos os serviços do projeto para rodar usaremos apenas um comando (`docker-compose up`). Quando eu disse “todos” eu quis dizer servidor web, banco de dados, e outras coisas que você possa vir a precisar.

Primeiro instale o Docker

A documentação é bem clara em relação a todas as etapas para instalar o docker e o docker-compose: https://docs.docker.com/compose/install/. Sendo assim a primeira coisa a fazer é seguir esse passo-a-passo, lendo com calma e atenção que você vai chegar no final com os recursos necessários para usar o docker-compose no terminal.

Se der tudo certo ao final você poderá rodar no seu terminal:

docker -v

No meu Ubuntu 14.04 no final de novembro de 2016 eu fiz os passos abaixo. Note que isso pode variar de acordo com a versão do S.O. e com as versões mais modernas das ferramentas. Por isso recomendo seguir a documentação.

Docker:

$ sudo apt-get install apt-transport-https \ ca-certificates
$ curl -fsSL https://yum.dockerproject.org/gpg | sudo apt-key add -
$ sudo add-apt-repository \ “deb https://apt.dockerproject.org/repo/ \ ubuntu-$(lsb_release -cs) \ main”
$ sudo apt-get update
$ sudo apt-get -y install docker-engine

Docker Compose:

$ curl -L “https://github.com/docker/compose/releases/download/1.9.0/docker-compose-$(uname -s)-$(uname -m)” -o /usr/local/bin/docker-compose
$ chmod +x /usr/local/bin/docker-compose

Depois reiniciei tudo.

E o que é isso tudo?

Você em algum momento já deve ter ouvido falar de virtualização. Virtualização é uma palavra manjada no meio da TI; ela aponta para a técnica de rodar mais de um sistema operacional em um mesmo dispositivo simultaneamente. Dessa forma lançamos mão do uso de máquinas virtuais. Imagine pegar os recursos físicos de um PC, particioná-los utilizando software e distribuir para sistemas operacionais diferentes. É isso o que a virtualização busca.

Virtualizar recursos é muito útil, permite dividir máquinas poderosas em diversas menores economizando espaço e o custo de adquirir muitas máquinas. Graças à essas vantagens uma boa parte da infra-estrutura de TI hoje usa essa tecnologia em algum momento. Uma característica da virtualização é que cada máquina virtual opera com um sistema operacional completo, fazendo com que esse sistema não soubesse que está em um máquina compartilhada com outras.

O fato de ser ter um sistema operacional completo faz com que máquinas virtuais não sejam simples de lidar e exigem muito de quem for mantê-las. Visando simplificar isso outras estratégias de utilizar uma mesma máquina para executar muitas tarefas foram sendo criadas. A que vamos abordar será a que é chamada de conteinerização.

A princípio podemos nos confundir e achar que o Docker é mais uma ferramenta de virtualização, mas não é bem assim. Similar ao que já tradicionalmente conhecemos como VirtualBox, VMWare e cia ele nos permite rodar processos que não estão instalados na nossa máquina, só que ele compartilha o mesmo Kernel da máquina que está atuando como hospedeira. Embora tenhamos tantas opções a conteinerização (técnica usada pelo Docker) tem um ponto que a diferencia das demais que é a possibilidade de particionar um mesmo kernel para rodar vários processos sem que seja necessário iniciar todo um sistema operacional. Sendo assim você não precisa mais repartir os recursos entre sistemas completos, e, pode aplicar esse conceito a fragmentos de sistemas: serviços.

Usando Docker acabamos por ter um ambiente misto onde você usufrui das vantagens que a virtualização oferece e as vantagens de não ter que gerir e orquestrar sistemas inteiros. Acabamos por nos preocupar apenas com nossos contêineres. Um modelo gráfico disso pode ser visto na imagem abaixo que compara as duas abordagens. É possível ver que a virtualização tradicional opera usando vários sistemas operacionais, enquanto que a abordagem de container usa apenas um.

Virtualização versus Conteinerização — Fonte: IBM

Para propiciar os recursos que conversamos acima o Docker acaba por criar um ambiente que conta com recursos como images, containers e volumes. As images são as instalações “puras”, como se fossem ISO’s dos serviços. Os containers são instâncias das images com adaptações e modificações que acontecem conforme vão sendo usados. Já os volumes são opções de armazenamento que podem ser reusadas entre containers.

Deixo uma referência bem legal aqui para a explicação que a própria Docker dá sobre o que é esse tal de container.

Por que Docker Compose?

O Docker Compose é uma abstração do Docker para gerenciar containers. O universo do Docker é longo e extensas são as possibilidades que ele cria. Já o Docker Compose está direcionado a iniciar e parar um pequeno conjunto de serviços que já ficam interligados entre si.

Se você que está chegando aqui está tentando fazer analogias, pense que ao invés de você ter uma VM completa com todo um sistema operacional você pode ter uma forma de rodar apenas os serviços que precisa de forma autônoma; ao invés de você ter uma imagem no Vagrant ou outro virtualizador com um S.O. (que chega a dar boot), você tem um gatilho que levanta e derruba os serviços que usamos para o desenvolvimento de forma totalmente independente.

Ah então é igual Xampp, Lampp?! Não exatamente!

No ecossistema Docker, a máquina que hospeda o serviço chama-se Host, mas os serviços não rodam nela, rodam no container, que é criado a partir da imagem e por ai vai. Para mais detalhes sobre o tema, recomendo o material abaixo.

Mão na massa!

Para começar a usar o Docker você pode baixar imagens do repositório oficial (https://hub.docker.com/), pode criar seu próprio dockerfile e criar sua imagem, pode usar um site que gere o dockerfile para você (https://phpdocker.io/generator) ou pode usar imagens de terceiros.

No caso desse artigo pretendo mostrar exemplos com base na galeria Ambientum.

Acreditando que você já instalou o circo todo, vamos criar uma pasta que será nosso projeto piloto.

Depois de criada a pasta abra o terminal e posicione-o na mesma. Vá no seu editor preferido e crie um arquivo semelhante a esse abaixo colocando o nome dele de “docker-compose.yml” (o nome é importante porque a ferramenta vai usar este nome como padrão, se o nome for diferente você terá que passar o nome do arquivo para o docker-compose toda vez que for usar ele).

O “version” na primeira linha é para controle interno do Docker e acho até que pode ser ignorado nas versões mais novas.

Na linha 3 é inicializada a sessão de serviços (“services”). Logo a seguir na linha 5 damos um nome ao serviço e tratamos de anotar suas características.

  • image: a imagem que será usada; lembra que eu disse que iríamos usar o Ambientum… era a isso que eu me referia;
  • container_name: eu sempre uso o mesmo nome do serviço para não confundir, mas poderia ser diferente. Esse nome é importante porque será usado nas configurações do próprio docker-compose e no seu projeto;
  • volumes: esta seção é muito útil e importante de se compreender. Ela é a ponte de ligação entre o sistemas de arquivos do host e do container. Neste exemplo vamos relacionar a pasta do nosso projeto, o “.” que está a esquerda do “:” com o “/var/www/app/public” (raiz do apache configurada nos fontes do container) que é um diretório que está dentro do container. Note que com esse comando eu poderia sobrescrever arquivos de configuração e pastas de serviços do container com estruturas locais de forma que o container use a pasta local achando que está usando um diretório que está dentro dele;
  • ports: uma outra seção de associação, mas nesse caso de portas. Como o Apache vai subir na porta 8080 (está configurado no container também) e eu quero acessar ele na porta 8090 no meu PC informei “8090:8080”. Ou seja, o que está a esquerda é a configuração do host e a direita do container.

Se você acha que precisa agora fazer muitas configurações a mais está totalmente enganado. Usando o terminal na pasta em criamos esse arquivo, a mesma que estamos usando para criar nosso projeto de teste agora, você já pode executar:

$ docker-compose up

Em alguns casos pode ser preciso usar “sudo” para usar o docker e o docker-compose, caso se depare com a mensagem abaixo passe a usar o comando usando “sudo” (dica do Hermes Autran).

Troubleshooting: problema de permissão

Esse único comando irá baixar a imagem “ambientum/php:7.0-apache”, se você ainda não tiver, inicializar o container com o bind de volume e porta que você configurou e quando parar de aparecer mensagens no terminal você já estará com tudo rodando!

Se você acha que é mentira minha agora crie um arquivo “index.php” nessa pasta com o conteúdo “It works!” (ou outro qualquer) e acesse no seu navegador em “localhost:8090”.

Se quiser não ficar vendo os logs do serviço no terminal você passar usar o parâmetro “-d” ($ docker-compose up -d), mas eu não recomendo muito. Sabe aquele caso do erro 500 que não mostra nada e aquela busca pelos erros como quem procura o Wally? Então, sem “desatachar” o comando do terminal estes erros ficam sendo mostrados bem ai nessa tela.

Mesmo que você rode o docker-compose com o “-d” pode acessar os logs de forma fácil usando o comando $ docker logs -f <container>. No nosso exemplo o container se chama “apache-local.app” (dica do Adalberto Taylor).

Ok, você é exigente e não cai nesses truques baratos, correto?! Quer ver então como vamos usar o MySQL?

Editei uma nova versão do arquivo conforme acima. Nesta nova versão estou introduzindo o serviço do MySQL, destaques para a nova propriedade “links” no serviço do Apache para permitir que ele acesse o serviço MySQL, o volume sobrescrevendo a pasta de arquivos dos bancos do MySQL e a propriedade “environment” com configurações para o banco de dados que será criado automaticamente.

Para usar essa nova versão do arquivo é de bom grado criar essa pasta “mysql” no mesmo diretório que criou o “index.php”.

Neste momento você pode dar um CTRL + C para parar o container que estava rodando (se você usou o parâmetro -d vai precisar dar o comando docker-compose down) e rodar o comando para subir novamente.

$ docker-compose up

Quando o container inicializar ele vai popular a pasta “mysql” que criamos e já poderemos criar um exemplo de conexão usando PDO.

Fiz esse exemplo bobo ai para demonstrar o funcionamento do ecossistema. Note que no DSN da conexão o “host” é o nome do container (no caso “mysql-local.app”) e a porta é a “3306” que é a porta que o container usa e não a porta que foi exposta para o host.

Para acessar a partir do host usando um cliente de banco de dados a configuração muda. Olha o print da minha janela de configuração do MySQL Workbench. Eu usei “127.0.0.1” como “host” e senha de root veio do “docker-compose.yml”. Eu poderia acessar com o usuário criado pelo Compose, então este exemplo é só para demonstrar que é criado um root e que eu posso inclusive criar mais bancos no volume do container usando ele.

Problemas comuns (Troubleshooting)

  • SELinux: Se você é usuário do Fedora ou outra distro que faça uso da ferramenta SELinux pode ser necessário configurar o mesmo para não bloquear as ações do docker. Não se esqueça de parar e iniciar novamente o container depois de fazer as configurações no SELinux.
  • ArchLinux: No Arch (kernel 4.10.8–1–ARCH) você pode atualizar os repositórios usando
    `$ sudo pacman -Syu` e em seguida baixar as ferramentas usando
    `$ sudo pacman -S docker docker-compose`.
    Para gerenciar o serviço (daemon) use o comando
    `$ sudo systemctl start/stop docker.service`
    e de brinde pode usar o
    `$ sudo systemctl enable docker.service` para colocar o docker no boot.

Bom, era só isso que eu tinha para mostrar para vocês mesmo, apresentar minha experiência com docker + docker-compose e espero que este material seja de utilidade para a comunidade de desenvolvimento em geral.

As principais features que a meu ver são necessárias para configurar um ambiente de desenvolvimento estão no texto. Os detalhes sobre as ferramentas podem ser vistos no livro que citei do Rafael Gomes. O Ambientum é mantido pelo pessoal do https://codecasts.com.br/, geralmente na pessoa do sr. Diego Hernandes.

Grande abraço e até a próxima.

--

--

Tem algumas coisas que a gente sabe que vão acontecer. Estas são as que acontecem por acaso. Todo o resto é o que compõe a certeza.