Azure Container Apps で動かす Goアプリから Dapr 経由でHTTPとかSMTPのサービスを使ってみます。合わせて、よく使いそうなSendGridでメール送信、Cronで定期実行も試したので記載。
まずは単純にnet/httpパッケージで、サンプルコードを実行するHTTPサーバーを実装。
type service struct {
client dapr.Client
}
func main() {
cli, err := dapr.NewClient()
if err != nil {
panic(err)
}
defer cli.Close()
svc := &service{
client: cli,
}
http.HandleFunc("/cron", cron)
http.HandleFunc("/smtp", svc.Smtp)
http.HandleFunc("/sendgrid", svc.SendGrid)
http.HandleFunc("/http", svc.Http)
http.ListenAndServe(":8080", nil)
}
仕様を参考にContainer AppsでDaprを呼ぶコードを実装。コンポーネントの設定からContainer Appsで不要な schema を削除していきます。
Example
HTTP, SMTP, SendGridのOutput Bindingは、リクエスト内容は異なりますが、dapr.NewClient() で作ったclientでリクエストを送るだけですので基本的には同じです。
HTTP
HTTP binding spec
- name: http
type: bindings.http
version: v1
metadata:
- name: url
value: http://example.com
func (svc *service) Http(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
in := &dapr.InvokeBindingRequest{
Name: "http",
Operation: "get",
Data: []byte("\"Hello, HTTP.\""),
Metadata: map[string]string{"path": "/"},
}
out, err := svc.client.InvokeBinding(ctx, in)
if err != nil {
fmt.Fprint(w, err.Error())
return
}
data := string(out.Data)
log.Print("Hello, HTTP.")
fmt.Fprint(w, data)
}
SMTP binding spec
- name: smtp
type: bindings.smtp
version: v1
metadata:
- name: host
value: "example.com"
- name: port
value: "587"
- name: user
value: "USER"
- name: password
value: "PASSWORD"
- name: skipTLSVerify
value: true
- name: emailFrom
value: "test@example.com"
- name: emailTo
value: "test@example.com"
- name: subject
value: "Example Smtp"
func (svc *service) Smtp(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
in := &dapr.InvokeBindingRequest{
Name: "smtp",
Operation: "create",
Data: []byte("\"Hello, SMTP.\""),
Metadata: map[string]string{"subject": "SMTP"},
}
_, err := svc.client.InvokeBinding(ctx, in)
if err != nil {
fmt.Fprint(w, err.Error())
return
}
log.Print("Hello, SMTP.")
fmt.Fprint(w, "OK. SMTP.")
}
Twilio SendGrid
Twilio SendGrid binding spec
- name: sendgrid
type: bindings.twilio.sendgrid
version: v1
metadata:
- name: emailFrom
value: "test@example.com"
- name: emailTo
value: "test@example.com"
- name: subject
value: "Example SendGrid"
- name: apiKey
value: "APIKEY"
func (svc *service) SendGrid(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
in := &dapr.InvokeBindingRequest{
Name: "sendgrid",
Operation: "create",
Data: []byte("\"Hello, SendGrid.\""),
Metadata: map[string]string{"subject": "SendGrid"},
}
_, err := svc.client.InvokeBinding(ctx, in)
if err != nil {
fmt.Fprint(w, err.Error())
return
}
log.Print("Hello, SendGrid.")
fmt.Fprint(w, "OK. SendGrid.")
}
Cron
Cron binding spec
cronはコンポーネントの名前に設定したエンドポイントに、metadataに設定されたタイミングで HTTP POST リクエストが来ます。サンプルはログに「Hello, Cron.」と出力していますので、Log Analyticsの設定をしてログで確認。
- name: cron
type: bindings.cron
version: v1
metadata:
- name: schedule
value: "@every 10m"
func cron(w http.ResponseWriter, _ *http.Request) {
log.Print("Hello, Cron.")
fmt.Fprint(w, "OK. Cron.")
}

デプロイ
ACRなどを利用してAZコマンドで試すときは、
components.yaml などに上記のコンポーネント設定をまとめて1ファイルで記載し、az containerapp create の dapr-components で、そのファイルを指定。
コマンド例
az containerapp create `
--name $NAME `
--resource-group $RESOURCE_GROUP `
--environment $CONTAINERAPPS_ENVIRONMENT `
--image $IMAGE `
--target-port 8080 `
--ingress 'external' `
--min-replicas 1 `
--max-replicas 1 `
--enable-dapr `
--dapr-app-port 8080 `
--dapr-app-id $ID `
--dapr-components "./components.yaml" `
--registry-login-server $LOG_SERVER `
--registry-username $USERNAME `
--registry-password $PASSWORD
無事デプロイ完了。ポータルでも確認できました。
