サーバーレスWebAPI開発に入門しようとしたけどうまくいかなかった話

AWS DAVの勉強をしていたら、Lambdaを使えばとても簡単にWebAPIが作れてしまうのでは?と感じたので、 ググって最初にヒットしたこちらの記事を参考に、サーバーレスWebAPIを作ろうとしたらうまくいかなかった話です。

AWS DAV の勉強をしていたら、Lambda を使えばとても簡単に WebAPI が作れてしまうのでは?と感じたので、ググって最初にヒットしたこちらの記事を参考に、サーバーレス WebAPI を作ろうとしたらうまくいかなかった話です。

なお、Terraform を使ったインフラ構築は特に詰まることも無かったので本記事では触れません。

LambdaとGoを使ったサーバーレスWebAPI開発実践入門 | フューチャー技術ブログ

はじめにこんにちは、TIGの辻です。 業務アプリケーションのビジネスロジックをサーバーレスで実装することも増えてきました。AWSサービストリガによるLambda関数起動の記事にもあるようにAPI GatewayとLambda関数を組み合わせてHTTPサーバを提供することも容易にできます。バックエンドのWebAPIをLambda関数で動かすユースケースがよくあるパターンです。Lambda関数とアプリ

そもそも Windows の開発環境で無理やりやっている事が原因だと考えていますが、 Dockerfile の書き方とか色々調べてて勉強になったので書き残しておきます。
記事の内容が間違っているぞということが主旨ではないです。

開発環境

  • Windows 10 Home(20H2)
  • WSL2
  • Docker Desktop
  • Visual Studio Code
    • Remote - Containers 拡張

読みにくいかもしれませんが、以下にやったことを時系列順に書いていきます。

Docker コンテナ上に Golang 開発環境を作る

最初は Windows 上で作業していたのですが、Makefile 中のコマンドを Windows のコマンドに置き換える事がうまくできなかったため、 Docker コンテナ上に Golang 開発環境を作ることにしました。

こちらの記事を参考に、Dockerfiledocker-compose.ymlを作成。

【Go言語(Golang)】WSL2とDockerで最高のGo開発環境をつくる

こんにちは。現役エンジニアの”はやぶさ”@Cpp_Learningです。 WSL2 + Docker + VS…

フォルダ構成

.
build
│└─Dockerfile
cmd
gen
testdata
docker-compose.yml

Dockerfile

# goバージョン
FROM golang:1.17.5-alpine

# 前提パッケージのインストール
RUN apk add --update && apk --no-cache add git curl zip unzip sudo binutils make alpine-sdk build-base

ENV GLIBC_VER=2.34-r0

# install glibc
RUN curl -sL https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub -o /etc/apk/keys/sgerrand.rsa.pub
RUN curl -sLO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VER}/glibc-${GLIBC_VER}.apk
RUN curl -sLO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VER}/glibc-bin-${GLIBC_VER}.apk
RUN apk add --no-cache glibc-${GLIBC_VER}.apk glibc-bin-${GLIBC_VER}.apk

# aws cli v2 のインストール
# https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv2-linux.html
RUN curl -sL "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
RUN unzip -q awscliv2.zip
RUN sudo ./aws/install

RUN go get -u github.com/go-swagger/go-swagger/cmd/swagger

コンテナは軽量なほうがいいだろうと、ベースイメージには Alpine Linux を選択。
後々 Golang をビルドする時に『stdlib.h が足りない』と怒られるため、alpine-sdkbuild-baseをインストール。
go getの裏では git が動いているようなので、gitも前提パッケージとなります。
また、AWS CLI をインストールしたいが、Alpine Linux ではそのまま sudo ./aws/installしてもうまくいかないためglibcをインストールした上で AWS CLI をインストールしてます。
apk コマンドでインストール可能なパッケージはこちらのサイトから検索できます。

Alpine Linux packages

docker-compose.yml

version: "3"
services:
  aws-sdk-go-container:
    build: # ビルドに使うDockerファイルのパス
      context: .
      dockerfile: ./build/Dockerfile
    container_name: aws-sdk-go-container
    volumes: # ホストのAWS認証情報を共有する
      - "~/.aws:/root/.aws"

  # LocalStack
  localstack:
    image: localstack/localstack:latest
    environment:
      - SERVICE=dynamodb
      - DEFAULT_REGION=ap-northeast-1 # リージョンを設定
    ports:
      - 4566:4566 # サービスへのアクセスポートは4566

volumesではホスト側のC:\Users\<ユーザ名>\.awsに置かれている AWS 認証情報を、 コンテナから探しにいけるようにしています。
また元記事ではdocker runコマンドで LocalStack を起動していますが、 せっかく開発環境をコンテナ上に構築しているので、 あわせて起動するようdocker-compose.ymlに記述します。
user_handler_test.goの dbEndpoint をhttp://localstack:4566に書き換える事で 開発環境のコンテナから LocalStack のコンテナにアクセスできます。

curl コマンドを叩くと 502 が返ってきてお手上げに

コンテナ上でmake testがうまくいったため、make deployして AWS にデプロイしました。
デプロイも成功したため、元記事の通り以下のコマンドを実行したところ、 502 InternalServerErrorException が返ってくるように。

curl -i https://${rest-api-id}.execute-api.ap-northeast-1.amazonaws.com/test/v1/users

AWS マネジメントコンソールから API Gateway の CloudWatch ログを有効化し、 ログを見てみるとno such file or directory: PathErrorとのこと。

alpine のイメージで AWS Lambda 用の go バイナリをビルドしたら PathError になった話 - Qiita

ググって出てきたこちらの記事を参考に、Makefile 内のgo buildコマンドのオプションを書き換えて再デプロイ。
エラーメッセージがstring producer has not yet been implemented: apiErrorに変わったけれど、 Swagger がよしなにやってくれている部分でエラーが出ているようで、写経しているレベルの初学者にはお手上げになりました。

WSL2 がホストのメモリを浪費する現象の対策

502 エラーに四苦八苦している時、PC のファンの音が大きくなり、ビルドに時間がかかるようになりました。
タスクマネージャーを開いてみると CPU、メモリ、ディスクが 100%近く張り付いています。
調べてみるとVmmemというプロセスがメモリを浪費していました。

WSL2 によるホストのメモリ枯渇を防ぐための暫定対処 - Qiita

ググってみたところ、WSL2 の不具合のようでした。
こちらの記事を参考に暫定対処を行いましたが、メモリスワップが 発生すると SSD の I/O が 100%になるのは怖いですね。

参考

開発環境系

Alpine Linux 系

メモリ浪費の暫定対処系

Built with Hugo
テーマ StackJimmy によって設計されています。