DEV Community

Cover image for Utilizando Docker em App WEB Spring Boot
Fernando Raposo da Camara Silva
Fernando Raposo da Camara Silva

Posted on • Updated on

Utilizando Docker em App WEB Spring Boot

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:

  1. Conceito do Docker e o que ele tenta resolver;
  2. Um pequeno sistema WEB utilizando Spring Boot;
  3. 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:
image

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 .
Enter fullscreen mode Exit fullscreen mode

Escolha Spring Initializr: Create a Maven Project
image
Depois escolha a versão mais recente que houver do SpringBoot, no caso, estou usando 2.5.3
image
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)
image
Após isso o seu VSCode deve estar assim com a classe DemoApplication.java criada:
image
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";
    }

}
Enter fullscreen mode Exit fullscreen mode

Volte na classe DemoApplication e no método main clique em Run para executar a aplicação. image
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.
image
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.
image
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)