Certo, muito se fala hoje em dia em Docker... A minha experiência recente é de puro fascínio, como demorei tanto para utilizá-lo? Realmente não sei...
Neste artigo tentarei sintetizar meus entendimentos de Docker e como utilizá-lo para "rodar" um sisteminha Web bem básico. Assim divido tudo em partes:
- Conceito do Docker e o que ele tenta resolver;
- Um pequeno sistema WEB utilizando Spring Boot;
- Juntando tudo: o sistema WEB rodando dentro do Docker;
O que é o Docker?
Analise estes cenários:
- Lembra aquela vez em que você queria usar um aplicativo no seu computador e instalando dependências necessárias para tal acabou por "quebrar" outros aplicativos no computador?
- Ou quando para evitar esse tipo de coisa descrita acima você tentou levantar um outro Sistema Operacional virtualizado rodando por cima do seu S.O e no final tudo isso rodando junto ficou tão lento e ocupou tanto espaço que você desistiu!
- Lembra aquele sistema que você desenvolveu, roda legal na sua máquina mas quando você coloca em produção você passa a noite inteira para fazer funcionar?
Para facilitar a resolução dos três cenários acima a resposta é Docker, Docker e Docker! Vamos primeiro tentar entender a diferença entre um sistema rodando no Docker e rodando numa virtualização de sistema operacional olhando a figura abaixo:
Para entender Docker precisamos entender o conceito de Containers. Pelo próprio site do Docker, um container é: "Uma peça padrão de software que empacota código e suas dependências de forma que as aplicações rodem rapidamente e de forma confiável de um ambiente computacional para o outro." Neste site há uma comparação legal, que compara o Docker a um condomínio de apartamentos e um sistema virtualizado a uma casa alugada.
Enquanto que em um condomínio os recursos (a piscina, a academia, garagem, água...) são compartilhados entre os vizinhos. Em uma casa alugada nada é compartilhado, ou seja tudo é exclusivo, e sabemos que essa exclusividade tem um custo.
Resumindo: Containers são menores que imagens virtuais, podem ser mais facilmente construídos (e destruídos) e eles compartilham recursos com o S.O em que estão rodando. Em contrapartida, sistemas virtualizados não compartilham nada um com o outro e também não compartilham recursos no S.O em que estão rodando.
OBS: Informações sobre como instalar o Docker podem ser encontradas no site oficial.
1. Docker
1.1. Dockerfile
O Docker entende uma receitinha de bolo que explica como construir o Container, essa receita é um arquivo sem terminação chamado Dockerfile. Se você vai usar um Linux bem pequeno chamado alpine para rodar o seu programa, você tem que dizer isso no Dockerfile. Se vai precisar instalar uma ferramenta/ dependência que o seu sistema precisa dizer isso também no Dockerfile.
1.2 Docker Image
O Dockerfile é só a receita do Container. É necessário construí-lo fisicamente em uma imagem (na verdade aquele Linux chamado Alpine que é pequeno e que você pode usar também é uma imagem), ou seja, imagens específicas são compostas de outras mais genéricas.
1.3 Container
Depois que temos o Dockerfile e a imagem construída, colocamos o Container baseado naquela imagem para rodar. Se fizermos a analogia com JAVA, imagine o Dockerfile como se fosse o arquivo *.java, a imagem como se fosse o *.class ou o *. jar gerado e o Container como o aquivo jar rodando. E como sabemos, para rodar um jar muitas vezes precisamos passar parâmetros, com os Containers não é diferente, por exemplo, se queremos acessar uma porta do Container, precisamos passar isso como parâmetro.
2. Sistema WEB com SpringBoot
2.1. http://localhost:8080
Crie uma pasta chamada docker e abra o VSCode nela e pressione CTRL+SHIFT+p
$mkdir docker
/docker$ code .
Escolha Spring Initializr: Create a Maven Project
Depois escolha a versão mais recente que houver do SpringBoot, no caso, estou usando 2.5.3
Escolha a linguagem JAVA e mantenha as opções que vem sendo apresentadas (com.example) e (demo). No packaging type, escolha Jar e na versão JAVA eu estou trabalhando com a 8.
Por fim escolha apenas a dependência do Spring Web (a última da foto)
Após isso o seu VSCode deve estar assim com a classe DemoApplication.java criada:
O programa ainda não tem muita função, precisamos de um acesso para este retorne informações quando o sistema receber requisições externas. Vamos criar uma classe chamada Serviço (Servico.java) dentro de uma package chamada service que é bem simples, ela só retorna "Hello World":
package com.example.demo.service;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Servico {
@RequestMapping("/hello")
public String hello() {
return "Hello World";
}
}
Volte na classe DemoApplication e no método main clique em Run para executar a aplicação.
Quando ela acabar de levantar, vá no browser e escreva http://localhost:8080/hello
O resultado será o abaixo, e isto quer dizer que o seu sistema WEB está rodando localmente com acesso ao serviço /hello na porta 8080.
Falamos antes de Docker e agora temos uma aplicação WEB rodando. Como criar um Container rodando esta aplicação? É o próximo desafio.
3. Aplicativo Rodando no Container
3.1. Construindo Dockerfile
Temos o nosso aplicativo construído na seção 2, vamos agora pensar em como seria o ambiente para executá-lo. Primeiramente, vamos executá-lo em um Container Linux, então vamos considerar o Alpine, mais informações sobre ele aqui. Lembrem que eu escolhi o Java 8 quando estava criando o aplicativo? Então este é outro ponto a se considerar.
Crie um arquivo Dockerfile (sem extensão) no mesmo diretório criado (docker) e no mesmo local onde o projeto JAVA está criado e irei comentar linha a linha este arquivo Dockerfile.
Linha 1: Diz que precisaremos de uma imagem do Linux Alpine e que deve vir com um jdk versão 8 já instalado (prático, não precisamos instalar JAVA);
Linha 3: Diz qual será o diretório de trabalho no Container, no caso será o /home
;
Linha 5: Diz para copiar tudo que estiver neste diretório em que estamos e mandar para o WORKDIR definido (no caso /home
);
Linha 7: Como a versão Alpine do Linux é bem básica, precisamos instalar o Maven (lembrem que criamos um Maven Project lá no VSCode), é isto que este comando faz;
Linha 9: Após a linha 3 executar passamos a ter um diretório /demo
dentro de /home
, setamos então /home/demo
como sendo o novo diretório de trabalho;
Linha 11: Rodamos o comando para fazer o MAVEN gerar o Jar do App que desenvolvemos, este jar é criado em uma pasta /home/demo/target
Linha 13: Este comando expõe a porta 8080 (que é a porta que o App Web utiliza para receber requisições
Linha 15: Este comando representa o que deverá ser rodado no prompt deste Container quando ele for iniciado, que são o comando java, com os parâmetros "-jar" e o arquivo jar a ser executado /home/demo/target/demo-0.0.1-SNAPSHOT.jar
3.2. Gerando Imagem
Lembrem que o Dockerfile é como se fosse o arquivo .java, então temos que gerar o .jar dele para podermos rodá-lo. Para fazer isso, utilizamos o comando build
e com isso geraremos a imagem com tudo que está descrito no Dockerfile. Assim, na mesma pasta em que estão o Dockerfile e a pasta /demo
com o nosso projeto Spring, digite:
docker build . -t java-spring
O que isso vai fazer? Vai ler o Dockerfile que está nesta pasta, vai ler o projeto Spring criado e gerar a imagem que terá o nome de "java-spring". Aguarde a imagem ser criada e depois digite o comando docker image list
para constatar que a imagem foi criada.
Isso quer dizer que a imagem (o nosso jar) foi criado. Temos que pô-lo para rodar.
3.3. Criando Container
Como foi dito, da mesma forma como temos que passar parâmetros para rodar um arquivo jar, para rodar um Container também temos a mesma lógica. Para executarmos o Container e conseguirmos acessá-lo do browser da mesma forma que acessamos quando rodamos localmente precisaremos fazer um mapeamento de portas. Recorde-se que na Linha 13 foi exposta a porta 8080, precisamos agora mandar informações para esta porta mapeando uma porta no S.O host para a porta do Container. Veja o comando abaixo para gerar o Container
docker run --name java-container -d -p 8080:8080 java-spring
traduzindo os parâmetros para:
-
--name
: o nome do Container (java-container); -
-d
: Modo dettached (isso quer dizer que após o container começar a rodar, ele ficará rodando em background e o terminal ficará livre para o usuário); -
-p
: é o mapeamento de portas PORTA_HOST:PORTA_CONTAINER, quer dizer que uma requisição no host para a porta 8080 irá ser enviada para o host na porta 8080.
O parâmetro a seguir é justamente a imagem java-spring
que foi criada, seria como se fosse o nome do jar que vamos rodar.
Após solicitar que o Container inicie-se pode ir no Browser e digitar http://localhost:8080/hello, o efeito será o mesmo de quando executávamos o app web no host, justamente a palavra Hello World.
3.4. Comandos Adicionais Docker
Listar Containers rodando
$docker ps
Listar Containers existentes
$docker ps -a
Iniciar um Container
$docker start <nome_container>
Derrubar um Container
$docker stop <nome_container>
Reiniciar um Container (stop seguido de um start)
$docker restart <nome_container>
Listar Imagens Máquina Local
$docker image list
Remover Imagem
$docker rmi <nome_imagem>
Enviar um comando para um Container rodando
$docker exec -it <nome_container> <comando>
Considerações
O Docker é um aliado poderoso, vale a pena aprender e usá-lo. O app e o Dockerfile estão aqui para quem quiser baixar.
Top comments (0)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.