AmplifyのAPIに自作コンテナを使う

# はじめに
前回、amplifyでコンテナを動かす例を記事にしました。

https://qiita.com/a_b_/items/01482e96099b6ab1257a

今回はそのコンテナを自作のものにしてみました。コンテナには以前に作ったRのplumberで作成したものを例にしました。

https://qiita.com/a_b_/items/32cbc21bd140321719c2

# やってみた

## 事前準備
以下を用意しました。

- Cloud9
    - t3.small。前回より大きいものに
- IAMユーザー
    - AdministratorAccessを付与
    - 後ほど使うので、アクセスキーを発行

準備用のコマンドは前回と同じものになります。
```bash
# インストール
npm install -g @aws-amplify/cli
# プロジェクトフォルダ作成
mkdir amplify-containerized && cd amplify-containerized

# 初期設定。設定値は前回参照
amplify init

amplify configure project

npx update-browserslist-db@latest
```

## 自作のコンテナ設定
ここから先は、前回と違ってきます。
```
$ amplify add api

# "REST"を選択
? Select from one of the below mentioned services: (Use arrow keys)
❯ GraphQL 
  REST 

# "API Gateway + AWS Fargate (Container-based) "を選択
? Which service would you like to use (Use arrow keys)
❯ API Gateway + Lambda 
  API Gateway + AWS Fargate (Container-based) 

# デフォルトの名前で指定
? Provide a friendly name for your resource to be used as a label for this category in the project: (containerf15cc372) 

# "Custom (bring your own Dockerfile or docker-compose.yml)"を選択
? What image would you like to use (Use arrow keys)
❯ ExpressJS - REST template 
  Docker Compose - ExpressJS + Flask template 
  Custom (bring your own Dockerfile or docker-compose.yml) 
  Learn More 

# On every "amplify push" (Fully managed container source) を選択
? When do you want to build & deploy the Fargate task (Use arrow keys)
❯ On every "amplify push" (Fully managed container source) 
  On every Github commit (Independently managed container source) 
  Advanced: Self-managed (Learn more: docs.amplify.aws/cli/usage/containers) 

# "n"を入力
? Do you want to restrict API access (Y/n) 

```
対象のディレクトリまで潜って、ファイルを作っていきます。
```bash
cd amplify/backend/api/containerf15cc372/src/

# ベースとなるイメージプル
docker pull r-base

# 必要なファイルを作成
touch Dockerfile
touch plumber.R
touch sample.R
```

３つのファイルの中身は以下です。
```dockerfile:Dockerfile
FROM r-base

COPY  sample.R /usr/local/src/
COPY  plumber.R /usr/local/src/

WORKDIR /usr/local/src/

# install the linux libraries needed for plumber
RUN apt-get update -qq && apt-get install -y \
  libsodium-dev \
  libcurl4-gnutls-dev

RUN R -e 'install.packages("plumber")'

EXPOSE 80

ENTRYPOINT ["Rscript", "plumber.R"]
```

```r:plumber.R
library(plumber)
api <- plumber::plumb("sample.R")
api$run(host = "0.0.0.0", port=80)
```
```r:sample.R
#* @get /hello
hw <- function() {
    return("Hello, world!")
}

#* @get /hello/<name>/<age:int>
hw <- function(name, age) {
    return(paste("Hello", name, "You're", age, "years old", seq=" "))
}

#* @get /fn
hw <- function(x) {
    x <- as.numeric(x)
    y <- 2 * x + 1
    return(y)
}

#irisを読み込み
df <- iris

#* @get /plot
#* @png
hw <- function() {
    p <- plot(df$Sepal.Length, df$Sepal.Width, 
        main="Sample plot", xlab="Sepal.Length", ylab="Sepal.Width")
    print(p)
}
```


## デプロイ
PUSHして、デプロイします。
```
$ amplify push

✔ Successfully pulled backend environment dev from the cloud.

    Current Environment: dev
    
┌──────────┬───────────────────┬───────────┬───────────────────┐
│ Category │ Resource name     │ Operation │ Provider plugin   │
├──────────┼───────────────────┼───────────┼───────────────────┤
│ Api      │ containerf15cc372 │ Create    │ awscloudformation │
└──────────┴───────────────────┴───────────┴───────────────────┘
# "Y"を入力
? Are you sure you want to continue? (Y/n) ‣ 
```

表示されたREST API endpointにCURLして、自作のコンテナで動くことを確認します。

```bash
ROOTURL=[REST API endpoint]

curl ${ROOTURL}/hello
curl ${ROOTURL}/hello/jiro/21
# pic.jpgでファイルが保存されます。
curl ${ROOTURL}/plot --output pic.jpg
```

# 削除
`amplify delete`で削除します。ディレクトリごと消えるので、必要なファイルは退避しておいてください。
```bash
cd ~/environment/amplify-containerized
amplify delete
```

ECRのリポジトリは残ったままなので不要であれば消します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/e5ed2fc5-adbb-3ca8-6a26-98fb6d0fd9e4.png)

また作ったIAMユーザも忘れずに消しておきます。

# おわりに
前回はテンプレートのコンテナを用いましたが、今回は自作コンテナを使って構築してみました。
自前のコンテナも簡単に扱えるので、かなり使い勝手良い印象を受けました。
この記事がどなたかのお役に立てれば幸いです。