A Quarkus-based Todo API deployed to Azure Container Apps using Terraform and Azure Developer CLI (azd).
┌────────────────────────────────────────────────────────────────┐
│ Azure Resource Group │
│ │
│ ┌──────────────────┐ ┌──────────────────────────────────┐ │
│ │ Container │ │ Container Apps Environment │ │
│ │ Registry (ACR) │───▶│ │ │
│ └──────────────────┘ │ ┌─────────────────────────────┐ │ │
│ │ │ Backend Container App │ │ │
│ │ │ (Quarkus Todo API) │ │ │
│ | | | | |
│ │ └─────────────────────────────┘ │ │
│ └──────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────┐ │
│ │ PostgreSQL Flexible Server │ │
│ │ - Database: todo │ │
│ └──────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Log Analytics Workspace │ │
│ └──────────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────┘
- Azure CLI
- Azure Developer CLI (azd)
- Terraform >= 1.0
- Docker
- Java 21 (for local development)
- Maven (for local development)
.
├── azure.yaml # Azure Developer CLI configuration
├── infra/ # Terraform infrastructure
│ ├── main.tf # Main configuration using modules
│ ├── variables.tf # Input variables
│ ├── outputs.tf # Output values
│ ├── main.tfvars.json # azd parameter file
│ └── modules/ # Terraform modules
│ ├── resource-group/ # Resource group module
│ ├── container-registry/# ACR module
│ ├── postgresql/ # PostgreSQL module
│ └── container-apps/ # Container Apps module
└── src/
└── backend/ # Quarkus application
├── Dockerfile
├── pom.xml
└── src/
└── main/
├── java/ # Java source code
└── resources/# Application configuration
azd auth logincd src/backend
./mvnw package -DskipTests
cd ../..azd upThis command will:
- Prompt for environment name and Azure location
- Provision all Azure resources using Terraform
- Build and push the Docker image to ACR
- Deploy the application to Container Apps
After deployment, the API will be available at the URL shown in the output:
BACKEND_URI = "https://backend.<unique-id>.azurecontainerapps.io"
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/todos | List all todos |
| POST | /api/todos | Create a new todo |
# Get all todos
curl https://backend.<unique-id>.azurecontainerapps.io/api/todos
# Create a todo
curl -X POST https://backend.<unique-id>.azurecontainerapps.io/api/todos \
-H "Content-Type: application/json" \
-d '{"description": "Learn Azure", "details": "Deploy apps to ACA"}'Creates an Azure Resource Group to contain all resources.
Provisions Azure Container Registry (ACR) for storing Docker images.
Deploys Azure Database for PostgreSQL Flexible Server with:
- Auto-generated secure password
- Firewall rule for Azure services
- Database named
todo
Creates the Container Apps environment and application with:
- Log Analytics workspace for monitoring
- Ingress configuration for external access
- Environment variables for database connection
- Auto-scaling (0-3 replicas)
docker run -d \
--name postgres \
-e POSTGRES_PASSWORD=postgres \
-e POSTGRES_DB=todo \
-p 5432:5432 \
postgres:16cd src/backend
./mvnw quarkus:devThe API will be available at http://localhost:8080/api/todos
| Variable | Description | Default |
|---|---|---|
| QUARKUS_DATASOURCE_JDBC_URL | PostgreSQL connection URL | jdbc:postgresql://localhost:5432/todo |
| QUARKUS_DATASOURCE_USERNAME | Database username | postgres |
| QUARKUS_DATASOURCE_PASSWORD | Database password | postgres |
| QUARKUS_HIBERNATE_ORM_DATABASE_GENERATION | Schema generation strategy | drop-and-create (dev) / update (prod) |
# Deploy everything
azd up
# Provision infrastructure only
azd provision
# Deploy application only (after code changes)
azd deploy
# View deployed resources
azd show
# Tear down all resources
azd down
# View logs
azd monitor --logsEnsure you're using Java 21:
java -version
export JAVA_HOME="/opt/homebrew/opt/openjdk@21/libexec/openjdk.jdk/Contents/Home"Check the logs:
az containerapp logs show \
--name backend \
--resource-group <resource-group> \
--followVerify the PostgreSQL firewall allows Azure services:
az postgres flexible-server firewall-rule list \
--resource-group <resource-group> \
--name <server-name>To delete all Azure resources:
azd downMIT