フォルダ構成
aca-terraform-sample/
├─ terraform/
│ ├─ main.tf # Terraform リソース定義
│ # 変数定義
├─ server.js # Node.js アプリ本体
├─ Dockerfile # Docker イメージ定義
├─ .gitignore # .terraform/, node_modules/, .env など除外
└─ README.md
az group create --name aca-rg --location japaneast
docker build -t myapp:latest .
docker tag myapp:latest myacaregistry1234.azurecr.io/myapp:latest
az acr login --name myacaregistry1234
docker push myacaregistry1234.azurecr.io/myapp:latest
az acr repository show-manifests --name myacaregistry1234 --repository myapp --output table
main.tf
// ...existing code...
terraform {
required_version = ">= 1.9.5"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = ">= 3.109.0"
}
}
}
provider "azurerm" {
features {}
subscription_id = ""
}
resource "azurerm_resource_group" "rg" {
name = "aca-rg"
location = "japaneast"
}
resource "azurerm_container_registry" "acr" {
name = "myacaregistry1234"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
sku = "Basic"
admin_enabled = true
}
resource "azurerm_container_app_environment" "env" {
name = "myapp-env"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
}
resource "azurerm_container_app" "app" {
name = "myapp"
resource_group_name = azurerm_resource_group.rg.name
container_app_environment_id = azurerm_container_app_environment.env.id
revision_mode = "Single"
# identity は残しておいても問題ありません(将来的にマネージドIDを使う場合に有用)
identity {
type = "SystemAssigned"
}
template {
container {
name = "myapp"
image = "${azurerm_container_registry.acr.login_server}/myapp:latest"
cpu = 0.25
memory = "0.5Gi"
env {
name = "PORT"
value = "8080"
}
}
}
ingress {
external_enabled = true
target_port = 8080
traffic_weight {
latest_revision = true
percentage = 100
}
}
# 管理者ユーザー方式で認証(password は secret を介して渡す)
registry {
server = azurerm_container_registry.acr.login_server
username = azurerm_container_registry.acr.admin_username
password_secret_name = "acr-admin-password"
}
# シークレットとして ACR の admin password を渡す(stateには含まれます)
secret {
name = "acr-admin-password"
value = azurerm_container_registry.acr.admin_password
}
tags = {
environment = "dev"
}
}
# ...existing code...
output "acr_login_server" {
value = azurerm_container_registry.acr.login_server
}
output "container_app_name" {
value = azurerm_container_app.app.name
}
output "container_app_rg" {
value = azurerm_resource_group.rg.name
}
output "container_app_env_id" {
value = azurerm_container_app_environment.env.id
}
server.js
const http = require("http");
const port = 8080;
const server = http.createServer((req, res) => {
res.writeHead(200, { "Content-Type": "text/plain" });
res.end("Hello from Azure Container Apps!\n");
});
server.listen(port, () => {
console.log(`Server running at http://localhost:${port}/`);
});
Dockerfile
FROM node:20-alpine
WORKDIR /usr/src/app
RUN apk update && apk upgrade
COPY server.js .
EXPOSE 8080
CMD ["node", "server.js"]