はじめに
本記事では、Go 言語と Redis を使用し簡単なAPIの作成手順について説明する。今回は、docker-compose を使って実装していく為、環境に依存しない開発環境で実装する。
また、効率的に開発が行える様、開発の中でいくつかの工夫を施しているので参考になれば幸いである。
追伸、今回は記述量が多くなるので以下の2部構成にした。
- Part.1 : 環境構築 ~ 動作確認
- Part.2 : API実装 ~ 実装検証
その為、本記事では環境構築から動作確認までを説明する。
初めて実装していく方の為に、実行環境と予備知識としていくつか説明する。
1. 実行環境
- macOS Catalina Ver.10.15.2
- Docker version 19.03.5, build 633a0ea
- docker-compose version 1.24.1, build 4667896b
- golang 1.13.6
- Redis 5.0.7
【補足①】
-
Go言語
- 2009年、Googleによって開発されたオープンソース(OSS)のプログラミング言語。
- 特徴として、「高速コンパイル」、「シンプルな記述」が挙げられる。
【補足②】
-
Redis
- キーバリュー型(KVS)の NoSQL の一種。
- キーと5種類の値型の対応関係を格納ができる。
- インメモリデータベースであるため、高速なデータへのアクセスが可能である。
【補足③】
-
Docker
- コンテナ型の仮想化ツール。
- 従来のハイパーバイザ型(Hyper-V)、ホスト型(VMWareやVirtualBoxなど)に比べ軽量で、且つ利便性が高い。
- docker-compose を使用する事で、複数のコンテナを組み合わせて1つのアプリケーションを構成できる。
2. 前提条件
今回、実装するに至って用意するべき事項は以下の2点である。
- PC内に docker、docker-composeがインストールされている
- Goの開発環境が整備されている
docker、docker-compose が動作する環境があれば、特必要となるものは無い。コードを書く際は、好みのエディター (Atom、VSCodeなど)を使用すると良い。Goの開発環境に関しては、開発を進める上でgo.mod
、go.sum
を事前に作成しておく必要がある為、インストールしている。
Goの開発環境に関しては、Homebrew
を使用した環境構築がオススメである。以下にインストール手順を示しておく。
$ brew install go
尚、今回使用するものが正常にインストールされているかどうかを確認したい場合は、以下のコマンドで確認が可能である。
# Goの確認
$ go version
go version go1.13.6 darwin/amd64
# dockerの確認
$ docker version
Client: Docker Engine - Community
Version: 19.03.5
API version: 1.40
...
# docker-composeの確認
$ docker-compose version
docker-compose version 1.24.1, build 4667896b
docker-py version: 3.7.3
...
3. 環境構築
3.1. ファイル構成
今回のファイル構成は以下の通りである。
sample_project
├── docker
│ ├── api
│ │ └── Dockerfile-api //API用
│ └── database
│ └── Dockerfile-redis //DB用
├── docker-compose.yml
└── src
└── app
├── controller
│ ├── sender.go
│ └── receiver.go
├── infrastructure
│ └── database.go
├── interface
│ └── user.go
└── main.go
今回は個々の処理を各ディレクトリに分けた。構成に関しては様々な設計思想があると思うので、それに基づいて開発を行う場合は、はじめにファイル構成などを考えてから構築して行くと良い。
3.2. Go Modulesの作成
GoではGo Modules
と呼ばれる外部パッケージの管理システムがある。今回はそれを使用する為、事前にmain.go
が配置されているディレクトリで以下のコマンドを実行し、go.mod
、go.sum
を作成しておく。
# appディレクトリまで移動
~/sample_project $ cd src/app
# go.modファイルを作成する
~/sample_project/src/app $ go mod init main.go
# go build コマンド、または go mod download コマンドのどちらかを実行する
~/sample_project/src/app # go build
~/sample_project/src/app # go mod download
次に、Dockerfileの作成する。
3.3. Dockerfileの作成
3.3.1. Dockerfile (API)
まず、API用のDockerfileを作成していく。API側のDockerfileではGoの環境を構築していく。開発環境ではソースコードが随時更新される事を考慮し、ホットリロード環境を導入するためにfresh
と呼ばれるライブラリを使用した。
###############################
# Builder Container
###############################
FROM golang:1.13.6 AS builder
# Go Moduleが使えるようにする
ENV GO111MODULE=on
WORKDIR /go/src/app/
# GOROOTが/goになるため
COPY src/app /go/src/app
# gormとginのドライバをインストールする
RUN apt-get update \
&& apt-get upgrade -y \
&& apt-get install -y git \
&& go mod download \
&& go get github.com/pilu/fresh \
# ホットリロードを実行する
CMD ["fresh"]
###############################
# Production Container
###############################
FROM golang:1.13.6-alpine AS production
COPY --from=builder /go/src/app/ /app
上記の様に、開発環境と本番環境とで環境を分ける為、マルチステージビルドしても良い。マルチステージビルドを使用する事で、可読性、保守性を保つ事ができる。また、逐一Dockerfile
を最適化するために書き直す面倒くささも解消できる。
尚、環境を分割する必要のない場合、以下の記述例でも良い。
FROM golang:1.13.6-alpine
ENV GO111MODULE=on
WORKDIR /go/src/app/
COPY src/app /go/src/app
RUN apk add --no-cache --virtual alpine-sdk git && \
go mod download && \
go get github.com/pilu/fresh
CMD ["fresh"]
alpine
を使用する事で、イメージが軽量化されるので、ビルド時間の短縮にもなる。しかし、RUNコマンドの記述が上記とは異なる為、注意してほしい。
※ alpine : Alpine Linuxと呼ばれる、BusyBoxとmuslをベースにしたLinuxディストリビューションを指す
今回は、簡単なAPIの実装なのでDockerfile-api-slim
(alpineの方)を使用して開発を行う。
3.3.2. Dockerfile (Database)
DB用のDockerfileを作成していく。DB側のDockerfileではRedisの環境を構築していく。
こちら側では今回、特に設定をする事はないので下記のような記述で良い。
FROM redis:5.0.7-alpine
Dockerfileの作成は以上である。
3.4. docker-compose.yml
次に、docker-compose.ymlの作成を行う。
version: '3.7'
services:
api:
build:
context: .
# マルチステージビルドを使用しない場合、targetは不要
target: builder
dockerfile: ./docker/api/Dockerfile-api
container_name: sample_project-api
image: sample_project/api:0.1.0
ports:
- "8080:8080"
# ホストOSとコンテナ内でソースコードを共有
volumes:
- ./src/app:/go/src/app
depends_on:
- redis
tty: true
redis:
build:
context: .
dockerfile: ./docker/database/Dockerfile-database
container_name: sample_project-redis
image: sample_project/redis:0.1.0
ports:
- "6379:6379"
restart: always
volumes:
- ./docker/database:/data
今回の実装の場合、DB側のコンテナの起動が完了してからAPIのコンテナを起動させたいので、
depends_on
でコンテナの作成順序を依存関係を決めている。
また、tty:true
を追記する事でコンテナを常時起動させる。ポート番号に関しては、デフォルトの8080
、6379
をそれぞれ設定している。
マルチステージビルドを採用している場合は、target
の箇所で、自分がビルドしたいステージを指定すると良い。
3.5. main.go
コンテナのイメージを作成後に正しく環境構築されているかどうかを確認するために、main.go
の作成をしておく。ここでは、簡単に作成し、後ほどAPIの開発のために改修していく。
以下に作成したソースコードを示す。
package main
import (
"github.com/gin-gonic/gin"
)
func main() {
router := gin.Default()
router.GET("/", func(context *gin.Context) {
context.JSON(200, gin.H{
"message": "Hello, World!!",
})
})
router.Run(":8080")
}
今回は、GoのWebフレームワークの1種である、Gin を使用した。処理の内容としては、http://localhost:8080/
へアクセスすることでHello, World!!
とメッセージが返ってくるだけの簡単なものである。
3.6. dockerイメージの作成
Dockerfile
, docker-compose.yml
を作成後、以下のコマンドを実行し dockerイメージを作成する。
~/sample_project $ docker-compose up -d
実行後、イメージができているかどうかを以下のコマンドを実行し、確認する。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
sample_project/redis 0.1.0 b68707e68547 9 days ago 29.8MB
redis 5.0.7-alpine b68707e68547 9 days ago 29.8MB
sample_project/api 0.1.0 f8d6549bee6c 24 minutes ago 449MB
golang 1.13.6-alpine 9954d1348cd8 10 days ago 359MB
3.7. コンテナの起動 / 動作確認
イメージの作成後、以下のコマンドを実行しコンテナを起動させる。
$ docker-compose up
# docker-composeコンテナ一覧の確認
$ dokcer-compose ps
Name Command State Ports
--------------------------------------------------------------------------------------
sample_project-api fresh Up 0.0.0.0:8080->8080/tcp
sample_project-redis docker-entrypoint.sh redis ... Up 0.0.0.0:6379->6379/tcp
コンテナを起動後、http://localhost:8080/ へアクセスするか、またはcurl
コマンドを実行する事で確認できる。
$ curl localhost:8080
{"message":"Hello, World!!"}
また、Redisの接続確認は以下のコマンドの通りである。
# コンテナ内部に入る
$ docker exec -it [CONTAINER ID] sh
# redis-cliの起動
/data # redis-cli
# 以下のIPアドレスに入れればOK
127.0.0.1:6379>
以上まで確認できれば、一通りの環境構築・動作検証は終了である。
4. まとめ
今回は環境構築から動作確認までを行った。今回の構成を真似しなくとも、ホットリロード環境は便利なので今後参考にして頂ければと思う。
次回は、この続きでAPIの実装を行っていく。