🤖

Go で書いた Web アプリを AWS Copilot CLI を使って AWS App Runner にデプロイする

2021/05/21に公開
  • とりあえず動かしたい人向けのメモ
  • AWS Copilot CLI のインストールやセットアップについては公式ドキュメントを参照

Go でアプリケーションを実装

とりあえず HTTP リクエストを受け取ったら UUID を返す Web アプリを実装

アプリ実装
package main

import (
	"fmt"
	"log"
	"net/http"
	"os"

	"github.com/google/uuid"
)

func handler(w http.ResponseWriter, r *http.Request) {

	uuidv4, err := uuid.NewRandom()
	if err != nil {
		fmt.Fprint(w, err)
		return
	}

	_, err = fmt.Fprint(w, uuidv4)
	if err != nil {
		return
	}
}

func main() {

	port := os.Getenv("PORT")

	if port == "" {
		port = "80"
	}

	http.HandleFunc("/", handler)
	log.Fatal(http.ListenAndServe(":"+port, nil))

}

Dockerfile を作成

Dockerfile 例
FROM golang:1.15.8-buster as gobuilder
WORKDIR /go/src/app
COPY go.mod go.sum ./
RUN go mod download
COPY main.go ./
RUN go build -ldflags="-w -s" -o /go/bin/app

FROM gcr.io/distroless/base
COPY --from=gobuilder /go/bin/app /
CMD ["/app"]

copilot で App Runner にデプロイ

copilot init して以下のように指定していけば OK

$ copilot init
Use existing application: No
Application name: hello-app-runner-app
Workload type: Request-Driven Web Service
Service name: uuid-service
Dockerfile: ./Dockerfile
no EXPOSE statements in Dockerfile ./Dockerfile
Port: 80
Deploy: Yes
実行例
$ copilot init
Note: It's best to run this command in the root of your Git repository.
Welcome to the Copilot CLI! We're going to walk you through some questions
to help you get set up with a containerized application on AWS. An application is a collection of
containerized services that operate together.

Use existing application: No
Application name: hello-app-runner-app
Workload type: Request-Driven Web Service
Service name: uuid-service
Dockerfile: ./Dockerfile
no EXPOSE statements in Dockerfile ./Dockerfile
Port: 80
Ok great, we'll set up a Request-Driven Web Service named uuid-service in application hello-app-runner-app listening on port 80.

✔ Created the infrastructure to manage services and jobs under application hello-app-runner-app.

✔ Wrote the manifest for service uuid-service at copilot/uuid-service/manifest.yml
Your manifest contains configurations like your container size and port (:80).

✔ Created ECR repositories for service uuid-service.

All right, you're all set for local development.
Deploy: Yes

✔ Linked account 000000000000 and region ap-northeast-1 to application hello-app-runner-app.

✔ Proposing infrastructure changes for the hello-app-runner-app-test environment.
- Creating the infrastructure for the hello-app-runner-app-test environment.  [create complete]  [86.3s]
  - An IAM Role for AWS CloudFormation to manage resources                    [create complete]  [24.1s]
  - An ECS cluster to group your services                                     [create complete]  [7.4s]
  - Enable long ARN formats for the authenticated AWS principal               [create complete]  [2.5s]
  - An IAM Role to describe resources in your environment                     [create complete]  [24.7s]
  - A security group to allow your containers to talk to each other           [create complete]  [4.6s]
  - An Internet Gateway to connect to the public internet                     [create complete]  [14.0s]
  - Private subnet 1 for resources with no internet access                    [create complete]  [18.6s]
  - Private subnet 2 for resources with no internet access                    [create complete]  [18.6s]
  - Public subnet 1 for resources that can access the internet                [create complete]  [18.6s]
  - Public subnet 2 for resources that can access the internet                [create complete]  [18.6s]
  - A Virtual Private Cloud to control networking of your AWS resources       [create complete]  [16.5s]
✔ Created environment test in region ap-northeast-1 under application hello-app-runner-app.
Environment test is already on the latest version v1.4.0, skip upgrade.
Sending build context to Docker daemon  9.216kB

Step 1/10 : FROM golang:1.15.8-buster as gobuilder
 ---> 7185d074e387
Step 2/10 : WORKDIR /go/src/app
 ---> Using cache
 ---> 4590930d6d64
Step 3/10 : COPY go.mod go.sum ./
 ---> Using cache
 ---> afbb960dc817
Step 4/10 : RUN go mod download
 ---> Using cache
 ---> 2a4a4045965a
Step 5/10 : COPY main.go ./
 ---> 2013b5f526d0
Step 6/10 : RUN go generate
 ---> Running in f6ac0ff48e1a
Removing intermediate container f6ac0ff48e1a
 ---> fe953db97d66
Step 7/10 : RUN go build -ldflags="-w -s" -o /go/bin/app
 ---> Running in 51ffa0a7d6d1
Removing intermediate container 51ffa0a7d6d1
 ---> b361588bb486
Step 8/10 : FROM gcr.io/distroless/base
 ---> a4cf6da932ac
Step 9/10 : COPY --from=gobuilder /go/bin/app /
 ---> 625ca2f3a6d3
Step 10/10 : CMD ["/app"]
 ---> Running in 8a3c59f93fed
Removing intermediate container 8a3c59f93fed
 ---> d71e55b6f2ad
Successfully built d71e55b6f2ad
Successfully tagged 000000000000.dkr.ecr.ap-northeast-1.amazonaws.com/hello-app-runner-app/uuid-service:latest
WARNING! Your password will be stored unencrypted in /home/ec2-user/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded
The push refers to repository [000000000000.dkr.ecr.ap-northeast-1.amazonaws.com/hello-app-runner-app/uuid-service]
f2ab491165eb: Pushed 
5d09c2db1d76: Pushed 
417cb9b79ade: Pushed 
latest: digest: sha256:9eebec4bd13dc05aa788f3b4f78050763f489de2ab536b291371c7f43afca965 size: 949
✔ Proposing infrastructure changes for stack hello-app-runner-app-test-uuid-service
- Creating the infrastructure for stack hello-app-runner-app-test-uuid-service    [create complete]  [247.6s]
  - An IAM Role for App Runner to use on your behalf to pull your image from ECR  [create complete]  [23.1s]
  - An IAM role to control permissions for the containers in your service         [create complete]  [23.1s]
  - An App Runner service to run and manage your containers                       [create complete]  [213.5s]
✔ Deployed uuid-service, you can access it at https://3ydgmrmaee.ap-northeast-1.awsapprunner.com.

アプリにリクエストしてみる

UUID がレスポンスされれば OK

$ curl https://3ydgmrmaee.ap-northeast-1.awsapprunner.com
fcf14357-f247-43e5-9c4f-cddabf1a8266

copilot によって生成されたファイル

$ tree -a copilot/
copilot/
├── uuid-service
│   └── manifest.yml
└── .workspace

1 directory, 2 files

後片付け

copilot app delete
実行例
$ copilot app delete
Are you sure you want to delete application hello-app-runner-app? Yes
✔ Deleted service uuid-service from environment test.
✔ Deleted resources of service uuid-service from application hello-app-runner-app.
✔ Deleted service uuid-service from application hello-app-runner-app.
✔ Deleted environment test from application hello-app-runner-app.
✔ Cleaned up deployment resources.
✔ Deleted application resources.
✔ Deleted application configuration.
✔ Deleted local .workspace file.

感想

  • AWS App Runner
    • サクッと使えて良い
    • 複雑なアプリケーションでなければ、自前で ELB とか Auto Scaling Group とか VPC とか管理したくない・・・
      • このあたりは Heroku や Cloud Run 使えば良いかなと思っていたが、新たな選択肢ができた
    • 今回は AWS Copilot CLI を使用したデプロイだったが、マネジメントコンソールからもサクッと使える
  • AWS Copilot CLI

試した環境

$ cat /etc/os-release 
NAME="Amazon Linux"
VERSION="2"
ID="amzn"
ID_LIKE="centos rhel fedora"
VERSION_ID="2"
PRETTY_NAME="Amazon Linux 2"
ANSI_COLOR="0;33"
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2"
HOME_URL="https://amazonlinux.com/"
$ uname -a
Linux ip-172-31-255-5.ap-northeast-1.compute.internal 4.14.231-173.361.amzn2.x86_64 #1 SMP Mon Apr 26 20:57:08 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
$ docker --version
Docker version 19.03.13-ce, build 4484c46
$ copilot --version
copilot version: v1.7.0

Discussion