Fale com a gente no WhatsApp Fale com a gente no WhatsApp
Fale com a gente no WhatsApp

Java DevOps

Deploy de uma aplicação Spring Boot na DigitalOcean

Aprenda nesse artigo como realizar o Deploy de uma aplicação Spring Boot em uma VPS da DigitalOcena, usando ferramentas como o Nginx.

há 1 ano 3 meses

Formação Analista DevOps
Conheça a formação em detalhes

No mundo atual, a infraestrutura em nuvem se tornou essencial para o desenvolvimento e implantação de aplicações web. A Virtual Private Server (VPS), ou Servidor Virtual Privado, é uma solução popular que oferece controle, escalabilidade e desempenho para hospedar aplicativos online. Neste artigo, apresentaremos um guia completo sobre como preparar uma VPS para hospedar uma aplicação Spring, permitindo que você execute e disponibilize sua aplicação com facilidade e segurança.

O processo será detalhado, desde a escolha do provedor de nuvem até a configuração do servidor web Nginx para servir a aplicação na web. Utilizaremos como exemplo a plataforma DigitalOcean, no entanto, os procedimentos podem ser adaptados para outras provedoras de nuvem que ofereçam serviços de VPS. Vamos começar preparando a VPS com todos os requisitos necessários para hospedar a sua aplicação Spring.

Preparando a nossa VPS

Primeiramente vamos preparar a VPS para que a mesma esteja com todo o ambiente necessário para executar e disponibilizar a nossa aplicação Spring.

Existem diversos provedores de nuvem que disponibilizam um serviço de VPS, nesse artigo vamos utilizar a DigitalOcean, porém, todo o passo a passo de configuração aqui demonstrado pode ser aplicado para outros provedores de nuvem. Pois essencialmente uma VPS nada mais é do que uma máquina virtual.

Spring Framework - Fundamentos
Curso Spring Framework - Fundamentos
Conhecer o curso

Criando um projeto

Agora vamos criar um Droplet, nome dado pela DigitalOcean ao seu produto de VPS. Para isso acesse a sua conta na DigitalOcean e selecione a opção de criar um novo Droplet.

Na tela de criação de um Droplet, vamos precisar passar algumas configurações. A primeira é que precisamos informar qual a região do Datacenter que irá conter o nosso Droplet.

Print da página de criação de droplet na DigitalOcean onde mostra a seleção da região

O ideal é escolher a região geograficamente mais próxima aos usuários que irão utilizar a aplicação.

Logo em seguida precisamos escolher qual a imagem do sistema operacional que vamos utilizar em nosso Droplet.

Print da página de criação de droplet na DigitalOcean onde mostra a seleção da imagem

Para esse artigo vamos utilizar uma máquina Ubuntu 22.04.

Também precisamos informar qual será a configuração de hardware do nosso Droplet. Esse é um ponto muito importante, pois, dependendo das configurações de hardware, seremos cobrados um valor diferente.

Print da página de criação de droplet na DigitalOcean onde mostra a seleção das configurações de hardware

Para esse exemplo vamos utilizar uma máquina com uma CPU AMD, com 1 GB de memória e 25 GB de armazenamento em disco. Para essa configuração seremos cobrados o valor de sete dólares por mês. Lembrado que a DigitalOcean só cobra pelo tempo utilizando, ou seja, caso a máquina fique disponível por um único dia, só seremos cobrados o equivalente há um dia de uso e não por um mês completo.

Agora precisamos informar o método de autenticação que iremos utilizar, para facilitar, vamos utilizar uma autenticação com senha.

Print da página de criação de droplet na DigitalOcean onde mostra a seleção do método de autenticação

Por fim, recomendo também alterar o hostname do Droplet para facilitar a identificação da VPS.

Print da página de criação de droplet na DigitalOcean onde mostra a configuração dos ajustes finais

Agora, basta clicar no botão “Create Droplet” para que o Droplet seja criado e disponibilizado.

Conectando ao Droplet via SSH

Agora que o nosso Droplet está criado, vamos precisar entrar no terminal desse Droplet para podermos executar comandos na nossa VPS. Para isso iremos utilizar o SSH (Secure Shell).

Primeiramente, precisamos do endereço IP que foi gerando para o nosso Droplet, para obter essa informação vá até a página de listagem dos Droplets, página essa para qual formos redirecionados após a criação do Droplet e copie o endereço IP disponibilizado.

Print da página de listagem de Droplets criados

Agora que temos o endereço IP do nosso Droplet vamos nos conectar a nossa VPS com o seguinte comando:

ssh root@165.232.148.181

Lembre-se de substituir o endereço IP do comando acima para o endereço IP da sua VPS.

Ao executar o comando acima pela primeira vez será exibida a seguinte mensagem:

The authenticity of host '165.232.148.181 (165.232.148.181)' can't be established.
ED25519 key fingerprint is SHA256:stYZPeU0IekNoljTjsAs8uHQiZFlSrnBhCvYDPisuwY.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])?

Basta digitar “yes” e depois dar um enter e logo em seguida digitar a senha que você configurou para o usuário root na criação do seu Droplet e dar um enter novamente.

Spring Framework - Tópicos Avançados
Curso Spring Framework - Tópicos Avançados
Conhecer o curso

Configurando um Firewall

Como boa prática de segurança, vamos habilitar um firewall em nosso servidor para garantir que apenas certos serviços possam receber conexões externas.

Para isso vamos utilizar o UFW (Uncomplicated Firewall), que é um serviço de firewall que já vem disponibilizado no Linux Ubuntu.

Primeiramente vamos configurar o UFW para permitir conexões via SSH, para isso execute o seguinte comando:

ufw allow OpenSSH 

E por fim vamos habilitar o nosso firewall com o comando:

ufw enable

Como o firewall está bloqueando atualmente todas as conexões, exceto o SSH, se você instalar e configurar serviços adicionais, precisará ajustar as configurações do firewall para permitir o tráfego.

Instalando o Java Runtime Enviroment

Para podermos executar a nossa aplicação, vamos precisar instalar o JRE (Java Runtime Enviroment), para isso executamos o seguinte comando:

apt install openjdk-17-jre-headless

Para verificarmos se a instalação foi bem sucedida, basta executar o comando java --version e a saída desse comando será algo semelhante ao conteúdo abaixo:

openjdk 17.0.7 2023-04-18
OpenJDK Runtime Environment (build 17.0.7+7-Ubuntu-0ubuntu122.04.2)
OpenJDK 64-Bit Server VM (build 17.0.7+7-Ubuntu-0ubuntu122.04.2, mixed mode, sharing)

Instalando o Nginx

A fim de disponibilizarmos a nossa aplicação na web, vamos precisar de um servidor HTTP, para esse artigo nós vamos utilizar o Nginx.

A instalação do Nginx pode ser feita com o seguinte comando:

apt install nginx

Para verificarmos se a instalação do Nginx foi bem sucedida podemos verificar o status do serviço do Nginx com o seguinte comando:

systemctl status nginx

A saída gerado pelo comando acima será algo semelhante ao conteúdo abaixo:

nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
     Active: active (running) since Mon 2023-07-31 07:27:49 UTC; 17s ago
       Docs: man:nginx(8)
    Process: 10076 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exit>
    Process: 10077 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, statu>
   Main PID: 10166 (nginx)
      Tasks: 2 (limit: 1116)
     Memory: 5.1M
        CPU: 27ms
     CGroup: /system.slice/nginx.service
             ├─10166 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
             └─10169 "nginx: worker process" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ">

Agora que temos o Nginx instalado, também precisamos habilitar o Nginx em nosso firewall, para isso execute o seguinte comando:

ufw allow 'Nginx Full'

Para verificarmos que de fato o Nginx foi habilitado em nosso firewall, basta acessar o código IP da nossa VPS no navegador que iremos visualizar a página de boas-vindas do Nginx.

Print da página de Boas-vindas do Nginx

Ao instalar o Nginx é criada uma pasta chamada www dentro do diretorio /var, essa pasta é onde comumente colocamos as nossas aplicações, então vamos criar uma nova pasta dentro de www que irá conter os arquivos da aplicação que iremos realizar o deploy. Então, execute o seguinte comando:

mkdir /var/www/spring

Nginx - Fundamentos
Curso Nginx - Fundamentos
Conhecer o curso

Preparando o projeto localmente

Agora nós já temos a configuração necessário em nosso servidor para que ele seja capaz de executar a nossa aplicação Spring. O que vamos precisar fazer é então preparar a aplicação localmente e então enviar essa aplicação para a VPS.

Eu já deixei pronta uma aplicação Spring Boot que iremos utilizar para exemplificar o processo de deploy, essa aplicação é bem simples, consiste basicamente em uma página de “Hello World” na rota principal da aplicação.

Executando a aplicação

Para testarmos a aplicação localmente vamos precisar clonar o repositório, entrar na pasta do projeto e então executar a aplicação. Para isso execute os seguintes comando no terminal.

git clone https://github.com/CleysonPH/spring-deploy-vps-example.git
cd spring-deploy-vps-example
mvn spring-boot:run

Após executar os comandos acima, acesse o link http://localhost:8080/ e você verá a seguinte página:

Pring da aplicação Spring sendo executada localmente

Gerando o arquivo JAR

As aplicações desenvolvidas com Spring Boot podem ser empacotadas em um arquivo .jar, esse arquivo é o build final de nossa aplicação, arquivo esse que precisamentos enviar para o nosso servidor.

Para gerar o arquivo JAR executamos o seguinte comando:

mvn clean package

Após a execução do comando acima, você verá que foi gerado um arquivo chamado vps-deploy-0.0.1-SNAPSHOT.jar localizado na pasta target.

Linux - Fundamentos para desenvolvedores
Curso Linux - Fundamentos para desenvolvedores
Conhecer o curso

Realizando o deploy do projeto

Agora que já conseguimos realizar o build da nossa aplicação e também já preparamos a nossa VPS para conseguir executar e disponibilizar a aplicação. Vamos de fato realizar o deploy do nosso projeto.

Enviando o arquivo JAR para o servidor

Para enviarmos o arquivo para JAR para dentro do nosso servidor vamos utilizar o SCP (Secure copy)

Para isso execute o seguinte comando:

scp target/vps-deploy-0.0.1-SNAPSHOT.jar root@165.232.148.181:/var/www/spring

Aqui está uma explicação detalhada do comando:

  • scp: É o comando que invoca a funcionalidade de cópia segura.
  • target/vps-deploy-0.0.1-SNAPSHOT.jar: É o caminho do arquivo que você deseja copiar. Neste caso, o arquivo é chamado “vps-deploy-0.0.1-SNAPSHOT.jar” e está localizado dentro da pasta “target”.
  • root@165.232.148.181: É o endereço IP ou nome de domínio do servidor remoto para o qual você deseja copiar o arquivo. O usuário “root” é usado para autenticação no servidor remoto.
  • :/var/www/spring: É o caminho do diretório de destino no servidor remoto onde o arquivo será copiado. Neste caso, o arquivo será copiado para o diretório “/var/www/spring” no servidor remoto.

Em resumo, o comando copiará o arquivo “vps-deploy-0.0.1-SNAPSHOT.jar” da pasta local “target” para o diretório “/var/www/spring” no servidor remoto com o endereço IP “165.232.148.181”, usando o usuário “root” para autenticação.

Executando o arquivo JAR no servidor

No servidor de produção nós podemos simplesmente executar o comando java -jar /var/www/vps-deploy-0.0.1-SNAPSHOT.jar para rodar a aplicação, porém, isso fará com que o terminal fique travado e assim que sairmos do terminal a aplicação também irá parar de executar. Então precisamos executar a aplicação de alguma maneira que o terminal não fique travado e que a mesma seja executada novamente caso a máquina, seja reiniciada.

Uma maneira de fazer isso é através da configuração de um serviço. Para isso precisamos de criar um arquivo de configuração que irá informar como esse serviço deve ser executado. Então devemos nos conectar novamente ao terminal do servidor através do SSH e então executar o seguinte comando:

nano /etc/system/system/spring.service

Com o comando acima vamos abrir o editor de texto nano em novo um arquivo chamado spring.service no diretório /etc/system/systemd, esse arquivo será o arquivo de configuração do nosso serviço.

Nesse arquivo vamos colocar o seguinte conteúdo:

[Unit]
Description=Aplicação Spring de teste para deploy na DigitalOcean

[Service]
WorkingDirectory=/var/www/spring
ExecStart=java -jar vps-deploy-0.0.1-SNAPSHOT.jar
User=root
Restar=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target

Aqui vai uma explicação detalhada do código de configuração que estamos utilizando:

  1. [Unit]: Esta seção contém metadados sobre o serviço. Neste caso, apenas a descrição do serviço está presente.
  2. [Service]: Esta seção contém informações sobre o serviço em si e como ele deve ser executado.
    • WorkingDirectory=/var/www/spring: Define o diretório de trabalho para o serviço. O serviço será iniciado a partir deste diretório.
    • ExecStart=java -jar vps-deploy-0.0.1-SNAPSHOT.jar: Especifica o comando que será executado para iniciar o serviço. Neste caso, ele inicia a aplicação Spring executando o arquivo JAR “vps-deploy-0.0.1-SNAPSHOT.jar” usando o comando “java -jar”.
    • User=root: Define o usuário sob o qual o serviço será executado. Neste caso, o serviço será executado com privilégios de superusuário (root).
    • Restart=on-failure: Indica que o serviço será reiniciado automaticamente se ele falhar inesperadamente (por exemplo, devido a uma exceção não tratada).
    • RestartSec=10: Especifica o intervalo de tempo (em segundos) após o qual o serviço será reiniciado, se necessário. Neste caso, após uma falha, o serviço será reiniciado após 10 segundos.
  3. [Install]: Esta seção especifica como o serviço deve ser instalado e configurado como parte do sistema.
    • WantedBy=multi-user.target: Indica que o serviço deve ser iniciado automaticamente quando o sistema estiver no modo multiusuário. Isso geralmente significa que o serviço será iniciado durante a inicialização do sistema.

Para salvar o conteúdo do arquivo e então sair do editor nano utilize os atalhos CTRL+o e depois CTRL+x.

Agora precisamos iniciar o serviço que foi configurado e também habilitar o serviço para que o mesmo sempre execute mesmo que o sistema seja reinicializado. Para isso execute os comandos:

systemctl start spring.service
systemctl enable spring.service

Para vermos os status do nosso serviço podemos executar o comando systemctl status spring.service e então veremos uma saída similar a seguinte:

spring.service - Aplicação Spring de teste para deploy na DigitalOcean
     Loaded: loaded (/etc/systemd/system/spring.service; enabled; vendor preset: enabled)
     Active: active (running) since Tue 2023-08-01 12:51:53 UTC; 4min 39s ago
   Main PID: 28525 (java)
      Tasks: 29 (limit: 1116)
     Memory: 128.8M
        CPU: 8.334s
     CGroup: /system.slice/spring.service
             └─28525 java -jar vps-deploy-0.0.1-SNAPSHOT.jar

Configurando o Nginx

Agora, a nossa aplicação já sendo executada em nosso servidor, porém ainda não temos acesso a mesmo pela web. Isso porque nós temos um firewall configurado que impede que conexões sejam feitas em nosso servidor e no momentos temos apenas o Nginx sendo habilitado para receber conexões.

Então precisamos configurar o Nginx para servir a nossa aplicação para o mundo externo. Para isso execute o seguinte comando:

nano /etc/nginx/sites-available/default

Com o comando acima vamos editar o arquivo de configuração padrão do Nginx e nesse arquivo vamos editar a seção location /, e colocar as configurações necessárias para o Nginx servir a aplicação para a web. Abaixo vou deixar a configuração completa do arquivo:

server {
        listen 80 default_server;
        listen [::]:80 default_server;

        root /var/www/html;

        server_name _;

        location / {
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header Host $http_host;
                proxy_pass http://127.0.0.1:8080;
                proxy_redirect off;
                try_files $uri $uri/ =404;
        }

}

Aqui está uma explicação das principais partes do código:

  1. server: Indica o início da configuração de um bloco de servidor. Isso permite definir as configurações específicas para esse servidor virtual.
  2. listen 80 default_server; e listen [::]:80 default_server;: Configura o servidor para escutar conexões HTTP na porta 80. A opção default_server significa que este servidor será usado como servidor padrão para qualquer solicitação que não corresponda a nenhum outro servidor virtual.
  3. root /var/www/html;: Define o diretório raiz para o servidor. Todos os arquivos do site estão localizados em “/var/www/html” neste caso.
  4. server_name _;: Especifica o nome do servidor virtual. Neste caso, o caractere sublinhado (_) é usado como um curinga, indicando que esse servidor virtual será o padrão usado para qualquer solicitação que não corresponda a um servidor virtual específico.
  5. location / { ... }: Define as configurações para a localização do servidor que corresponde ao caminho “/”. Isso é a configuração padrão para todas as solicitações não tratadas por outras localizações.
  6. Nas configurações location / { ... }, temos várias diretivas de proxy para passar as solicitações para o aplicativo ou serviço em execução na porta 8080 em localhost (127.0.0.1).
    • proxy_set_header: Define os cabeçalhos que serão enviados para o servidor backend (127.0.0.1:8080).
    • proxy_pass http://127.0.0.1:8080;: Define o endereço do servidor backend (aplicativo ou serviço) onde as solicitações serão encaminhadas.
    • proxy_redirect off;: Desativa a substituição automática de cabeçalhos “Location” nos cabeçalhos da resposta do servidor backend.
    • try_files $uri $uri/ =404;: Tenta servir o arquivo solicitado diretamente, ou se não existir, repassa para o servidor backend (127.0.0.1:8080).

Essa configuração é comum para atuar como um proxy reverso para aplicativos da web ou servidores de aplicativos que estão sendo executados na porta 8080 do localhost. O Nginx recebe as solicitações na porta 80, encaminha-as para o servidor de backend na porta 8080 e retorna as respostas para o cliente que fez a solicitação.

Agora podemos acessar a aplicação pela web, basta acessar o endereço IP da sua VPS pelo navegador, no meu caso a acessar o endereço http://165.232.148.181/ veremos a seguinte página.

Pring da aplicação Spring sendo executada na VPS

Conclusão

Neste artigo, exploramos o passo a passo de como preparar uma Virtual Private Server (VPS) para hospedar e disponibilizar uma aplicação Spring. Aprendemos a configurar uma VPS na plataforma DigitalOcean e como instalar o Java Runtime Environment (JRE) e o servidor web Nginx, elementos essenciais para executar e servir a aplicação.

Além disso, mostramos como realizar o deploy da aplicação, desde a geração do arquivo JAR localmente até a transferência e execução do mesmo na VPS. Ao configurar um serviço através do systemd, garantimos que a aplicação seja executada de forma contínua mesmo após reinicializações.

Com a VPS devidamente preparada e o Nginx configurado como proxy reverso, sua aplicação Spring está pronta para ser acessada pela web. É importante destacar que a segurança também foi considerada, visto que habilitamos um firewall para permitir apenas as conexões necessárias.

Seguindo esse guia, você estará pronto para hospedar suas aplicações web com eficiência, escalabilidade e segurança em uma VPS. Experimente e explore todas as possibilidades que essa poderosa ferramenta oferece para o desenvolvimento e disponibilização de suas aplicações online.

Autor(a) do artigo

Cleyson Lima
Cleyson Lima

Professor, programador, fã de One Piece e finge saber cozinhar. Cleyson é graduando em Licenciatura em Informática pelo IFPI - Campus Teresina Zona Sul, nos anos de 2019 e 2020 esteve envolvido em vários projetos coordenados pela secretaria municipal de educação da cidade de Teresina, onde o foco era introduzir alunos da rede pública no mundo da programação e robótica. Hoje é instrutor dos cursos de Spring na TreinaWeb, mas diz que seu coração sempre pertencerá ao Python.

Todos os artigos

Artigos relacionados Ver todos