Go3 Advent Calendar 2018の9日目を担当するtheoden9014です。よろしくお願いします。
Makefileについて書こうと思ったのですが、内容が同じような記事が先に出てしまったようなので、少し趣向を変えたタイトルにしました。
この記事では、Makefile
とDockerfile
を上手く利用することによって、Docker内でのビルドやデバッグを簡単にする方法についてご紹介します。
この手法であれば、開発者は手元にはDockerをインストールするだけでGoを使った開発を行えるようになります。
今回は以下のリポジトリをベースとしてご紹介していきます。
https://github.com/theoden9014/go-startkit/tree/qiita
背景
Goで開発する際には$GOPATH
の知識は必要不可欠です。
vgoの普及によって$GOPATH
の重要性は下がってくるでしょうが、現段階では全く考慮しないわけには行きません。
初心者でも簡単にHello 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さんです!