Go
AdventCalendar
golang
docker
Go3Day 9

Goの開発環境でDockerを利用する

Go3 Advent Calendar 2018の9日目を担当するtheoden9014です。よろしくお願いします。

Makefileについて書こうと思ったのですが、内容が同じような記事が先に出てしまったようなので、少し趣向を変えたタイトルにしました。

この記事では、MakefileDockerfileを上手く利用することによって、Docker内でのビルドやデバッグを簡単にする方法についてご紹介します。
この手法であれば、開発者は手元にはDockerをインストールするだけでGoを使った開発を行えるようになります。

今回は以下のリポジトリをベースとしてご紹介していきます。
https://github.com/theoden9014/go-startkit/tree/qiita

背景

Goで開発する際には$GOPATHの知識は必要不可欠です。
vgoの普及によって$GOPATHの重要性は下がってくるでしょうが、現段階では全く考慮しないわけには行きません。
初心者でも簡単にHallo Worldができるような環境を作りたいな、と思い今回の記事を書きました。

Dockerfile

以下のDockerfileはdockerのマルチステージビルドを用い、以下のステージに分けています

  • development
    • 開発を行うための周辺環境が整っているステージ
  • builder
    • ビルドを行うための周辺環境が整っているステージ

ステージを指定しない場合は、builderステージでビルド後、成果物をalpineへコピーし、バイナリを実行するだけのコンテナイメージをビルドすることができます。

#
# Use multi stage build so require docker version higher 17.05.
#
FROM golang:1.11 AS development
ARG name=
ARG repository=
RUN apt-get update -y
RUN apt-get install -y doxygen doxygen-gui graphviz
WORKDIR /go/src/${repository}
COPY Makefile ./
RUN make setup
CMD ["/bin/true"]

FROM development AS builder
COPY Gopkg.toml Gopkg.lock ./
RUN make vendor
COPY . .
RUN make build
CMD ["/bin/true"]

FROM alpine
ARG name=
ARG repository=
ENV PORT 8080
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /go/src/${repository}/${name} ./app
ENTRYPOINT ["./app"]

Makefile

https://github.com/theoden9014/go-makefile/blob/qiita/Makefile
上記のMakefileのDockerに関する部分について軽く説明していきます。

REPOSITORY              ?= github.com/theoden9014/go-startkit
NAME                    ?= go-startkit

...

#
# Docker
#
DOCKER                          ?= docker
DOCKER_IMAGE_NAME               := $(NAME)
DEVELOP_DOCKER_IMAGE_NAME       := $(NAME)-dev
BUILD_DOCKER_IMAGE_NAME         := $(NAME)-build
DOCKERFILE                      := Dockerfile
DEVELOP_STAGE                   := development
BUILD_STAGE                     := builder
DEFAULT_DOCKER_BUILD_OPTS       := -f $(DOCKERFILE) --build-arg name=$(NAME) --build-arg repository=$(REPOSITORY)
DOCKER_BUILD_DEVELOP_STAGE_OPTS := $(DEFAULT_DOCKER_BUILD_OPTS) -t $(DEVELOP_DOCKER_IMAGE_NAME) --target $(DEVELOP_STAGE)
DOCKER_BUILD_BUILD_STAGE_OPTS   := $(DEFAULT_DOCKER_BUILD_OPTS) -t $(BUILD_DOCKER_IMAGE_NAME) --target $(BUILD_STAGE)
DOCKER_BUILD_OPTS               := $(DEFAULT_DOCKER_BUILD_OPTS) -t $(DOCKER_IMAGE_NAME)

...

# Docker targets from here
docker: ## Build server image
    docker build $(DOCKER_BUILD_OPTS) .
login: build-develop-stage ## Login to development environment with container
    docker run --rm -it \
    -v $(PWD):/go/src/$(REPOSITORY) \
    -p 8080:8080 \
    $(DEVELOP_DOCKER_IMAGE_NAME) \
    /bin/bash
docker-check: build-develop-stage ## Run 'make check' inside container
    docker run --rm -it \
    $(DEVELOP_DOCKER_IMAGE_NAME) \
    make check
docker-coverview: build-develop-stage ## Run 'make coverview' inside container
    docker run --rm -it \
    -v $(PWD):/go/src/$(REPOSITORY) \
    $(DEVELOP_DOCKER_IMAGE_NAME) \
    make coverview
docker-graph: build-develop-stage ## Run 'make graph' inside container
    docker run --rm -it \
    -v $(PWD):/go/src/$(REPOSITORY) \
    $(DEVELOP_DOCKER_IMAGE_NAME) \
    make graph
build-develop-stage:
    docker build $(DOCKER_BUILD_DEVELOP_STAGE_OPTS) .
build-build-stage:
    docker build $(DOCKER_BUILD_BUILD_STAGE_OPTS) .

.PHONY: docker login docker-check docker-coverview docker-graph build-develop-stage build-build-stage

上記のMakefileを利用することで以下のようなことが行えるようになります。

  • make login
    • プロジェクトルートディレクトリをコンテナ内の$GOPATH配下へマウントし、コーディングはローカルのIDEで、ビルドやデバッグはコンテナ内で行えます
  • make docker-*
    • コンテナ内でテストやパッケージ依存関係のグラフ作成等を行えるようにしています

最後に

以上、簡単ではありましたがGo言語をDockerで開発する方法の紹介でした。
ここまでご覧いただきありがとうございました。

明日は@pankonaさんです!