はじめに
2022年2月8日(米国時間)に、AWS App Runner にて Amazon VPC 接続用の機能が追加されました。アップデート前は、VPC 内にホストされている Amazon RDS などのサービスに接続することが出来ませんでした。このアップデートにより、VPC 内にホストされている RDS をはじめとした、各種サービスと連携ができるようになりました!
AWS では、VPC 内でホストされているサービスがあるため、ユースケースが広がるアップデートとなります。詳細は次のブログを参照してください。
また、このアップデートの留意点としては、App Runner にアクセスする経路は変わらずインターネットをつかったアクセスが必要です。アクセス元 → App Runner 方向のインバウンドトラフィックは、インターネットを経由した接続が必要で、App Runner → なにか 方向のアウトバウンドトラフィックは、自分たちが管理している VPC の経路をつかった接続となります。詳細は次のブログを参照してください。
今回の記事は、Go 言語で作成した Docker Image を使って、VPC 内に構成している RDS for MySQL と接続する App Runner を作成してみる記事となります。
Go言語で動作確認用プログラムを作成
MySQL と接続するための Go言語のプログラムをローカル環境で作成します。エラーハンドリングなどは省略しているので、本番環境での利用はダメです。ローカルで開発するため、接続先の MySQL の情報は環境変数化しています。
package main
import (
"database/sql"
"fmt"
"net"
"net/http"
"os"
"time"
_ "github.com/go-sql-driver/mysql"
)
var db *sql.DB
func handler(w http.ResponseWriter, r *http.Request) {
// MySQL のデータを表示
row := db.QueryRow(`select * from sample`)
var id, name string
row.Scan(&id, &name)
println(name)
fmt.Fprintf(w, name+"\n")
fmt.Fprintf(w, "\n")
// ローカルのIPアドレスを表示
fmt.Fprintf(w, "IPアドレス一覧"+"\n")
interfaces, err := net.Interfaces()
if err != nil {
fmt.Println(err)
return
}
for _, inter := range interfaces {
addrs, err := inter.Addrs()
if err != nil {
fmt.Println(err)
return
}
for _, a := range addrs {
if ipnet, ok := a.(*net.IPNet); ok {
if ipnet.IP.To4() != nil {
fmt.Println(ipnet.IP.String())
fmt.Fprintf(w, ipnet.IP.String()+"\n")
}
}
}
}
}
func main() {
// MySQL のコネクションを取得
mysql_hostname := os.Getenv("MYSQL_HOSTNAME")
mysql_port := os.Getenv("MYSQL_PORT")
mysql_username := os.Getenv("MYSQL_USERNAME")
mysql_password := os.Getenv("MYSQL_PASSWORD")
var err error
db, err = sql.Open("mysql", mysql_username+":"+mysql_password+"@tcp("+mysql_hostname+":"+mysql_port+")/sugi01")
if err != nil {
println("MySQL のコネクション接続に失敗")
panic(err)
}
defer db.Close()
db.SetConnMaxLifetime(time.Minute * 3)
db.SetMaxOpenConns(10)
db.SetMaxIdleConns(10)
http.HandleFunc("/", handler) // ハンドラを登録してウェブページを表示させる
http.ListenAndServe(":8080", nil)
}
ローカル環境では、Docker を使って MySQL を動かしている必要があります。詳細はこちらの記事に記載しております。
ローカルで、MySQL を動かしたうえで、Go 言語のプログラムの動作確認をしていきます。
go run app.go
ブラウザからアクセスすると、MySQL から取得した「MySQLのデータ」と、コンテナに付与されている IP アドレス一覧が表示されます。
Go言語のプログラムをBuildします。
go build -o app
app ファイルがビルドされました。
> ls -la
total 6576
drwxr-xr-x 2 ec2-user docker 76 Feb 14 01:31 .
drwxr-xr-x 5 ec2-user docker 74 Feb 14 00:00 ..
-rwxr-xr-x 1 ec2-user docker 6714375 Feb 14 01:31 app
-rw-r--r-- 1 ec2-user docker 1567 Feb 14 01:28 app.go
-rw-r--r-- 1 ec2-user docker 87 Feb 14 01:30 Dockefile
-rw-r--r-- 1 ec2-user docker 101 Feb 14 00:55 go.mod
-rw-r--r-- 1 ec2-user docker 179 Feb 14 00:10 go.sum
ECR Repository 作成
これから Docker Image を作成していくのですが、Docker Image を保管するための ECR Repository を用意していきます。ECR の画面を開いて、Create Repository を押します。
Repository 名を入力します。
Create Repository を選択します。
作成されました。
Docker Image Build
次に、手元の環境で Docker Image を Build していきます。次のように Dockerfile を作成します。
- ベースのイメージは、ECR Public にある Golang 1.16 のものを利用
- Build した Go 言語のプログラムを、
/workdir
に格納 - 8080 ポートを EXPOSE
FROM public.ecr.aws/docker/library/golang:1.16
RUN mkdir /workdir
COPY app /workdir
EXPOSE 8080
CMD ["/workdir/app"]
作成した ECR Repository を指定して、Docker Build を行います。
docker image build -t xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/app-runner-testapp:0.0.1 .
作成した Docker Image を使って、動作確認をします。
- MySQL はローカルの Docker で稼働している前提 (172.17.0.2 の IP アドレスは、MySQL コンテナの IP アドレス)
docker run \
-it \
--env MYSQL_HOSTNAME=172.17.0.2 \
--env MYSQL_PORT=3306 \
--env MYSQL_USERNAME=root \
--env MYSQL_PASSWORD=mypassword \
-e BIND-ADDRESS=0.0.0.0 \
-p 8080:8080 \
xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/app-runner-testapp:0.0.1
ブラウザから動作確認をします。正常に稼働しています。
ECR に Push
正常に Docker Image が作成できたので、ECR に Push していきます。まず、Login をします。
aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com
Login 後、ECR に Push を行います。
docker push xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/app-runner-testapp:0.0.1
ECR に Push されています。
latest tag も付与して Push をします。
docker image build -t xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/app-runner-testapp:latest .
docker push xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/app-runner-testapp:latest
RDS の準備
App Runner から接続するための、RDS for MySQL を作成しました。
これに、テストデータを入れていきましょう。
mysql -u admin -h single-rds01.chuxmuzmrpgx.ap-northeast-1.rds.amazonaws.com -p
テストデータを入れます。
CREATE DATABASE sugi01;
USE sugi01;
CREATE TABLE sample(
id INT(11) NOT NULL AUTO_INCREMENT,
name VARCHAR(10) NOT NULL,
PRIMARY KEY (id)
);
INSERT INTO sample(name) VALUES ("RDSのデータ");
テストデータが格納されているか確認です。
mysql> SELECT * FROM sugi01.sample;
+----+-----------------+
| id | name |
+----+-----------------+
| 3 | RDSのデータ |
+----+-----------------+
1 row in set (0.00 sec)
App Runner の作成
それでは、App Runner で Service を作成していき、ECR に Push したコンテナイメージを動かしていきましょう。Create service を選びます。
ECR 上で作成したコンテナイメージを指定します。
Deployment settings は、Automatic にしておきます。これにより、latest イメージが更新されたときに、自動デプロイを行うようにします。
Service の名前や、環境変数などを指定していきます。Go 言語のアプリケーションに渡すための、RDS の接続情報を与えましょう。
MYSQL_HOSTNAME single-rds01.chuxmuzmrpgx.ap-northeast-1.rds.amazonaws.com
MYSQL_PORT 3306
MYSQL_USERNAME admin
MYSQL_PASSWORD yourpassword
Auto Scaling デフォルトのままにします。
Health Check はデフォルトのままにします。
Security もデフォルトのままにします。
Networking では、RDS と接続するために、VPC Connector を作成していきます。
VPC connector の名前や、接続する VPC, Subnet, Security Group などを指定します。
指定された状態です。
Next
Create & Deploy を押します。
Service の Deploy が走ります。
一定時間後、Deploy が完了します。
アクセス確認
該当のドメインにアクセスすると、作成したコンテナイメージが正常に稼働していることがわかります。RDS と接続が出来ており、「RDSのデータ」と表示さされています。