Spring Boot + Docker + AWS EC2

thiagosouzasi

Thiago Souza

Posted on April 26, 2023

Spring Boot + Docker + AWS EC2

Introdução

Salve galera! Nesse post vou tentar demostrar como publicar uma Api Spring Boot utilizando Docker, DockerHub e uma instância do EC2 da AWS. Então seguem os passos que vamos seguir para publicar a Api.

  1. Criar um projeto Spring Boot
  2. Criar uma imagem com Dockerfile
  3. Publicar a imagem no DockerHub
  4. Configurar uma instância EC2 na AWS e colocar a API em produção

Vamos Lá!

Criando o projeto

Para criação do projeto vamos utilizar a plataforma Spring Initializr e criar um projeto simples utilizando maven e java 17 e com apenas uma dependência conforme abaixo.

Image description

O projeto consiste em uma pequena Api que vai consultar dados sobre Pokemons em uma outra Api bem famosa, a PokéApi. Faremos a consulta passando o nome do pokemon para um controller get na nossa api.

PokemonControler

@RestController
public class PokemonController {

    @Autowired
    PokemonService pokemonService;

    @GetMapping("pokemon-info")
    public String GetPokemonInfo(@RequestParam String pokemonName){

        return pokemonService.GetPokemonInfo(pokemonName);
    }
}

Enter fullscreen mode Exit fullscreen mode

Dentro do nosso controller temos uma injeção de dependência para nossa classe service que por sua vez acionará nosso repository que buscará os dados.

PokemonService

@Service
public class PokemonService {

    @Autowired
    PokemonRepository pokemonRepository;
    public String GetPokemonInfo(String pokemonName) {
      return pokemonRepository.GetPokemonInfo(pokemonName);
    }
}

Enter fullscreen mode Exit fullscreen mode

Por último temos nosso PokemonRepository, geralmente é aqui que fazemos o acesso ao banco de dados, mas como a Api é simples vamos simular esse acesso aos dados com uma chamada para outra Api passando o nome do pokemon recebido pelo controller.

PokemonRepository

@Repository
public class PokemonRepositoryImplementation implements PokemonRepository {

    @Autowired
    private Environment env;

    @Override
    public String GetPokemonInfo(String pokemonName) {
        try {
          return  new RestTemplate().getForObject(env.getProperty("baseUrl")+pokemonName, String.class);
        }catch (HttpClientErrorException error){
            if (error.getStatusCode() == HttpStatus.NOT_FOUND) {
                throw new ResponseStatusException(HttpStatus.NOT_FOUND);
            } else {
                throw new ResponseStatusException(HttpStatus.BAD_REQUEST);
            }
        }

    }
}

Enter fullscreen mode Exit fullscreen mode

O código completo pode ser encontrado no meu GitHub

2. Criar a imagem com Dockerfile

Vamos criar um arquivo na raiz do projeto com o nome Dockerfile sem extensão. Dentro desse arquivos vamos incluir os comandos Docker para geração da imagem que será enviada para o DockerHub e posteriormente carregada dentro de um container na nossa instância EC2 na AWS.

Dockerfile

Image description

Dentro do arquivo vamos entender o que faz cada comando:

FROM openjdk:17 -> Indica que vamos construir nossa imagem a partir do jdk 17 necessário para que a nossa Api seja executada no container.

WORKDIR /app -> Cria o repositório app dentro do nosso container para onde vamos copiar nossos arquivos .jar compliados.

COPY /target/demo-0.0.1-SNAPSHOT.jar /app/api.jar -> Aqui estamos copiando nosso jar de dentro da pasta onde ele foi gerado, para dentro do repositório criado no nosso comando anterior.

EXPOSE 8080 -> Expondo a porta onde nossa aplicação ficará disponível.

ENTRYPOINT ["java","-jar", "api.jar"] -> Executando nosso arquivo .jar criado para que nossa aplicação seja iniciada.

Antes de utilizarmos o Dockerfile para criar nossa imagem, precisamos construir o nosso .jar com nosso código fonte compilado, para isso utilizaremos o comando mvn clean install isso deve gerar nossos arquivos dentro do diretório target do projeto.

Image description

A partir de agora precisaremos estar com o Docker instalado e rodando em nossa máquina, pois vamos fazer build utilizando nosso Dockerfile para efetivamente gerar a imagem que será posteriormente enviada ao DockerHub. É necessário também possuir uma conta no DockerHub pois vamos precisar efetuar o login na nossa conta para fazer o push da imagem.

Abra o terminal e execute o seguinte comando docker build -t pokemon-api . esse comando vai gerar nossa imagem com o nome pokemon-api utilizando nosso Dockerfile criado anteriormente.

Podemos agora executar o comando docker images e verificar que nossa imagem foi criada com. sucesso!

Image description

3. Publicar a imagem no DockerHub

Agora que temos a nossa imagem gerada, vamos subir para a nossa conta no DockerHub. Precisamos fazer login na nossa conta, então vamos rodar o comando docker login dentro do terminal, nossas credenciais serão solicitadas após isso já poderemos efetuar o push da imagem para nossa conta.

Vamos marcar a imagem com uma tag que será importante na hora de fazer o pull dentro da nossa instância de EC2. O padrão para esse comando é: docker tag <image_id> <dockerhub_username>/<image_name>:<tag>, onde image_id é o ID da imagem que desejamos marcar, no meu caso, o comando ficaria assim: docker tag c8a7b3f87156 thiagosouzasi/pokemon-api:0.0.1. Estou utilizando a tag para versionar a nossa imagem com 0.0.1.

Agora que a imagem já possui a tag, vamos fazer o push para nosso repositório. Pra isso vamos utilizar o comando docker push thiagosouzasi/pokemon-api:0.0.1. Lembrando que precisamos estar logados na nossa conta para que o processo funcione.

Pronto, agora temos nossa imagem publicada dentro do DockerHub.
Image description

4. Configurar uma instância EC2 na AWS e colocar a API em produção.

Finalmente chegou a hora de publicarmos nossa Api, para isso é preciso inicialmente possuir uma conta na AWS.

Com a conta criada vamos navegar até o console e digitar EC2 na busca. Dentro do EC2 vamos clicar em Executar Instância para criar uma nova Instância de EC2.

Image description
Informamos o nome da instância e escolheremos o tipo Amazon Linux. Devemos ainda selecionar o tipo t2.micro, assim, conseguiremos publicar a Api sem custos.

Posteriormente precisamos configurar o login sem atribuir chaves de acesso, atenção esse tipo de configuração não é recomendado em projetos reais por deixar brechas de segurança, contudo, por hora isso será o suficiente e facilitará a conexão com a instância que será feita mais a frente.

Após isso basta clicar em executar instância.
Image description

Adicionaremos ainda outra configuração importante, devemos liberar a porta http(80) da nossa instância para habilitar o acesso externo. Mais a frente faremos o mapeamento dessa porta para a porta do container que deverá rodar nossa APi.

Selecione a instância criada, e navegue até a aba segurança.
Image description

Em grupo de segurança clicamos em launch-wizard vai ser aberta uma tela onde vamos configurar uma regra de entrada.

Na tela a seguir vamos selecionar regras de entrada e clicar em editar regras de entrada

Image description

Vamos adicionar a regra para protocolo http (80) e salvar a configuração.
Image description

Agora já estamos com o EC2 configurado, selecione a instância criada e vá em conectar. Agora instalaremos o Docker, faremos o pull da imagem do Dockerhub e executaremos nossa Api.

Image description

Uma vez conectados basta executar uma sequência de comandos:

  • Primeiro vamos alternar para o modo root no terminal com o comando sudo -i

  • Agora vamos atualizar os pacotes da máquina com o comando sudo yum update -y

  • Na sequência vamos instalar o Docker na EC2 com o comando sudo yum install docker. Após o download e instalação dos pacotes podemos verificar se a instalação foi bem sucedida executando o comando docker -v.

Image description

Vamos agora iniciar o Docker com o comando sudo service docker start

Docker rodando, vamos fazer o pull da nossa imagem salva no Dockerhub, para isso precisaremos efetuar novamente o login na nossa conta do Dockerhub com o mesmo comando que utilizamos na nossa máquina local docker login. Uma vez logados vamos buscar a imagem, o comando pode ser encontrado no próprio Dockerhub onde salvamos a imagem.

Image description

Vamos rodar o comando docker pull thiagosouzasi/pokemon-api:0.0.1 substituindo o tag name pela tag da versão da imagem que configuramos anteriormente.

A imagem será baixada para nossa instância, ao final do processo podemos ainda conferir se deu tudo certo rodando o comando docker images.

Image description

Chegamos à última etapa, vamos subir um container utilizando nossa imagem para finalmente colocar nossa Api em produção!

Rode o comando docker run -d -p 80:8080 thiagosouzasi/pokemon-api:0.0.1

Com esse comando estamos subindo nosso container na porta 8080, mesma porta configurada na nossa api spring boot e estamos mapeando essa porta para a porta 80 da instância EC2, justamente por isso configuramos a regra de entrada nas etapas anteriores. Dessa forma todo tráfego que chegar na porta http padrão será direcionado para a api no nosso container.

Foi utilizada ainda a flag -d para que nosso container suba em modo detached e permaneça rodando mesmo quando fecharmos o terminal do EC2.

Image description

Pronto, é chegada a hora da verdade! Agora basta pegar DNS IPv4 público da nossa instância e fazer uma requisição passando o nome de um pokemon que vc conhece para ver se está tudo funcionando.

Image description

Por hoje é isso pessoal!

💖 💪 🙅 🚩
thiagosouzasi
Thiago Souza

Posted on April 26, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Spring Boot + Docker + AWS EC2
springboot Spring Boot + Docker + AWS EC2

April 26, 2023