Programação
Entenda para que serve o Docker
Eu falando de Docker?! Pode não parecer, mas sempre tive um pé em infra, não que eu tenha me especializado. Eu consigo montar um servidor web do zero, otimizar até certo ponto. Por ser desenvolvedor, sempre tive problema com “retrabalho”, ter que repetir os mesmos passos do zero, é como uma farpa na minha mente.
Claro, existem muitas soluções pra isso: scripts Ansible e Puppet por exemplo, APIs como a da Digital Ocean ou o Heroku. Muitos serviços nos ajudam, mas localmente, até que ponto o meu ambiente local se assemelha ao de produção? Foi quando me apresentaram o Docker e eu pensei “pronto, é isso!”.
Breve introdução ao Docker e conteinerização
O Docker trabalha com um conceito muito legal de containers, cada “máquina virtual” (note as aspas) é chamada de container. Esses containers são isolados do resto do sistema operacional, mas ao mesmo tempo não são. Eu sei, é confuso, mas eu chego lá.
Quando criamos um container com algum recurso, um Apache por exemplo, o Docker prepara um Apache no “sistema operacional principal” (chamamos o “sistema operacional principal de host“). Quando você cria um segundo container com Apache, você não está subindo um segundo servidor web, mas usando o primeiro. O impacto em performance é quase nulo, já que estamos usando um serviço já existente no host, é diferente do que o Vagrant faz. Não estou dizendo que é superior ou inferior, são propostas diferentes, mas o Docker se encaixa melhor no contexto geral.
As vantagens desta abordagem são imensas, na verdade, sempre que a palavra isolamento está no meio, presto atenção.
Primeiramente, falaremos da escalabilidade. Os containers acabam funcionando como serviços. Você pode “plugar” um serviço a outro, como também, não permitir a comunicação entre eles. Pode escalar sua aplicação, horizontalmente (mais servidores), sem muita dor de cabeça, aliás, seu notebook ou pc vai rodar, exatamente, os mesmos serviços e versões destes serviços que o ambiente de testes, de produção e da sua equipe, tudo alinhado.
Abstração é outro ponto forte. O Docker é exatamente como um container lacrado, o host não sabe o que tem lá dentro ele não sabe o que tem fora. Você trabalha a escalabilidade vertical (recursos do host, como memória, cpu…), sem se preocupar com o serviços dele. O inverso ocorre da mesma forma, você trabalha com o Docker sem se preocupar com os recursos do host. Claro, tudo tem uma linha limite, não dá pra subir uma aplicação com 1 milhão de acessos diários num hot com 500mb de memória. Espero que você tenha entendido o que quero dizer com abstração.
Versionamento e dependências, o que dizer isso? É a grande pedra no sapato de quem trabalha com… bem, com tudo em TI. PHP 7.2 ou 5.6? Node LTS ou Current? E se você usar o Current e o servidor LTS? No fim, você pode acabar usando algum recurso que não teria em produção, “na sua máquina funciona?”… Nada disso, com Docker você pode definir e mudar a versão que quiser e todo mundo vai usar exatamente o que foi definido, joga o arquivo de configuração no git e pronto. Quer ter uma ideia exata de como isso funciona? Dá uma olhada no Docker Hub:
Aqui as versões disponíveis do PHP no Docker Hub, pronto pra usar.
Poderia passar dias escrevendo sobre conceitos e vantagens de utilizar essa “caixa mágica”, mas não vou te cansar mais com isso, vamos ver um pouco de prática.
Docker Compose
Antes de qualquer coisa, darei um exemplo prático, resumindo tudo o que vimos no tópico anterior. Recomendo que você, iniciante em Docker, dê uma olhada no nosso curso de Docker iniciante. Os passos a seguir farão mais sentido, mas isso é uma sugestão. Você pode conseguir entender e replicar os exemplos, mas não ficará tão completo.
Inclusive, se quiser saber como instalar o Docker, recomendo o mesmo curso, o Wesley fala disso, passo a passo no curso.
O Docker Compose é o compositor do Docker, com ele podemos definir como nossos containers vão se comportar, utilizando um arquivo yml. Eu sei que parece complicado,mas vamos ver abaixo como esse arquivo deveria ser, ele deve se chamar docker-compose.yml:
version: "2" services: php: build: ./docker/php volumes: - ./app:/app web: image: "nginx:1.13.8-alpine" volumes: - ./app:/app - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf ports: - "80:80" links: - "php" composer: image: "composer:1.6.1" command: "composer install" volumes: - ./app:/app
Nossa Erik, quanta informação! Na verdade não, são apenas 20 linhas que sobem e configuram um servidor web com Nginx , PHP 7.2 e o Composer do PHP.
A grande sacada aqui são os nós dentro do item services (serviços).
No services, temos 3 serviços (até aqui chamamos de containers, dê uma olhadinha no curso que indiquei, vai te ajudar). O primeiro é o PHP, ele carrega um container com PHP 7.2 do Docker Hub usando um arquivo chamado Dockerfile. Esse arquivo é carregado logo na primeira linha do serviço PHP, alí onde está build: ./docker/php. Na segunda linha informei que um diretório app, no mesmo diretório do docker-compose.yml, estará disponível dentro do container do PHP. Apenas este diretório do host estará visível para o Docker, nada mais. Essa é minha aplicação.
Conteúdo do arquivo Dockerfile:
FROM php:7.2.0-fpm-alpine RUN docker-php-ext-install pdo_mysql
Bacana né? Ele carrega um container com PHP 7.2.0 FPM do Docker Hub na primeira linha e instala a extensão pdo_mysql na segunda linha. Não importa se você está no Windows, Linux, Mac, em ambiente de produção, testes ou desenvolvimento. Todos verão a mesma coisa, o mesmo PHP, mesma versão, mesmas extensões. É lindo de ver.
Agora, tenho outro serviço, o web. Vou pegar parte do docker-compose.yml para facilitar a explicação.
image: "nginx:1.13.8-alpine" volumes: - ./app:/app - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf ports: - "80:80" links: - "php"
Na primeira linha, usei o parâmetro image ao invés do build usado no serviço PHP. Desta vez, linkei direto para uma imagem do host. O legal é que se ela não existir, o Docker vai buscar no Docker Hub e baixar pra gente, exatamente como o Dockerfile do serviço PHP. Viu, você não precisou fazer nada, Nginx instantâneo.
Em volumes, eu indiquei meu diretório app (da minha aplicação), já que o Nginx também precisa “ver” meus arquivos. Criei um arquivo de configuração do Nginx, a ideia é poder alterar isso a partir do host, vou mostrar esse arquivo a seguir.
Na sequência, informei que a porta 80 vai ser mapeada para a 80 do host (a ordem aqui é container primeiro e depois host, ou seja container:host no parâmetro port). Por último, “linkei” o serviço web ao serviço PHP. Agora, meu serviço web pode enxergar e usar o serviço PHP. Isso é bem óbvio, já que vamos usar o php-fpm no nginx.
Por fim, em docker/nginx eu criei um arquivo chamado default.conf com esse conteúdo:
version: "2" services: php: build: ./docker/php volumes: - ./app:/app web: image: "nginx:1.13.8-alpine" volumes: - ./app:/app - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf ports: - "80:80" links: - "php" composer: image: "composer:1.6.1" command: "composer install" volumes: - ./app:/app
Na linha fastcgi_pass php:9000; passamos o endereço do php-fpm, o valor mais comum aqui é fastcgi_pass 127.0.0.1:9000;. Não usei um IP, usei o nome do serviço PHP do Docker Compose. Veja como o serviço web usa o serviço PHP. Assim, eu posso alterar a versão do PHP no meu Dockerfile do serviço PHP, o serviço web não tem ideia de qual versão estamos usando, apenas sabe que, se ele chamar o serviço php a coisa vai andar, isso é muito útil.
Este é o exemplo original que usei no direto ao ponto Ambiente Docker – Nginx + PHP da School of Net. Caro que no vídeo criamos tudo isso do zero e vamos passo a passo até mostrar o aplicativo rodando no navegador. São 27 minutos de aula, impossível reproduzir aqui sem escrever um livro, mas este resumo é o suficiente para você testar na prática “pra que serve o Docker”.
Resumo
Pra que serve o Docker?
O Docker serve para facilitar o dia a dia dos desenvolvedores e profissionais de infra, criando, de forma simplificada, um ambiente onde possam trabalhar alinhados com sua equipe e infraestrutura de servidores e fique simples criar e re-utilizar containers com “serviços” pré-configurados, simples de alterar e que possam ser versionados e mantidos através de simples arquivos de configuração.