Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tarefa2 #2

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
117 changes: 117 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#=================================== MULTISTAGE -> build ====================================
# FROM [nome da imagem]:[versão/tag da imagem]
# Referência: https://docs.docker.com/engine/reference/builder/#from
#
# Define uma imagem local ou pública do Docker Store. Aqui é utilizado uma imagem oficial do
# Maven (baseada na distribuição linux Debian Stretch Slim), cujo objetivo é servir de imagem
# base para os demais estágios do processo de build da imagem final, reduzindo seu tamanho e
# permitindo total independência à ferramentas externas ao Docker.
#============================================================================================
FROM maven:3.5.2-jdk-8 AS build

#============================================================================================
# COPY [arquivo a ser copiado] [destino do arquivo copiado]
# Referência: https://docs.docker.com/engine/reference/builder/#copy
#
# Copia os arquivos de código fonte da aplicação para dentro do container.
#============================================================================================
COPY src /usr/src/app/src
COPY pom.xml /usr/src/app

#============================================================================================
# RUN [comandos a serem executados]
# Referência: https://docs.docker.com/engine/reference/builder/#run
#
# A instrução RUN executará qualquer comando sobre uma nova camada da imagem atual e
# confirmará os resultados. A imagem resultante será usada para o próximo passo no Dockerfile.
#============================================================================================
RUN \
mvn -f /usr/src/app/pom.xml clean package -DskipTests

#================================== MULTISTAGE -> release ===================================
# FROM [nome da imagem]:[versão/tag da imagem]
# Referência: https://docs.docker.com/engine/reference/builder/#from
#
# Define uma imagem local ou pública do Docker Store. Aqui é utilizado uma imagem oficial do
# Debian (baseada na distribuição linux Debian Stretch Slim). Em sua primeira execução, ela
# será baixada para o computador e usada no build para criar a imagem da aplicação.
#================================
FROM debian:stretch

#============================================================================================
# LABEL maintainer=[nome e e-mail do mantenedor da imagem]
# Referência: https://docs.docker.com/engine/reference/builder/#label
#
# Indica o responsável/autor por manter a imagem.
#============================================================================================
LABEL maintainer="Raphael F. Jesus <[email protected]>"

#============================================================================================
# ARG <nome do argumento>[=<valor padrão>]
# Referência: https://docs.docker.com/engine/reference/builder/#arg
#
# A instrução ARG define uma variável que os usuários podem passar no tempo de compilação
# para o construtor com o comando docker build.
#============================================================================================
ARG PORT

#============================================================================================
# ENV [nome da variável de ambiente]
# Referência: https://docs.docker.com/engine/reference/builder/#env
#
# Variáveis de ambiente com o path da aplicação dentro do container.
#============================================================================================
ENV \
PORT=${PORT:-8090} \
JAVA_OPTS='-Xms256m -Xmx256m' \
DEBUG_OPTS=

#============================================================================================
# VOLUME [nome do volume]
# Referência: https://docs.docker.com/engine/reference/builder/#volume
#
# Cria um ponto de montagem com o nome especificado e marca-o como um volume persistente
# montado a partir de hospedeiros nativos ou outros containers.
#============================================================================================
VOLUME /tmp

#============================================================================================
# EXPOSE [número da porta]
# Referência: https://docs.docker.com/engine/reference/builder/#expose
#
# Irá expor a porta para a máquina host (hospedeira). É possível expor múltiplas portas, como
# por exemplo: EXPOSE 80 443 8080
#============================================================================================
EXPOSE ${PORT}

#============================================================================================
# RUN [comandos a serem executados]
# Referência: https://docs.docker.com/engine/reference/builder/#run
#
# A instrução RUN executará qualquer comando sobre uma nova camada da imagem atual e
# confirmará os resultados. Aqui será executado a atualização dos pacotes instalado no sistema
# operacional, bem como instalar o openjdk e o pacote Curl para usarmos no healthcheck.
#============================================================================================
RUN \
apt -y update \
&& apt-get -y install openjdk-8-jre-headless curl --no-install-recommends \
&& rm -rf /var/lib/apt/lists/*

#============================================================================================
# COPY [arquivo a ser copiado] [destino do arquivo copiado]
# Referência: https://docs.docker.com/engine/reference/builder/#copy
#
# Copia o arquivo da aplicação para dentro do container sob o nome app.jar.
#============================================================================================
COPY --from=build /usr/src/app/target/spring-boot-sample-hateoas-2.0.1.RELEASE.jar /app.jar

#============================================================================================
# ENTRYPOINT [executável seguido dos parâmetros]
# Referência: https://docs.docker.com/engine/reference/builder/#entrypoint
#
# Inicia o container como um executável a partir da inicialização da aplicação. Essa instrução
# é muito útil, pois caso a aplicação caia, o container cai junto, indicando ao orquestrador
# de containers aplicar a política de restart configurada para a aplicação.
#============================================================================================
ENTRYPOINT exec java ${JAVA_OPTS} ${DEBUG_OPTS} -Djava.security.egd=file:/dev/./urandom -jar /app.jar

148 changes: 145 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,148 @@
# Example application #
# Bravi Software - Teste para vaga de Arquiteto DevOps

A simple Spring Boot application that sports a REST API and does persistence using JPA.
Este documento tem como objetivo demonstrar os passos necessários para validar as implementações submetidas pelos candidados à vaga de Arquiteto DevOps na Bravi Software.

This project is based on Spring Boot's [HATEOAS example](https://github.com/spring-projects/spring-boot/tree/master/spring-boot-samples/spring-boot-sample-hateoas).
Tabela de conteúdo
==================

- [Pré-requisitos](#pré-requisitos)
- [Tarefas](#tarefas)
- [Tarefa 1: Migrar a persistência para Postgresql ou MySQL](#tarefa-1:-migrar-a-persistência-para-postgresql-ou-mysql)
- [Tarefa 2: Empacotar a aplicação usando Docker e implantá-la usando uma ferramenta de orquestração compatível com Docker](#tarefa-2:-empacotar-a-aplicação-usando-docker-e-implantá-la-usando-uma-ferramenta-de-orquestração-compatível-com-Docker)
- [Referências](#referências)

## Pré-requisitos

Antes de iniciar a execução das tarefas descritas no teste em pauta, certifique-se que as seguintes ferramentas estão disponíveis em seu ambiente:

- [Git](https://git-scm.com/)
- [JDK 8+](https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)
- [Maven 3.3+](https://maven.apache.org/download.cgi)
- [Docker 1.17+](https://docs.docker.com/install/)
- [Docker Swarm](https://docs.docker.com/engine/swarm/swarm-tutorial/)
- [cURL](https://curl.haxx.se/docs/manpage.html)
- [watch](https://linux.die.net/man/1/watch)

Para assegurar que as ferramentas citadas acima estão devidamente instaladas no ambiente, execute os comandos abaixo:

```shell
# Printa a versão do Git instalado na máquina
git --version

# Printa a versão da JDK instalada na máquina
java -version

# Printa a versão do Maven instalado na máquina
mvn --version

# Printa a versão do Docker instalado na máquina
docker --version
```

![Console com a confirmação da instalação das ferramentas](docs/images/Tarefa1-Console_com_a_confirmacao_da_instalacao_das_ferramentas.png)

## Tarefas

## Tarefa 1: Migrar a persistência para Postgresql ou MySQL

Para execução dessa tarefa, será utilizado o banco de dados PostgreSQL.

1) Nesta etapa, será demonstrado os passos necessários para criação do banco de dados que será utilizado pela aplicação.

```shell
# Execute o comando abaixo para criar um container Docker a partir da imagem oficial do PostgreSQL expondo-o na porta 5432
docker run --name postgres-test -p 5432:5432 -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=postgres -d postgres:10.6-alpine
```

![Console com a criação do banco de dados PostgreSQL](docs/images/Tarefa1-Console_com_a_criacao_do_banco_de_dados_PostgreSQL.png)

2) A partir do diretório raiz do projeto, empacote (formato .jar) a aplicação e execute-a a partir de um terminal, conforme descrito abaixo.

```shell
# Execute o empacotamento da aplicação utilizando o Maven
mvn clean package
```

![Console com o finalização do empacotamento da aplicação](docs/images/Tarefa1-Console_com_o_finalizacao_do_empacotamento_da_aplicacao.png)

```shell
# Inicie a aplicação empacotada via terminal
java -jar target/spring-boot-sample-hateoas-2.0.1.RELEASE.jar
```

![Console com a inicialização da aplicação via terminal](docs/images/Tarefa1-Console_com_a_inicializacao_da_aplicacao_via_terminal.png)

3) Com aplicação inicializada, acesse a URL `http://localhost:8090/swagger-ui.html` a partir do seu navegador favorito e teste a aplicação utilizando os recursos do Swagger.

![Página inicial do Swagger gerado pela aplicação](docs/images/Tarefa1-Pagina_inicial_do_Swagger_gerado_pela_aplicacao.png)

>**Nota:** Tenha certeza que as portas `8090` e `5432` utilizadas pela aplicação e banco de dados respectivamente, não estão em uso por outros processos em seu ambiente.

### Tarefa 2: Empacotar a aplicação usando Docker e implantá-la usando uma ferramenta de orquestração compatível com Docker

Para execução dessa tarefa, será utilizado o Docker Swarm como ferramenta de orquestração de containers Dockers.

1) Inicie um docker swarm em seu ambiente, executando os comandos abaixo:

```shell
# Inicializa o orquestrador de containers na máquina
docker swarm init
```

2) Com o orquestrador de containers inicializado, inicie o container do PostgreSQL como serviço.

```shell
# Execute o comando abaixo a partir do diretório raiz do projeto
docker stack deploy --compose-file docker-stack-infra.yml BRAVI
```

![Console com a criação do container PostgreSQL como serviço](docs/images/Tarefa2-Console_com_a_criacao_do_container_PostgreSQL_como_servico.png)

>**Nota:** Garanta que a porta `5432` utilizada pelo PostgreSQL não esteja em uso.

2) Em seguida, a partir do diretório raiz do projeto, gere a imagem docker da aplicação e implante-a como serviço, conforme configuração contida no arquivo `docker-stack.yml`.

```shell
# Constrói a imagem docker da aplicação
docker build --tag spring-boot-sample-hateoas:1.0.0 .

# Execute o comando abaixo a partir do diretório raiz do projeto para implantar a aplicação como serviço
docker stack deploy --compose-file docker-stack.yml BRAVI

# Confirme se o serviço foi criado corretamente
docker service ls
```

![Console com a confirmação da criação do serviço da aplicação](docs/images/Tarefa2-Console_com_a_confirmacao_da_criacao_do_servico_da_aplicacao.png)

>**Nota:** Para visualizar os logs gerados pela aplicação implantada como serviço, utilize o comando `docker service logs BRAVI_spring-boot-sample-hateoas` a partir do terminal.

3) Na sequência, usando seu navegador favorito, acesse a URL `http://127.0.0.1:8090/swagger-ui.html` e teste a aplicação utilizando os recursos do Swagger.

![Página inicial do Swagger da aplicação](docs/images/Tarefa2-Pagina_inicial_do_Swagger_da_aplicacao.png)

4) Agora, simule a queda de um dos containers associados ao serviço da aplicação e veja como a aplicação se comporta para o usuário final. Para executar esse passo, todos os comandos descritos abaixo devem ser executados em terminais diferentes.

```shell
# Diminua a réplica do serviço de 2 para 1
docker service scale BRAVI_spring-boot-sample-hateoas=1

# Lista todos os containers em execução a meio segundo
watch -n 0.5 docker ps

# Testa o endpoint da aplicação a cada 1 segundo
watch -n 1 curl -I http://127.0.0.1:8090/swagger-ui.html
```

![Console com a saída do monitoramento da aplicação quando simulado uma queda](docs/images/Tarefa2-Console_com_a_saida_do_monitoramento_da_aplicacao_quando_simulado_uma_queda.png)

## Referências

- [Git - Documentação](https://git-scm.com/doc)
- [JDK - Documentação](https://docs.oracle.com/javase/8/docs/)
- [Maven - Documentação](https://maven.apache.org/guides/index.html)
- [Docker - Documentação](https://docs.docker.com/)
- [Docker Swarm - Documentação](https://docs.docker.com/engine/swarm/)
- [PostgreSQL - Documentação](https://www.postgresql.org/docs/10/index.html)
- [PostgreSQL - Imagem oficial no Docker Store](https://docs.docker.com/samples/library/postgres/)

16 changes: 16 additions & 0 deletions docker-stack-infra.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
version: '3.5'
services:
postgres-test:
image: postgres:10.6-alpine
environment:
- POSTGRES_DB=postgres
- POSTGRES_USER=postgres
- "POSTGRES_PASSWORD=postgres"
ports:
- 5432:5432
networks:
- rede

networks:
rede:
driver: overlay
36 changes: 36 additions & 0 deletions docker-stack.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
version: '3.5'
services:
spring-boot-sample-hateoas:
image: spring-boot-sample-hateoas:1.0.0
environment:
- JAVA_OPTS=-Xms256m -Xmx256m
- DATASOURCE_URL=jdbc:postgresql://postgres-test:5432/postgres
- DATASOURCE_USERNAME=postgres
- DATASOURCE_PASSWORD=postgres
ports:
- 8090:8090
networks:
- rede
stop_grace_period: 30s
deploy:
resources:
limits:
memory: 512M
reservations:
memory: 256M
replicas: 2
restart_policy:
condition: on-failure
delay: 15s
max_attempts: 5
window: 120s
update_config:
parallelism: 1
delay: 10s
failure_action: rollback
monitor: 60s
max_failure_ratio: 0.5

networks:
rede:
driver: overlay
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 3 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@
</dependency>

<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>

<dependency>
Expand Down
14 changes: 5 additions & 9 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
server.port=8090

spring.datasource.name=customerdb
spring.datasource.url=${DATASOURCE_URL:jdbc:postgresql://127.0.0.1:5432/postgres}
spring.datasource.username=${DATASOURCE_USERNAME:postgres}
spring.datasource.password=${DATASOURCE_PASSWORD:postgres}
spring.datasource.driver-class-name=org.postgresql.Driver


spring.datasource.url=jdbc:h2:file:~/${spring.datasource.name}
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driver-class-name=org.h2.Driver

spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=none

flyway.schemas=customer
Expand All @@ -18,6 +16,4 @@ logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.tool.hbm2ddl=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
logging.level.org.flywaydb.core.internal.dbsupport=DEBUG

logging.level.sample=DEBUG