0
0

[golang]golangで作ったAPIをコンテナ化する方法(docker image の作成方法)

Posted at

はじめに

作ったアプリのコンテナ化(docker image の作成)ってどうやるんだっけ?
っていう話になったので備忘を兼ねてメモ

今回のゴール

golang 製のAPIアプリをコンテナ化(docker image を作成)して、 docker run で動くようにする

作業の流れ

  1. コンテナ化する go アプリの準備
  2. Dockerファイル作成
  3. コンテナイメージ(docker image)作成
  4. コンテナを起動(docker run)

準備

コンテナ化するアプリを準備します
golang で gin を使った簡単な API です
/pingなエンドポイントを叩くと pongと応答します
コードはこんな感じ

main.go
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 の軽量化とか、マルチビルドステージについて触れようかな、、、
ではでは。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0