Deploy do Quarkus no Fly.io

Marcus Paulo
9 min readJan 9, 2023

--

Fonte: https://www.flickr.com/photos/marcus-paulo/8281933715/

Introdução

O objetivo desse post, será criar uma aplicação simples utilizando o framework Quarkus e publicar no serviço Fly.io. Antes de iniciar a parte prática, será necessário fazer uma pequena introdução sobre o Fly.io e o Quarkus.

Fly.io

O serviço Fly.io é uma plataforma global de distribuição de aplicativos. As aplicações são executadas em microVMs(Virtual Machines) Firecracker em todo o mundo. Para mais informações acesse a documentação oficial: https://fly.io/docs/.

Até o momento da publicação desse post, o Fly.io, não permite o Deploy de uma aplicação Java, sendo assim, vamos utilizar o Docker para realizar esse Deploy.

Quarkus

No dia 29 de março de 2019, a Red Hat lançou o Quarkus , um framework Java nativo do Kubernetes feito sob medida para o GraalVM e OpenJDK HotSpot . O Quarkus visa tornar o Java uma plataforma líder em ambientes serverless e Kubernetes, oferecendo aos desenvolvedores um modelo unificado de programação reativa e imperativa, para mais informações, visite o site oficial: https://quarkus.io/.

Adicionalmente, te convido a conhecer um repositório no Github com uma curadoria sobre vários assuntos relacionados ao Quarkus. Qualquer feedback é super bem vindo e caso goste do projeto, fique à vontade para dar uma estrela no repositório https://github.com/marcuspaulo/awesome-quarkus.

Iniciando as configurações no Fly.io

Para começar, será necessário criar uma conta no Fly.io

Criando uma nova conta

  1. Acesse o site: fly.io.
  2. Clique no botão “Sign In”
Tela inicial do Fly.io

3. Na próxima página, clique no botão: “Need on Account”

4. Agora escolha uma das duas opções: Acessar através da sua conta do Github ou através do preenchimento dos seus dados cadastrais, conforme a imagem abaixo.

Tela de registro

Após a criação da conta, faça o login e acesse o Dashboard do Fly.io. Nesse Dashboard, será exibido um panorama geral, incluindo todas as Apps, pagamentos, cobranças e muito mais.

Dashboard do Fly.io

No próximo tópico, será apresentado como instalar o Fly CTL CLI (Command Line Interface — Interface de linha de comando), essa ferramenta será útil para o Deploy da aplicação, para mais informações, acesse a documentação oficial. https://fly.io/docs/hands-on/install-flyctl/

Instalando o Fly ctl CLI

Passo a passo:

macOS

Se você tiver o gerenciador de pacotes Homebrew instalado, o flyctl pode ser instalado executando:

brew install flyctl

Caso contrário, você pode executar o seguinte script de instalação:

curl -L [<https://fly.io/install.sh>](<https://fly.io/install.sh>) | sh

Linux

Execute o script de instalação:

curl -L [<https://fly.io/install.sh>](<https://fly.io/install.sh>) | sh

Windows

Execute o script de instalação no Powershell:

iwr [<https://fly.io/install.ps1>](<https://fly.io/install.ps1>) -useb | iex

Criando um projeto em Quarkus

Nesse tópico, abordaremos alguma das formas para criar uma aplicação simples no Quarkus. Você pode criar sua aplicação utilizando o Quarkus-CLI (será apresentada nesse artigo), através do Maven, ou ainda através do site: https://code.quarkus.io/

Passo 1: Crie um projeto no Quarkus

quarkus create quarkus-fly

Abra o projeto em sua IDE favorita e escreva alguma mensagem no arquivo **GreetingResource.java**

IDE Alteração no código

Em seguida, coloque a mesma mensagem na classe de teste **GreetingResourceTest.java**, conforme a imagem abaixo:

IDE alteração na classe de teste

Após essas alterações, abra o terminal e execute o comando de Login no Fly.io e siga os procedimentos solicitados.

flyctl auth login

Fazendo um Deploy manual

Antes de iniciar o processo de Deploy manual, será necessário criar o pacote da aplicação, para isso, basta digitar o comando: ./mvnw clean package, conforme o exemplo abaixo

❯ ./mvnw clean package
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------< org.acme:quarkus-fly >------------------------
[INFO] Building quarkus-fly 1.0.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ quarkus-fly ---
[INFO] Deleting /Users/marcus/Developer/java/quarkus-fly/quarkus-fly/target
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ quarkus-fly ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 2 resources
[INFO]
[INFO] --- quarkus-maven-plugin:2.14.0.Final:generate-code (default) @ quarkus-fly ---
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ quarkus-fly ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/marcus/Developer/java/quarkus-fly/quarkus-fly/target/classes
[INFO]
[INFO] --- quarkus-maven-plugin:2.14.0.Final:generate-code-tests (default) @ quarkus-fly ---
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ quarkus-fly ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/marcus/Developer/java/quarkus-fly/quarkus-fly/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ quarkus-fly ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 2 source files to /Users/marcus/Developer/java/quarkus-fly/quarkus-fly/target/test-classes
[INFO]
[INFO] --- maven-surefire-plugin:3.0.0-M7:test (default-test) @ quarkus-fly ---
[INFO] Using auto detected provider org.apache.maven.surefire.junitplatform.JUnitPlatformProvider
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running org.acme.GreetingResourceTest
2023-01-08 10:39:33,406 INFO [io.quarkus] (main) quarkus-fly 1.0.0-SNAPSHOT on JVM (powered by Quarkus 2.14.0.Final) started in 0.902s. Listening on: <http://localhost:8081>
2023-01-08 10:39:33,407 INFO [io.quarkus] (main) Profile test activated.
2023-01-08 10:39:33,407 INFO [io.quarkus] (main) Installed features: [cdi, resteasy-reactive, smallrye-context-propagation, vertx]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.355 s - in org.acme.GreetingResourceTest
2023-01-08 10:39:33,990 INFO [io.quarkus] (main) quarkus-fly stopped in 0.014s
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ quarkus-fly ---
[INFO] Building jar: /Users/marcus/Developer/java/quarkus-fly/quarkus-fly/target/quarkus-fly-1.0.0-SNAPSHOT.jar
[INFO]
[INFO] --- quarkus-maven-plugin:2.14.0.Final:build (default) @ quarkus-fly ---
[INFO] [io.quarkus.deployment.QuarkusAugmentor] Quarkus augmentation completed in 810ms
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5.720 s
[INFO] Finished at: 2023-01-08T10:39:34-03:00
[INFO] ------------------------------------------------------------------------

Ainda no terminal, digite o comando abaixo, para iniciar o processo de Deploy no Fly.io

❯ fly launch --dockerfile src/main/docker/Dockerfile.jvm
Creating app in /Users/marcus/Developer/java/quarkus-fly/
Scanning source code
Detected a Dockerfile app
? Choose an app name (leave blank to generate one):

No próximo passo, você terá que escolher em qual região ficará hospedado a sua aplicação. Eu optei por escolher a região de São Paulo, porém, fique à vontade para escolher qualquer outra região.

**Choose a region for deployment:  [Use arrows to move, type to filter]**
Amsterdam, Netherlands (ams)
Paris, France (cdg)
Denver, Colorado (US) (den)
Dallas, Texas (US) (dfw)
Secaucus, NJ (US) (ewr)
Frankfurt, Germany (fra)
> São Paulo (gru)
Hong Kong, Hong Kong (hkg)
Ashburn, Virginia (US) (iad)
Johannesburg, South Africa (jnb)
Los Angeles, California (US) (lax)
London, United Kingdom (lhr)
Chennai (Madras), India (maa)
Madrid, Spain (mad)
Miami, Florida (US) (mia)

Na próxima etapa, você ter que escolher se deseja utilizar ou não um banco de dados. Para esse artigo, eu vou criar sem o Banco de dados, porém, se vocês quiserem um artigo de como conectar com o banco de dados, deixe um comentário.

? Would you like to set up a Postgresql database now? No

A próxima pergunta é se você deseja configurar o Redis, no meu caso, eu marquei a opção Não.

? Would you like to set up an Upstash Redis database now? (y/N): N

A última pergunta, é se você deseja realizar um Deploy agora:

? Would you like to deploy now? (y/N) Y

Após todos esses passos, será criado um arquivo de configuração chamado: fly.toml, conforme o exemplo abaixo:

# fly.toml file generated for quarkus-fly
app = "quarkus-fly"
kill_signal = "SIGINT"
kill_timeout = 5
processes = []
[build]
dockerfile = "src/main/docker/Dockerfile.jvm"
[env][experimental]
allowed_public_ports = []
auto_rollback = true
[[services]]
http_checks = []
internal_port = 8080
processes = ["app"]
protocol = "tcp"
script_checks = []
[services.concurrency]
hard_limit = 25
soft_limit = 20
type = "connections"
[[services.ports]]
force_https = true
handlers = ["http"]
port = 80
[[services.ports]]
handlers = ["tls", "http"]
port = 443
[[services.tcp_checks]]
grace_period = "1s"
interval = "15s"
restart_limit = 0
timeout = "2s"

Log completo do Fly launch

❯ fly launch --dockerfile src/main/docker/Dockerfile.jvm
An existing fly.toml file was found for app quarkus-fly
App is not running, deploy...
==> Building image
Remote builder fly-builder-weathered-river-1197 ready
==> Creating build context
--> Creating build context done
==> Building image with Docker
--> docker host: 20.10.12 linux x86_64
[+] Building 5.9s (0/1)
[+] Building 4.2s (9/9) FINISHED
=> [internal] load remote build context 0.0s
=> copy /context / 0.1s
=> [internal] load metadata for registry.access.redhat.com/ubi8/openjdk-17:1.14 3.5s
=> CACHED [1/5] FROM registry.access.redhat.com/ubi8/openjdk-17:1.14@sha256:e584c314986211bfbf 0.0s
=> [2/5] COPY --chown=185 target/quarkus-app/lib/ /deployments/lib/ 0.1s
=> [3/5] COPY --chown=185 target/quarkus-app/*.jar /deployments/ 0.0s
=> [4/5] COPY --chown=185 target/quarkus-app/app/ /deployments/app/ 0.0s
=> [5/5] COPY --chown=185 target/quarkus-app/quarkus/ /deployments/quarkus/ 0.0s
=> exporting to image 0.1s
=> => exporting layers 0.1s
=> => writing image sha256:c816918be6d48d27d964939063914531d679823f74a3929d0e0b7f647a89850d 0.0s
=> => naming to registry.fly.io/quarkus-fly:deployment-01GP8SVMM7Z8TNVT1ZCJEKX3B2 0.0s
--> Building image done
==> Pushing image to fly
The push refers to repository [registry.fly.io/quarkus-fly]
146e51500226: Pushed
6b817fc68003: Pushed
e31dbefb9e5f: Pushed
96a06e23bd71: Pushed
778a038154ae: Pushed
52cbfc36b72b: Pushed
deployment-01GP8SVMM7Z8TNVT1ZCJEKX3B2: digest: sha256:a26abc3a308af657ca891553a5fef0385a5281b96eabc1d85290b46614aadbd0 size: 1582
--> Pushing image done
image: registry.fly.io/quarkus-fly:deployment-01GP8SVMM7Z8TNVT1ZCJEKX3B2
image size: 410 MB
==> Creating release
--> release v2 created
--> You can detach the terminal anytime without stopping the deployment
==> Monitoring deployment
Logs: <https://fly.io/apps/quarkus-fly/monitoring>
1 desired, 1 placed, 0 healthy, 0 unhealthy [health checks: 1 total, 1 passing]

Pronto, o Deploy foi realizado com sucesso. Em seguida, abra no navegador e acesse o Dashboard do Fly.io. Após isso, basta clicar em sua aplicação para carregar os detalhes.

Dashboard com a aplicação no Fly.io

Nos detalhes da aplicação, você terá um Dasboard com muitas informações, incluindo consumo de memória, monitoramento, métricas, certificados e outras informações.

Detalhes da aplicação no Dashboard do Fly.io

Para acessar a aplicação, clique no endereço que está abaixo do Hostname. Na imagem abaixo, é possível ver a tela inicial do Quarkus.

Para acessar a API, clique no @Path /hello, o Quarkus vai direcionar você para o endereço correto.

Tela inicial do Quarkus

Testando a API:

Resultado do teste da Api

Possiveis erros

Abaixo, seguem possíveis soluções de dois problemas que aconteceram durante o deploy

**fly launch --dockerfile src/main/docker/Dockerfile.jvm**
An existing fly.toml file was found for app quarkus-fly
App is not running, deploy...
==> Building image
Remote builder fly-builder-wandering-glade-3735 ready
==> Creating build context
--> Creating build context done
==> Building image with Docker
--> docker host: 20.10.12 linux x86_64
[+] Building 6.0s (0/1)
[+] Building 0.0s (2/2) FINISHED
=> CACHED [internal] load remote build context 0.0s
=> CACHED copy /context / 0.0s
Error failed to fetch an image or build from source: error building: failed to
solve with frontend dockerfile.v0: failed to read dockerfile:
open /data/docker/tmp/buildkit-mount775098382/src/main/docker/Dockerfile.jvm:
no such file or directory

Ou esse erro:

==> Building image
Remote builder fly-builder-shy-surf-3723 ready
==> Creating build context
--> Creating build context done
==> Building image with Docker
--> docker host: 20.10.12 linux x86_64
Sending build context to Docker daemon 186.1kB
[+] Building 3.6s (8/8) FINISHED
=> [internal] load remote build context 0.0s
=> copy /context / 0.0s
=> [internal] load metadata for registry.access.redhat.com/ubi8/openjdk-17:1.14 3.5s
=> [1/5] FROM registry.access.redhat.com/ubi8/openjdk-17:1.14@sha256:e584c314986211bfbfd4fc5f75e3972f75eb7f05adf52c2748ee315fef80bea3 0.0s
=> => resolve registry.access.redhat.com/ubi8/openjdk-17:1.14@sha256:e584c314986211bfbfd4fc5f75e3972f75eb7f05adf52c2748ee315fef80bea3 0.0s
=> ERROR [2/5] COPY --chown=185 target/quarkus-app/lib/ /deployments/lib/ 0.0s
=> CACHED [3/5] COPY --chown=185 target/quarkus-app/*.jar /deployments/ 0.0s
=> ERROR [4/5] COPY --chown=185 target/quarkus-app/app/ /deployments/app/ 0.0s
=> ERROR [5/5] COPY --chown=185 target/quarkus-app/quarkus/ /deployments/quarkus/ 0.0s
------
> [2/5] COPY --chown=185 target/quarkus-app/lib/ /deployments/lib/:
------
------
> [4/5] COPY --chown=185 target/quarkus-app/app/ /deployments/app/:
------
------
> [5/5] COPY --chown=185 target/quarkus-app/quarkus/ /deployments/quarkus/:
------
Error failed to fetch an image or build from source: error building: failed to compute cache key: "/target/quarkus-app/quarkus" not found: not found

Solução

No arquivo .dockerignore, comente a seguinte linha

# **/target <-- Comment this line
# flyctl launch added from .gitignore
#Maven
# **/target <-- Comment this line
**/pom.xml.tag
**/pom.xml.releaseBackup
**/pom.xml.versionsBackup
**/release.properties
**/.flattened-pom.xml
(Hidden)

Código-fonte

https://github.com/marcuspaulo/quarkus-fly

Espero que você tenha gostado desse artigo. Muito obrigado e até a próxima.

--

--