takaya030の備忘録

PHP、Laravel、Docker などの話がメインです

minikube + skaffold でGo言語のアプリケーションを動かす

検証環境

Windows11 Home Edition (version 22H2)
VirtualBox 7.0.6
vagrant 2.3.4

# Docker Host OS
ubuntu 22.04.2 LTS

go version go1.20.3 linux/amd64
Docker version 23.0.3, build 3e7cbfd
minikube version: v1.30.1
skaffold v2.3.0

ファイル構成

helloecho フォルダを作成しその中に main.gohellomodules/hander.go を作成する

helloecho
├── hellomodules
│   └── handler.go
└── main.go
// main.go

package main

import (
    "github.com/labstack/echo"
    "github.com/takaya030/helloecho/hellomodules"
)

func main() {
    // Echoのインスタンス作る
    e := echo.New()

    // ルーティング
    e.GET("/hello", handler.MainPage())
    e.GET("/api/hello", handler.ApiHelloGet())

    // サーバー起動
    e.Start(":8080")
}
// hellomodules/handler.go

package handler

import (
    "net/http"

    "github.com/labstack/echo"
)

func MainPage() echo.HandlerFunc {
    return func(c echo.Context) error {
        return c.String(http.StatusOK, "Hello World")
    }
}

func ApiHelloGet() echo.HandlerFunc {
    return func(c echo.Context) error {
        return c.JSON(http.StatusOK, map[string]interface{}{"hello": "world"})
    }
}

Go Modules の初期化

$ cd helloecho
$ go mod init github.com/takaya030/helloecho
$ go mod tidy

成功すると go.modgo.sum が作られる

helloecho
├── go.mod
├── go.sum
├── hellomodules
│   └── handler.go
└── main.go

Dockerfile の作成

下記の内容で Dockerfile を作成する

FROM golang:1.20 as build

WORKDIR /go/src/app
COPY go.mod go.sum /go/src/app/
RUN go mod download

COPY . /go/src/app
RUN go build -o /go/bin/app

FROM gcr.io/distroless/base-debian10
COPY --from=build /go/bin/app /
CMD ["/app"]

マニュフェストの作成

下記の内容で k8s-app.yaml を作成する

apiVersion: v1
kind: Service
metadata:
  name: sample-app
spec:
  selector:
    app: sample-app
  ports:
    - port: 80
      targetPort: http
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-app
spec:
  selector:
    matchLabels:
      app: sample-app
  template:
    metadata:
      labels:
        app: sample-app
    spec:
      containers:
        - name: sample-app
          # ビルドしたコンテナイメージ
          image: sample-app:latest
          imagePullPolicy: Never
          ports:
            - name: http
              containerPort: 8080

Skaffold 定義ファイルの作成

以下のコマンドで定義ファイルのテンプレートを作成

$ skaffold init --force

作成された skaffold.yaml を下記内容に変更
( portForward の設定を追加)

apiVersion: skaffold/v4beta4
kind: Config
metadata:
  name: helloecho
build:
  artifacts:
    - image: sample-app
      docker:
        dockerfile: Dockerfile
manifests:
  rawYaml:
    - k8s-app.yaml
portForward:
- resourceType: service
  resourceName: sample-app
  namespace: default
  port: 80
  address: 0.0.0.0
  localPort: 8080

最終的なファイル構成

helloecho
├── Dockerfile
├── go.mod
├── go.sum
├── hellomodules
│   └── handler.go
├── k8s-app.yaml
├── main.go
└── skaffold.yaml

動作確認

minikube を起動

$ minikube start --listen-address=0.0.0.0

dockerminikubeリポジトリを使用するように変更

$ eval $(minikube -p minikube docker-env)

helloecho フォルダに移動後、 skaffold dev を実行

$ cd helloecho
$ skaffold dev --port-forward

エラーが無ければ以下のように web サーバーが起動する

Starting deploy...
 - service/sample-app created
 - deployment.apps/sample-app created
Waiting for deployments to stabilize...
 - deployment/sample-app is ready.
Deployments stabilized in 3.224 seconds
Port forwarding service/sample-app in namespace default, remote port 80 -> http://0.0.0.0:8080
Listing files to watch...
 - sample-app
Press Ctrl+C to exit
Watching for changes...
[sample-app]
[sample-app]    ____    __
[sample-app]   / __/___/ /  ___
[sample-app]  / _// __/ _ \/ _ \
[sample-app] /___/\__/_//_/\___/ v3.3.10-dev
[sample-app] High performance, minimalist Go web framework
[sample-app] https://echo.labstack.com
[sample-app] ____________________________________O/_______
[sample-app]                                     O\
[sample-app] ⇨ http server started on [::]:8080

http://[minikubeのホスト]:8080/helloGET して Hello World が返れば成功

$ curl http://192.168.33.10:8080/hello
Hello World

このままの状態で hellomodules/handler.go を下記内容に変更

--- a/handler.go  2023-04-15 13:51:14.986453215 +0000
+++ b/handler.go  2023-04-15 13:52:29.530453215 +0000
@@ -8,7 +8,7 @@

 func MainPage() echo.HandlerFunc {
        return func(c echo.Context) error {
-               return c.String(http.StatusOK, "Hello World")
+               return c.String(http.StatusOK, "Hello Echo")
        }
 }

変更を保存すると自動でビルドが実行される

Generating tags...
 - sample-app -> sample-app:latest
Some taggers failed. Rerun with -vdebug for errors.
Checking cache...
 - sample-app: Not found. Building
Starting build...
Found [minikube] context, using local docker daemon.
Building [sample-app]...
Target platforms: [linux/amd64]
#1 [internal] load build definition from Dockerfile
#1 transferring dockerfile:
#1 transferring dockerfile: 32B 0.0s done
#1 DONE 0.1s

#2 [internal] load .dockerignore
#2 transferring context: 2B 0.0s done
#2 DONE 0.1s

#3 [internal] load metadata for gcr.io/distroless/base-debian10:latest
#3 DONE 0.0s

#4 [internal] load metadata for docker.io/library/golang:1.20
#4 DONE 0.0s

#5 [build 1/6] FROM docker.io/library/golang:1.20
#5 DONE 0.0s

#6 [stage-1 1/2] FROM gcr.io/distroless/base-debian10
#6 DONE 0.0s

#7 [internal] load build context
#7 transferring context: 610B 0.0s done
#7 DONE 0.1s

#8 [build 3/6] COPY go.mod go.sum /go/src/app/
#8 CACHED

#9 [build 2/6] WORKDIR /go/src/app
#9 CACHED

#10 [build 4/6] RUN go mod download
#10 CACHED

#11 [build 5/6] COPY . /go/src/app
#11 DONE 0.3s

#12 [build 6/6] RUN go build -o /go/bin/app
#12 DONE 30.3s

#6 [stage-1 1/2] FROM gcr.io/distroless/base-debian10
#6 CACHED

#13 [stage-1 2/2] COPY --from=build /go/bin/app /
#13 DONE 0.2s

#14 exporting to image
#14 exporting layers
#14 exporting layers 0.2s done
#14 writing image sha256:d01915d4980a60dfd909d4b7403ea1c41146f29e0a2841547fa2f4a4177886f2 done
#14 naming to docker.io/library/sample-app:latest done
#14 DONE 0.2s
Build [sample-app] succeeded
Tags used in deployment:
 - sample-app -> sample-app:d01915d4980a60dfd909d4b7403ea1c41146f29e0a2841547fa2f4a4177886f2
Starting deploy...
 - deployment.apps/sample-app configured
Waiting for deployments to stabilize...
 - deployment/sample-app is ready.
Deployments stabilized in 3.289 seconds
Port forwarding service/sample-app in namespace default, remote port 80 -> http://0.0.0.0:8080
Watching for changes...

ビルド終了後再度 http://[minikubeのホスト]:8080/helloGET すると変更が反映されている

$ curl http://192.168.33.10:8080/hello
Hello Echo

終了処理

Ctrl + Cskaffold を停止

minikube を停止

$ minikube stop

dockerリポジトリの向き先を戻す

$ eval $(minikube docker-env -u)

参考サイト

qiita.com

zenn.dev

developer.mamezou-tech.com

developer.mamezou-tech.com

skaffold.dev