Criando serviços com o Docker de forma simplificada
A arquitetura do Docker
O Docker é uma tecnologia de virtualização, ou seja, possiblita que criemos ambientes independentes e isolados do sistema operacional hospedeiro. Diferentemente das máquinas virtuais tradicionais, o Docker cria a sua máquina baseado em um conceito de compartilhamento de Kernel.
Na virtualização tradicional é possível ter máquinas COMPLETAS (Guest OS) rodando em cima de um sistema hospedeiro (Host OS). O problema com isso é cada sistema operacional para rodar consome recursos do sistema hospedeiro como cpu, disco e memória. Só isso já reduz a capacidade do sistema hospedeiro. E não estamos falando ainda nem dos recursos que o seu serviço precisa para rodar.
Na virtualização baseada no Docker, cada “máquina virtual” (veremos adiante isso), denominada de container, compartilha o sistema operacional do hospedeiro. Com isso o Docker não tem o conceito de Guest OS. Essa mudança de paradigma abre espaço para dois conceitos importantes:
- O seu container passa a consumir apenas os recursos necessários para que o serviço rode, já que não precisa ter um sistema operacional instalado dentro do container;
- Cada container passa a ser uma aplicação isolada que pode ser replicada para qualquer ambiente que tenha o Docker instalado.
Então, com isso, é possível ter um serviço do MySQL baseado em container, ou do Postgres, ou ainda um ElasticSearch por exemplo.
O único inconveniente para algumas pessoas é que como o Docker foi desenvolvido baseado na arquitetura Linux ele só consegue rodar Containers que tem como base a arquitetura Linux.
Erros de conceito comuns
Apesar de ser muito simples subir um container com um serviço e compartilhar recursos da sua máquina, é muito importante frisar que o Docker mantém um isolamento de recursos entre o container e a máquina hospedeira.
Já vi pessoas, e eu mesmo, perdendo várias horas tentando entender por que determinadas coisas não funcionavam mesmo aparentemente estando tudo certo. Por não ser 100% uma máquina virtual, mas isolando os recursos do container, muitas vezes induzem as pessoas a cometer alguns erros de conceito:
Endereçamento IP
Para garantir o isolamento dos recursos, é necessário que o container tenha a sua própria interface de rede e com isso o seu próprio endereço IP. Isso significa que para acessar um serviço, ou você utiliza os “links” do Docker que facilita esse mapeamento ou você tem que especificar o endereço IP do container criado. Além disso, você pode literalmente acessar esse container por SSH.
Mapeamento de portas
Já que cada Container tem o seu próprio IP, isso significa que ao subir o serviço você está relacionando a porta ao IP do container. Logo, para que você consiga acessar aquele serviço em especial você precisa “expor” a porta dele para a máquina hospedeira.
Sistema de Arquivos
Cada container docker também tem o seu próprio sistema de arquivos. Isso significa que se um determinado serviço precisa de arquivos que estão no sistema hospedeiro, você precisará fazer um mapeamento do diretório do sistema hospedeiro para o container. Um outro detalhe importante é que se você salva um arquivo diretamente no Container, ao reiniciar o container, esse arquivo simplesmente some!
Confundir Imagem com Container
Esse é um erro muito comum. A imagem contém um pedaço “IMUTÁVEL” da máquina, ou seja, é a definição dela. O Container é imagem que está está em execução. Os dados salvos no container são efêmeros.
Container não é uma Máquina Virtual
Apesar de frequentemente utilizarmos esse conceito, um container não é uma máquina virtual [1]. Mesmo tendo conceitos bastante comuns como o isolamento da arquitetura o fato do container Docker compartilhar recursos da máquina hospedeira não o torna uma máquina virtual “conceitualmente”.
Instalando o Docker
O Docker por ser instalando em qualquer máquina Linux, ARM, Mac ou Windows. É importante lembrar que por conta da arquitetura do Docker descrita acima, os containers ficam restritos à arquitetura as quais as imagens foram criadas.
Para Windows ou Mac baixe o Docker aqui: https://www.docker.com/products/docker-desktop.
Para Linux rode o comando:
wget -qO- https://get.docker.com/ | sh
Você pode obter outros comandos úteis aqui: https://github.com/byjg/docker-bash-scripts/
Usando o Docker
Após instalado o Docker, vamos agora aplicar os conceitos rodando uma imagem. Para o nosso exemplo vamos rodar uma aplicação em PHP. Para isso vamos utilizar a imagem “byjg/php:7.2-fpm-nginx”. Para se ver mais mais imagens basta acessar https://hub.docker.com.
Então vamos criar o nosso primeiro arquivo PHP, mesmo que você não tenha o PHP instalado em sua máquina. Por exemplo, criaremos o arquivo: /opt/exemple/page.php, com o seguinte conteúdo:
<?php
echo "Hello World";
Para rodar ele vamos inicialmente pensar em :
docker run -d --rm --name instancephp byjg/php:7.2-fpm-nginx
O parâmetro -d
indica que a sua instância irá rodar em background, --name
define um nome para a sua instância e --rm
indica para remover a instância ao terminar de executá-la.
Para saber se está tudo certo basta rodar: docker ps
e teremos algo mais ou menos assim:
Entretanto, se tentarmos acessar essa página simplesmente não conseguiremos. Isso acontece, por que o Docker isola o container da máquina hospedeira, fazendo com que tenha a sua própria memória, rede e estrutura de arquivos. Com isso, se quisermos rodar uma imagem teremos que adicionar alguns parâmetros para informar o que iremos compartilhar da máquina hospedeira com o container e vice-versa. Normalmente a documentação da imagem já informa esses parâmetros.
Sendo assim, inicialmente vamos para a nossa instância docker:
docker stop instancephp
E vamos compartilhar o nosso arquivo que criamos com o container e também vamos dizer que a porta 80 do container será exposta na porta 8080 da máquina hospedeira. A execução do docker agora seria:
docker run -d --rm --name instancephp \
-v /opt/example:/var/www/html \
-p 8080:80 \
byjg/php:7.2-fpm-nginx
Os parâmetros acima informam que a pasta /opt/example
da máquina hospedeira será mapeada na pasta /var/www/html
do container, e que porta 8080 da máquina será redirecionada para a porta 80 do container.
Então se você rodar http://localhost:8080/page.php você poderá ver na tela “Hello World”