---
# System prepended metadata

title: App Runner 入門
tags: [YouTube]

---

###### tags: `YouTube`

# App Runner 入門

## IAM ユーザの作成

![](https://i.imgur.com/S9SGXb1.jpg)

![](https://i.imgur.com/peZspz4.jpg)

![](https://i.imgur.com/p2QVpb2.png)

![](https://i.imgur.com/OEXI3Je.jpg)

![](https://i.imgur.com/U81WnHw.png)

![](https://i.imgur.com/TL2xmWB.jpg)

![](https://i.imgur.com/pJOHgix.jpg)

![](https://i.imgur.com/NHYS2BM.jpg)

![](https://i.imgur.com/0KHn3ph.png)


```bash
$ aws configure --profile apprunner-tutorial
```

対話型の設定画面が現れる。

```
AWS Accrss Key ID [None]: 取得したアクセスキー ID
AWS Secret Access Key [None]: 取得したシークレットアクセスキー
Default region name [None]: ap-northeast-1
Default output format [None]: json
```

## AWS CDK によるリソースの作成

### 環境構築

#### Node.js のインストール

まずは、Node.js をインストールする。
Node.js のバージョン管理システムである Nodebrew を使うため、最初に **Homebrew** をインストールする。


```bash
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

インストールできたら、バージョンを確認。
バージョンが表示されれば OK。

```bash
$ brew -v
Homebrew 3.6.21
```

続いて、Nodebrew をインストールする。

```
$ brew install nodebrew
```

インストールできたら、バージョンを確認。
バージョンが表示されれば OK。

```bash
$ nodebrew -v
nodebrew 1.0.1
```

次に、Nodebrew を使って Node.js の安定版をインストールする。

```bash
$ nodebrew install-binary stable
```

インストールされたバージョンを確認する。

```bash
$ nodebrew ls
```

2023/02/22 現在、安定版は v18.14.2 であるため、v18.14.2 を有効化する。

```bash
nodebrew use v18.14.0
```

最後に PATH を通す。
zsh を使っている場合は下記のコマンドを実行する。

```bash
$ echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.zshrc
$ source ~/.zshrc
```

bash を使っている場合は下記のコマンドを実行する。

```bash
$ echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.bash_profile
$ source ~/.bash_profile
```

Node.js のバージョンを確認すると、v18.14.0 が表示されるはず。

```
$ node -v
v18.14.0
```

これで、Node.js のインストールが完了。

#### npm のインストール

続いて、下記コマンドを用いて npm をインストールする。

```bash
$ npm install -g npm
```

インストールされたバージョンを確認する。

```bash
$ npm -v
9.4.2
```

#### AWS CDK CLI のインストール

最後に、下記コマンドを用いて AWS CDK CLI のインストールする。

```bash
$ npm install -g aws-cdk
```

インストールされたバージョンを確認する。

```bash
$ cdk --version
2.64.0 (build fb67c77)
```

### CDK プロジェクトを作成する

新しいディレクトリの作成。

```bash
$ mkdir apprunner-tutorial && cd apprunner-tutorial
```

プログラミング言語として今回は TypeScript を採用する。

```bash
$ cdk init app --language typescript
```

### 必要なライブラリのインストール

App Runner コンストラクトライブラリをインストールする。

```bash
$ npm install @aws-cdk/aws-apprunner-alpha
```

### Stack の設定

bin/apprunner-tutorial.ts

```typescript
#!/usr/bin/env node
import "source-map-support/register";
import * as cdk from "aws-cdk-lib";
import { ApprunnerTutorialStack } from "../lib/apprunner-tutorial-stack";

const app = new cdk.App();
new ApprunnerTutorialStack(app, "ApprunnerTutorialStack", {
  env: { account: "761817748648", region: "ap-northeast-1" },
});
```

env の account は、IAM ユーザを作成した AWS アカウント ID を指定する。アカウント ID は、下記コマンドで確認可能。

```bash
$ aws sts get-caller-identity --profile apprunner-tutorial
```

### Stack・Construct の作成

AWS リソースを定義する。

lib/apprunner-tutorial-stack.ts

```typescript
import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import * as assets from "aws-cdk-lib/aws-ecr-assets";
import * as apprunner from "@aws-cdk/aws-apprunner-alpha";

export class ApprunnerTutorialStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const asset = new assets.DockerImageAsset(this, "ImageAssets", {
      directory: "./app",
      platform: assets.Platform.LINUX_AMD64,
    });

    new apprunner.Service(this, "Service", {
      source: apprunner.Source.fromAsset({
        asset: asset,
        imageConfiguration: {
          port: 8080,
        },
      }),
    });
  }
}
```

## Go 言語でアプリ作成

### Go のインストール

最初に Go をインストールする。
今回は macOS 上で動作するパッケージ管理ツール Homebrew を使って Go をインストールする。

```bash
$ brew install go
```

上記コマンドの実行が完了したら、インストールされた Go のバージョンを確認。

```bash
$ go version
go version go1.20.1 darwin/amd64
```

### API サーバの作成

ディレクトリを作成。先ほど、CDK のプロジェクトを作成した場所で、新たに app ディレクトリを作成する。

```bash
$ mkdir app && cd app
```

現在のディレクトリにおけるモジュールを外部からインポートする時のパスを設定する。基本的には GitHub での公開が一般的となるため、`github.com/<ユーザ名>/<GitHub上のリポジトリ名>` といったパスを指定する。


```bash
$ go mod init github.com/FarStep131/apprunner-tutorial/app
```

`server/server.go` を作成する。

```bash
$ mkdir server && touch server/server.go
```

server/server.go

```go
package server

import (
	"log"
	"net/http"
	"sync/atomic"
	"time"

	"github.com/gin-gonic/gin"
)

type Server struct {
	counter int64

	server *http.Server
	router *gin.Engine
}

// New creates an instance of a gin server with counter endpoint
func New() *Server {
	router := gin.Default()
	server := &Server{
		router:  router,
		counter: int64(0),
	}

	router.GET("/", server.CounterHandler)

	return server
}

// CounterHandler calculates number of requests and return a json with counter number
func (s *Server) CounterHandler(ctx *gin.Context) {
	counter := atomic.AddInt64(&s.counter, 2)

	ctx.JSON(200, gin.H{"counter": counter})
}

// Start starts the server and listen on a provided address in a format <host>:<port>
func (s *Server) Start(address string) error {
	s.server = &http.Server{
		Addr:        address,
		Handler:     s.router,
		ReadTimeout: 10 * time.Second,
	}

	log.Printf("start server on %s", address)

	return s.server.ListenAndServe()
}
```

`main.go` を作成する。

main.go

```go
package main

import (
	"fmt"
	"log"

	"github.com/NaokiYazawa/apprunner-tutorial/app/server"
)

const (
	host = "0.0.0.0"
	port = "8080"
)

func main() {
	s := server.New()
	err := s.Start(fmt.Sprintf("%s:%s", host, port))
	if err != nil {
		log.Fatalf("server stopped with error: %s", err)
	}

	log.Printf("server stopped successfully")
}
```

サーバを起動する。

```bash
$ go run main.go
```


## 作成したアプリの Docker 化

`Dockerfile` を作成する。

```bash
$ touch Dockerfile
```

Multi-stage build を用いてイメージを作成する。

【1st Stage】
1. Go 言語の環境を用意
2. ライブラリ等のインストール
3. バイナリファイルの作成

【2nd Stage】
1. バイナリファイルの実行環境を用意
2. 1st stage から作成されたバイナリファイルをコピー
3. バイナリファイルの実行

![](https://i.imgur.com/jDM1lbw.png)

イメージサイズは小さければ小さいほどよい

- アップロードもダウンロードも早くなる
- 起動に要する時間が短縮される
- コンテナに含まれるプログラムが少ないほど、脆弱性が軽減される

Dockerfile

```dockerfile
# Build stage
# golang のイメージを使用
FROM golang:1.20 AS builder
WORKDIR /app
COPY . .
RUN go mod download
RUN CGO_ENABLED=0 go build -o main /app/main.go

# Run stage
# Debian の distroless をベースイメージに別のステージを定義
# 最終的なイメージには、distroless/static-debian11 イメージの最小限のライブラリセットとアプリの実行ファイルのみが含まれる
FROM gcr.io/distroless/static-debian11
WORKDIR /app
COPY --from=builder /app/main .
EXPOSE 8080
CMD [ "/app/main" ]
```

Docker Desktop が起動していることを確認後、ビルドする。

```bash
$ docker build -t app .
```

`-t` オプションをつけることで、イメージの名前・タグを指定することができる。
コマンドの最後のピリオドは、`Dockerfile` が存在するディレクトリを指定。

実行する。

```bash
$ docker run --name app --rm -it -p 8080:8080 app
```

| オプション | 用途 |
| -------- | -------- |
| **--name** | コンテナの名前を指定する |
| **--rm** | コンテナを終了したときにコンテナを削除する |
| **-it** | -i -t と同じ意味。インタラクティブモードで起動する。 |
| **-p** | ポートを指定する（外部のポート:コンテナ内部のポート） |

コマンドの最後の app は、イメージの名前を指定。


## デプロイ

### ブートストラップ

ブートストラップは、AWS CDK アプリケーションを環境にデプロイする前にリソースをプロビジョニングするプロセスである。
これらのリソースには、ファイルを保存するための Amazon S3 バケットや、デプロイの実行に必要なアクセス権限を付与する IAM ロールが含まれる。

```bash
$ cdk bootstrap --profile apprunner-tutorial
```

### 単一または複数のスタックを AWS にデプロイ

```bash
$ cdk deploy --profile apprunner-tutorial
```

### 単一または複数のスタックの削除

```bash
$ cdk destroy --profile apprunner-tutorial
```
