Executando aplicações Spring Boot no Docker

O Docker é uma plataforma que vem ganhando bastante adoção nas construção de ambientes dos sistemas, pois suas características de container que proporcionam construir e gerenciar ambientes de diferentes tipos(desenvolvimento, produção, testes, etc), de forma homogênea, automatizando instalações de sistema operacional, servidores, banco de dados e outras dependências necessárias para executar a aplicação.

Com isso, esse post tem como objetivo demonstrar como criar um ambiente de desenvolvimento composto por uma aplicação Spring Boot e o banco de dados Postgres, onde cada um roda em um container Docker.

Pré requisitos

Para realizar os passos desse post é preciso de Maven e Docker instalado.

Iniciando

Como mencionado anteriormente, o sistema é composto por duas partes em termos de infraestrutura: a aplicação e o banco de dados, dessa forma, o ambiente também será dividido em dois containers, como demonstrado na imagem abaixo, onde cada container pode ter as características mais apropriadas para sua execução.

Container 1 – Aplicação

O primeiro passo é criar o arquivo Dockerfile com as configurações do ambiente necessário para executar a aplicação, assim, o arquivo deve seguir basicamente a estrutura demonstrada abaixo:

Dockerfile

FROM openjdk:8-jdk-alpine
VOLUME /tmp
COPY target/spring-boot-docker-*.jar app.jar
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app.jar"]
  • FROM: Configuração de qual imagem será utilizado como base, com isso na Docker hub é disponibilizado uma serie de imagens já prontas para serem utilizadas, como no exemplo a openjdk:8-jdk-alpine que já é uma imagem “slim”, com sistema operacional Debian e openJDK configurado na versão 8;
  • VOLUME: Define um diretório para compartilhamento externo a imagem;
  • ADD: Adiciona o artefato da aplicação para ser executado, passando dois parâmetros: a origem do arquivo e o destino do arquivo;
  • ENTRYPOINT: Comando para executar o artefato adicionado dentro da imagem.

Observação: No atributo “ADD” a origem vai depender de onde se encontra o arquivo Dockerfile, no exemplo acima o arquivo está na raiz do projeto e o artefato gerado pelo maven se encontra dentro da pasta /target, que por padrão em projetos Spring Boot, são empacotados como .jar.

Observação: No atributo “ENTRYPOINT” o comando pode mudar conforme a imagem utilizada no “FROM”, nesse caso, com a imagem do openjdk foi utilizado o comando java.

Para simplificar a criação da imagem Docker em aplicações Java o Spotify disponibiliza um plugin Maven: dockerfile-maven-plugin, que abstrai os comandos docker para geração da imagem local e possibilita a criação da imagem em conjunto com o build da aplicação.

<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>dockerfile-maven-plugin</artifactId>
    <version>1.4.2</version>
        <configuration>
            <repository>emmanuelneri/${project.artifactId}-app</repository>
        </configuration>
</plugin>

Após configurado a imagem e adicionado o plugin, executar o comando abaixo para gerar o artefato da aplicação e construir a imagem docker da aplicação.

mvn clean package dockerfile:build
  • mvn clean package: O mvn clean package apaga a pasta target e gera novamente um build da aplicação, ou seja, será criado um novo arquivo .jar dentro da pasta do Maven;
  • dockerfile:build: Cria a imagem da aplicação com o nome definido no plugin dockerfile-maven-plugin na área de configuration -> repository e instala no docker local, assim sendo visível quando executado o comando docker images.

Caso não queira utilizar o plugin do Spotify, a imagem docker pode ser construída facilmente pelo comando build do docker executando o comando abaixo na pasta que se encontra o DockerFile:

docker build -t emmanuelneri/spring-boot-docker-app .
  • docker build: Constrói a imagem a partir do Dockerfile no repositório local;
  • -t (tag): Informe o nome da imagem.

Container 2 – Banco de dados

Diferente do container das aplicações, que possuem particularidades conforme a tecnologia, os containers de base de dados podem ser mais genéricos, dessa forma, podemos utilizar as imagens disponíveis no Docker Hub e apenas configurar para aplicação como no comando abaixo:

docker run -d \
    --name docker-postgres \
    -e POSTGRES_DB=db \
    -e POSTGRES_USER=postgres \
    -e POSTGRES_PASSWORD=postgres \
   postgres:10.4
  • docker run: Executa a imagem Docker;
  • -d: Mantém a execução do container mesmo que fechado a janela (d = ativando Detached mode)
  • -e: Define configuração e ambiente (e = environment) ;
  • POSTGRES_DB: Configura o nome da base de dados, se não tiver será criado;
  • POSTGRES_USER: Configura o usuário de acesso ao banco de dados;
  • POSTGRES_PASSWORD: Configura a senha do usuário de acesso ao banco de dados;
  • postgres:10.4: Imagem a ser executada, no caso a imagem oficial do Postgres, versão 10.4.

Depois de executado o container do Postgres é preciso configurar a URL de datasource de acesso ao banco de dados para o nome dado ao container da base de dados, então como foi definido docker-postgres no atributo –name da execução é esse o nome a ser inserido no arquivo de configuração”.

application.properties

spring.datasource.url=jdbc:postgresql://localhost:5432/db
spring.datasource.username=postgres
spring.datasource.password=postgres

Executando o ambiente

Feito a construção da imagem da aplicação e executado a base de dados, agora é só executar o container da aplicação com o seguinte comando.

docker run -it \
    --link docker-postgres  \
    -p 8080:8080 \
    emmanuelneri/spring-boot-docker-app

 

  • docker run: Executa a imagem Docker;
  • -it: Executa o container com o shell iterativo com o container (it = interactive )
  • –link: Criar link com outros containers, no caso com o container da base de dados;
  • -p: Configura a porta a ser executado o serviço;
  • emmanuelneri/exemplo-docker-app : Executa a imagem construída com a aplicação..

Pronto, a aplicação está disponível no endereço http://localhost:8080 e com o comando docker ps é possível listar os containers em execução.

CONTAINER ID        IMAGE                                 COMMAND                  CREATED             STATUS              PORTS                    NAMES
3b7f0cfeceaf        emmanuelneri/spring-boot-docker-app   "java -Djava.securit…"   8 minutes ago       Up 7 seconds        0.0.0.0:8080->8080/tcp   springbootdocker_docker-app_1
7f01ce21cb11        postgres:10.4                         "docker-entrypoint.s…"   8 minutes ago       Up 7 seconds        5432/tcp                 springbootdocker_docker-postgres_1

Uma outra alternativa para executar esse cenário seria utilizando com Docker Compose, que é uma ferramenta do próprio Docker para execução de múltiplos containers. Assim, basta criar o arquivo docker-compose.yml com as configurações abaixo e executar o comando docker-compose up.

version: '3'
services:
 docker-app:
    image: emmanuelneri/spring-boot-docker-app
    ports:
      - "8080:8080"
    depends_on:
      - docker-postgres
 docker-postgres:
    image: postgres:10.4
    environment:
      - POSTGRES_DB=db
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres

  • version: Versão do Docker Compose;
  • services: Declaração dos serviços, no caso os dois containers docker-app e docker-postgres;
  • image: Define a imagem utilizada para o serviço acima;
  • ports: Define as portas que podem ser acessadas por fora do containers, mesmo comportamento do parâmetro -p;
  • depends_on: Informa que o container depende de outro container, assim chamará a inicialização do container dependente por primeiro;
  • environment: Possibilita a configurações das variáveis de ambiente da imagem, mesmo comportamento do parâmetro -e.

Bom é isso, o Docker é uma excelente solução de container para nos auxiliar na construção de ambientes para nossos sistemas, onde cada vez mais podemos criar e recriar nossos cenários com mais rapidez e facilidade, aplicando esses mesmos benefícios para a execução de aplicações com Spring Boot.

Um pouco mais…

Criando um profile específico para o Docker

Nem sempre vamos executar todo o tempo nossas aplicações no docker, com isso, o Spring boot oferece a possibilidade da criação de profiles, onde podemos criar um application-docker.properties específico para ser executado com os containers, como na configuração abaixo:

application-docker.properties

spring.datasource.url=jdbc:postgresql://docker-postgres:5432/db
spring.datasource.username=postgres
spring.datasource.password=postgres

spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults=false

E no Dockerfile configuramos o profile ativo com o parâmetro -Dspring.profiles.active.

Dockerfile

FROM openjdk:8-jdk-alpine
VOLUME /tmp
COPY target/spring-boot-docker-*.jar app.jar
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-Dspring.profiles.active=docker", "-jar", "/app.jar"]

Um pouco mais sobre profiles no Spring boot pode ser visto neste post.

Consideração

Na configuração dos plugins, caso não estiver usando o spring-boot-starter-parent no pom da aplicação é preciso configurar spring-boot-maven-plugin para executar o repackage do plugin.

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <version>${spring-boot.version}</version>
    <executions>
        <execution>
            <goals>
                <goal>repackage</goal>
            </goals>
        </execution>
    </executions>
</plugin>

O código fonte do exemplo acima está disponível no <a href="https://github.com/emmanuelneri-blog/spring-boot-docker.

Anúncios

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.