はじめに
作ったアプリのコンテナ化(docker image の作成)ってどうやるんだっけ?
っていう話になったので備忘を兼ねてメモ
今回のゴール
golang 製のAPIアプリをコンテナ化(docker image を作成)して、 docker run で動くようにする
作業の流れ
- コンテナ化する go アプリの準備
- Dockerファイル作成
- コンテナイメージ(docker image)作成
- コンテナを起動(docker run)
準備
コンテナ化するアプリを準備します
golang で gin を使った簡単な API です
/ping
なエンドポイントを叩くと pong
と応答します
コードはこんな感じ
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "pong",
})
})
r.Run()
}
go run main.go
で起動して、curl でリクエストを投げるとこんな感じにレスポンスが返ってきます
% curl localhost:8080/ping
{"message":"pong"}
今回は、このアプリを内包した docker image を作成していきます
Dockerfile の作成
作成した Dockerfile
# ベースイメージとしてGoのバージョン1.21を使用
FROM golang:1.21
# 作業ディレクトリを `/usr/src/app` に設定
WORKDIR /usr/src/app
# `go.mod` と `go.sum` (依存関係の管理ファイル) をコンテナにコピー
COPY go.mod go.sum ./
# 依存関係をダウンロードし、キャッシュを利用してビルド
RUN go mod download
# プロジェクト全体をコンテナにコピー
COPY . /usr/src/app
# Goプログラムをビルド (CGOを無効化し、スタティックバイナリを作成)
# `CGO_ENABLED=0` は、C言語に依存しないビルドを意味する
# `-v` はビルドの詳細を表示し、`-o app` は出力ファイル名を `app` に指定
RUN CGO_ENABLED=0 go build -v -o app
# コンテナ実行時にビルドしたアプリケーションを起動
CMD ["./app"]
以下のコマンドで docker image 作成します
docker build -t go-docker-handson-1 .
実際にイメージが作成されたか確認してみます
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
go-docker-handson-1 latest c490c80a2582 2 minutes ago 1.18GB 1.15GB
ちゃんと作成されてますね、よかった!
ファイルサイズが異様に大きいですが、これは使用しているベースイメージが golang:1.21
なので、本来 go を動かすのに不要なファイルなんかが含まれているからです。
なので、実際に本番環境で動かす docker image を作る際には、もっと軽量なベースイメージを使ったり、マルチビルドとかするんですけど、この話はまた別の機会に。
では、実際に作った docker image を run して、アプリが起動するか確認してみます
docker run -d go-docker-handson-1
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] GET /ping --> main.main.func1 (3 handlers)
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
[GIN-debug] Listening and serving HTTP on :8080
別ターミナルにて
curl localhost:8080/ping
{"message":"pong"}%
はい、ちゃんと期待通り動いてますね!よかった
最後に
今回作ったものは以下に公開しています
よかったら参考までに
https://github.com/Ixy-194/handson-go-doker/tree/main/handson-1
次回は docker image の軽量化とか、マルチビルドステージについて触れようかな、、、
ではでは。