DockerでGoの開発環境を作ってServerlessでAWS Lambdaにデプロイしてみた

Goを使ってみようかなと思い立ったので、まずは開発環境を構築してみました。


## 前提

- Dockerがインストール済み
- AWSのアカウントがある
- ```AWS_ACCESS_KEY_ID``` と```AWS_SECRET_ACCESS_KEY``` がある

```sh
> docker --version
Docker version 18.09.0, build 4d60db4

> docker-compose --version
docker-compose version 1.23.1, build b02f1306
```


## 手順

GitHubにソースをアップしていますので、よければご参考ください。
https://github.com/kai-kou/deploy-in-go-lambda-with-sls-on-docker

### Dockerコンテナの作成

```sh
> mkdir 任意のディレクトリ
> cd 任意のディレクトリ
> touch Dockerfile
> touch docker-compose.yml
```

Dockerfileは下記を参考にserverlessをインストールしています。

yunspace/serverless-golang: AWS Lambda Go functions using Serverless Framework and Python shim
https://github.com/yunspace/serverless-golang


```txt:Dockerfile
FROM golang:latest

ENV SERVERLESS serverless@1.30.1
ENV GOPATH /go
ENV PATH $GOPATH/bin:/root/.yarn/bin:$PATH

RUN apt-get update && \
    apt-get install git
RUN	go get -u github.com/rancher/trash
RUN curl --silent --location https://deb.nodesource.com/setup_6.x | bash - && \
    apt-get install -y nodejs
RUN curl -o- -L https://yarnpkg.com/install.sh | bash
RUN npm install -g $SERVERLESS
```

docker-compose.ymlは下記を参考に```volumes``` を指定しました。

Docker Compose で Go の開発環境をサクッと作る - Qiita
https://qiita.com/macoshita/items/827ae5ac245b94ed4b4c


コンテナ内でserverlessを用いてデプロイまで実行したかったので、```environment``` にAWSのアカウント情報を含めました。

```yaml:docker-compose.yml
version: '2'
services:
  app:
    build: .
    volumes:
      - 'data:/go'
      - '.:/go/src/app'
    environment:
      - AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID
      - AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY
volumes:
  data:
    driver: 'local'
```

AWS CLIがインストール済みの場合、```$HOME/.aws/credentials``` にアカウント情報が保存されていると思いますので、それを環境変数に設定します。

Cameron Eckelberry - Full Stack Developer
https://cameroneckelberry.co/words/getting-aws-credentials-into-a-docker-container-without-hardcoding-it

```sh:bash
> export AWS_ACCESS_KEY_ID=$(aws --profile default configure get aws_access_key_id)
> export AWS_SECRET_ACCESS_KEY=$(aws --profile default configure get aws_secret_access_key)
```

```sh:fish
> set -x AWS_ACCESS_KEY_ID (aws --profile default configure get aws_access_key_id)
> set -x AWS_SECRET_ACCESS_KEY (aws --profile default configure get aws_secret_access_key)
```

準備ができたら、コンテナを立ち上げます。

```sh
> docker-compose build
(略)
Successfully built 25cabb8b3be0
Successfully tagged 任意のディレクトリ_app:latest

> docker-compose run app

root@148f0f743c3f:/go#
```

### プロジェクトの作成とビルド

無事にコンテナ内へ入れたら下記を参考に```serverless``` でGoのプロジェクトを作成して、必要なパッケージをインストールしてビルドします。

Serverless FrameworkでGolangのLambda関数を作成してみる ｜ DevelopersIO
https://dev.classmethod.jp/etc/serverless-framework-golang-lambda-create/


```sh:コンテナ内
> cd src/app
> serverless create \
  -u https://github.com/serverless/serverless-golang/ \
  -p hello-go-lambda

> cd hello-go-lambda
> go get github.com/aws/aws-lambda-go/lambda
> GOOS=linux go build -o bin/main
```

### AWS Lambdaへデプロイ

AWS Lambdaへデプロイします。serverless.ymlはそのままでもデプロイできますが、```region``` などを変更したい場合には編集してからデプロイしてください。


```sh:コンテナ内
> serverless deploy
(略)
Serverless: Stack update finished...
Service Information
service: hello-go-lambda
stage: dev
region: us-east-1
stack: hello-go-lambda-dev
api keys:
  None
endpoints:
  None
functions:
  hello: hello-go-lambda-dev-hello
```

デプロイできたら実行してみます。

```sh:コンテナ内
> serverless invoke -f hello

{
    "message": "Go Serverless v1.0! Your function executed successfully!"
}
```

やったぜ。

### 後片付け

デプロイしたLambda関数を削除する場合、以下コマンドを実行します。

```sh:コンテナ内
> serverless remove

Serverless: Getting all objects in S3 bucket...
Serverless: Removing objects in S3 bucket...
Serverless: Removing Stack...
Serverless: Checking Stack removal progress...
..........
Serverless: Stack removal finished...
```


## まとめ

serverlessを利用するのにnode.jsをインストールする必要があるのが、若干手間ですが、思ってたよりも簡単に環境構築することができました。


## 参考

yunspace/serverless-golang: AWS Lambda Go functions using Serverless Framework and Python shim
https://github.com/yunspace/serverless-golang

Docker Compose で Go の開発環境をサクッと作る - Qiita
https://qiita.com/macoshita/items/827ae5ac245b94ed4b4c

Docker上でgolangの開発環境を整える - Qiita
https://qiita.com/yasuno0327/items/be7fb992054f40b491cc

Serverless FrameworkでGolangのLambda関数を作成してみる ｜ DevelopersIO
https://dev.classmethod.jp/etc/serverless-framework-golang-lambda-create/

ServerlessインストールからLambdaへのデプロイ - Qiita
https://qiita.com/jumjamjohn/items/abbc060fd2c1c6791ef3

Serverless Framework(Go) でHello worldしてみる - Qiita
https://qiita.com/seike460/items/b54a61ec8d07b2be8c87

Docker Compose - docker-compose.yml リファレンス - Qiita
https://qiita.com/zembutsu/items/9e9d80e05e36e882caaa

Cameron Eckelberry - Full Stack Developer
https://cameroneckelberry.co/words/getting-aws-credentials-into-a-docker-container-without-hardcoding-it

Fish Shellでコマンドの実行結果を変数に代入する方法 | Web Scratch
https://efcl.info/2013/0520/res3282/