Spring Boot + Docker + AWS EC2
Thiago Souza
Posted on April 26, 2023
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.
- Criar um projeto Spring Boot
- Criar uma imagem com Dockerfile
- Publicar a imagem no DockerHub
- 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.
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);
}
}
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);
}
}
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);
}
}
}
}
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
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.
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!
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.
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.
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.
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.
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
Vamos adicionar a regra para protocolo http (80) e salvar a configuração.
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.
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 comandodocker -v
.
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.
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
.
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.
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.
Por hoje é isso pessoal!
Posted on April 26, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.