概要
個人アプリにて、Fargateでのコンテナ運用を行うため、golang環境のDockerfileを作成しました。
当環境の特徴として、
- DockerイメージをAlpine Linuxベースを使用し、軽量化。
- マルチステージビルド機能を使用し、ビルド環境でgolangアプリやその他バイナリを作成し、軽量化。
- Fargateで運用するコンテナの中に入ってシェル操作するため、ssm-agentを導入。
です。
各種ファイル
Dockerfile
FROM golang:1.14.4-alpine3.12 as builder
ARG SSM_AGENT_VERSION=2.3.1205.0
RUN apk add --no-cache \
'make~=4.3-r0' \
'git~=2.26.2-r0' \
'gcc~=9.3.0-r2' \
'libc-dev~=0.7.2-r3' \
'bash~=5.0.17-r0'
RUN wget -q https://github.com/aws/amazon-ssm-agent/archive/${SSM_AGENT_VERSION}.tar.gz && \
mkdir -p /go/src/github.com && \
tar xzf ${SSM_AGENT_VERSION}.tar.gz && \
mv amazon-ssm-agent-${SSM_AGENT_VERSION} /go/src/github.com/amazon-ssm-agent && \
echo ${SSM_AGENT_VERSION} > /go/src/github.com/amazon-ssm-agent/VERSION
WORKDIR /go/src/github.com/amazon-ssm-agent
RUN gofmt -w agent && make checkstyle || ./Tools/bin/goimports -w agent && \
make build-linux
WORKDIR /go/src/server
COPY go.mod go.sum ./
RUN go mod download
RUN go get bitbucket.org/liamstask/goose/cmd/goose
COPY . .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o /go/bin/server
FROM alpine:3.12 as prod
RUN apk add --no-cache \
'aws-cli~=1.18.55-r0' \
'sudo~=1.9.0-r0' \
'mysql-client~=10.4.15-r0'
RUN adduser -D ssm-user && \
echo "Set disable_coredump false" >> /etc/sudo.conf && \
echo "ssm-user ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/ssm-agent-users && \
mkdir -p /etc/amazon/ssm
COPY --from=builder /go/src/github.com/amazon-ssm-agent/bin/linux_amd64/ /usr/bin
COPY --from=builder /go/src/github.com/amazon-ssm-agent/bin/amazon-ssm-agent.json.template /etc/amazon/ssm/amazon-ssm-agent.json
COPY --from=builder /go/src/github.com/amazon-ssm-agent/bin/seelog_unix.xml /etc/amazon/ssm/seelog.xml
COPY --from=builder /go/bin/server /go/bin/server
COPY --from=builder /go/bin/goose /go/bin/goose
RUN mkdir -p /go/bin/db
COPY ./db/dbconf.yml /go/bin/db/dbconf.yml
COPY ./db/migrations /go/bin/db/migrations
COPY ./db/mysql/init /docker-entrypoint-initdb.d
EXPOSE 8080
COPY ./aws/docker-entrypoint.sh /
CMD ["sh", "/docker-entrypoint.sh"]
docker-entrypoint.sh
#!/bin/sh
set -e
amazon-ssm-agent -register -code $SSM_ACTIVATE_CODE -id $SSM_ACTIVATE_ID -region "ap-northeast-1"
amazon-ssm-agent &
/go/bin/server
要点
Alpineはssmエージェント未対応
※一部抜粋
RUN wget -q https://github.com/aws/amazon-ssm-agent/archive/${SSM_AGENT_VERSION}.tar.gz && \
mkdir -p /go/src/github.com && \
tar xzf ${SSM_AGENT_VERSION}.tar.gz && \
mv amazon-ssm-agent-${SSM_AGENT_VERSION} /go/src/github.com/amazon-ssm-agent && \
echo ${SSM_AGENT_VERSION} > /go/src/github.com/amazon-ssm-agent/VERSION
Alpineではssmエージェントのパッケージがないので、ソースから拾いビルドして設置する必要があります。
https://github.com/aws/amazon-ssm-agent/issues/140
ECRスキャンはscratchベース非対応
FROM alpine:3.12 as prod
Dockerイメージ軽量化のため、最初はscratchベースで実行環境を構築しようとしましたが、ECRはイメージスキャン未対応のことなので、実行環境もAlpineを採用しました。
https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/image-scanning-troubleshooting.html
マイグレーションツールのgooseを採用
RUN mkdir -p /go/bin/db
COPY ./db/dbconf.yml /go/bin/db/dbconf.yml
COPY ./db/migrations /go/bin/db/migrations
開発環境でもお世話になったgoose
を本番環境でも採用しました。ビルド環境でバイナリ作成、実行環境にバイナリと必要なファイルをコピーして準備完了。ファイルの置き場所によって設定ファイルdbconf.yml
が読み込まれなくなってしまうので、注意が必要です。
シェルスプリクトで起動コマンド設定
amazon-ssm-agent -register -code $SSM_ACTIVATE_CODE -id $SSM_ACTIVATE_ID -region "ap-northeast-1"
amazon-ssm-agent &
コンテナ内で実行するため、シェルスクリプトでコマンドを投げてあげます。この時アクチベーションキーも設定しないといけないので、コンテナ内の環境変数に設定します。
参考資料
Go 1.12 の開発環境と本番環境の Dockerfile を考える
Alpine Linux に amazon-ssm-agent をインストールする
AWS Fargateで動かしてるコンテナの中に入る方法