いつ go build したサーバーなのか外から確認したいときってありますよね?
はじめに
今動いているサーバーがいつ作成されたものなのか外から確認したいときってありますよね?
たぶんあるはずです。
なかったとしてもなんとなくビルドしたタイミングを外から確認できたら便利なときが来る気がするので作成方法を調べてみました。
go build で version を含める
こちらの方の記事を参考したら速攻で作成できました。ありがとうございます。
私の方でもこちらの情報を元にサーバーを起動するコードを書いてみます。
てっとり早く作りたかったので実装は以下のようになります。
package main
import (
"fmt"
"log"
"net/http"
)
var version string
func Version(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte(version))
log.Println(r.URL.Path)
}
func main() {
http.HandleFunc("/version", Version)
fmt.Printf("Server Version: %s\n", version)
log.Fatal(http.ListenAndServe("localhost:8080", nil))
}
起動時と/version
へのアクセス時にbuild時に含めた値を参照するようにしています。
ローカル環境で起動して動作確認してみます。go run main.go
では確認できなかったので以下のコマンドをMakefile
に記述しています。
export
VERSION := local
.PHONY: build
build:
@go build -ldflags "-X main.version=local" -o main
.PHONY: run
run:
@make build
@./main
❯ make run
Server Version: local
2023/0x/0x 00:00:00 /version
curl http://localhost:8080/version
local
起動ログおよびcurlによる取得にて環境変数で設定したversion値local
が設定されていることを確認できました。
ko に設定する
私はGoアプリをビルドするときkoを使っています。
koについては以下の記事を参考していただけると幸いです。
koでビルドしたコンテナにも任意のversion値を設定したいので調整していきます。
koのコンテナビルドには.ko.yaml
ファイルを用意し設定を記載する必要があります。
builds:
- id: go-build-include-version
dir: .
main: ./
env:
- GOOS=linux
- GOARCH=amd64
- CGO_ENABLED=0
ldflags:
- -s -w
- -X main.version=local
こちらのファイルを用意して以下のコマンドにてローカル環境で動作確認をしてみます。
起動コマンドは以下となります。(Makefile
だとうまく動かせなかったので直接実行)
❯ docker run --rm -p 8080:8080 $(ko publish --local .)
2023/0x/0x 00:00:00 Using base distroless.dev/static:latest@sha256:eae79cd3ef653a6233fa1f87d3643cb3ff279eebf78fd8ff83d1a44255a06628 for gobuildincludeversion
2023/0x/0x 00:00:00 Using build config go-build-include-version for gobuildincludeversion
2023/0x/0x 00:00:00 Building gobuildincludeversion for linux/amd64
2023/0x/0x 00:00:00 Loading ko.local/gobuildincludeversion-31abc168f0c3cbc7d0b2bce8e9fea564:7082117446b97c197618deadea1665d9f1acd1e06cf710f41cdadc9194def205
2023/0x/0x 00:00:00 Loaded ko.local/gobuildincludeversion-31abc168f0c3cbc7d0b2bce8e9fea564:7082117446b97c197618deadea1665d9f1acd1e06cf710f41cdadc9194def205
2023/0x/0x 00:00:00 Adding tag latest
2023/0x/0x 00:00:00 Added tag latest
Server Version: local
koを用いてもversion値local
を含めてコンテナをビルド・起動できることが確認できました。
動的にversionを指定する
koを用いてもversion値を含めることが確認できましたが、いちいち.ko.yaml
を編集・コミットしていくのは手間です。
そこで動的に.ko.yaml
を作成することを考えます。
私の持ち手で使えそうなツールとしてenvsubst
を知っていたので利用します。
builds:
- id: go-build-include-version
dir: .
main: ./
env:
- GOOS=linux
- GOARCH=amd64
- CGO_ENABLED=0
ldflags:
- -s -w
- -X main.version=${VERSION}
動的に指定したい値を${VERSION}
としファイル名を.ko.yaml.template
として保存します。
そして以下のコマンドをMakefile
に記載し実行します。
export
VERSION := local
.PHONY: ko
ko:
@envsubst '$$VERSION' < .ko.yaml.template > .ko.yaml
make ko
結果として以下のような.ko.yaml
が出力されます。
builds:
- id: go-build-include-version
dir: .
main: ./
env:
- GOOS=linux
- GOARCH=amd64
- CGO_ENABLED=0
ldflags:
- -s -w
- -X main.version=local
これで任意の値を.ko.yaml
に設定することができました!
動作確認をCIで行う
より実践的な使い方でGitHubActions
にて動的に設定をしてみようと思います。
最終的な成果物はこのようになりました。
name: version
run-name: ${{ github.ref_name }} by @${{ github.actor }} [${{ github.workflow }}]
on:
workflow_dispatch:
jobs:
version:
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v3
# 含めるバージョンを環境変数に設定する
# 今回は最新のコミットハッシュを設定する
- name: Create version
run: |
version=$(git show --format='%H' --no-patch)
echo "VERSION=${version}" >> $GITHUB_ENV
# envsubstを使うためのインストールコマンド
- name: Install gettext
run: sudo apt-get install gettext
- name: Set up go
uses: actions/setup-go@v3
with:
go-version-file: go.mod
# ツールのバージョン管理ツール
# なくても大丈夫です。
- name: Setup aqua
uses: aquaproj/aqua-installer@v2.0.2
with:
aqua_version: v1.33.0
# aquaを用いてkoをインストールします。
# go install github.com/google/ko@latest でも問題ないです。
- name: Install ko
run: ${AQUA_ROOT_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/aquaproj-aqua}/bin/aqua install -t ko
# .ko.yamlファイルを作成します。
- name: Create .ko.yaml
env:
VERSION: ${{ env.VERSION }}
run: envsubst '$$VERSION' < .ko.yaml.template > .ko.yaml
# koを用いてコンテナビルドおよび起動時にversionが指定されているか確認します。
- name: Build ko container
run: |
docker run --rm -p 8080:8080 $(ko publish --local .) &
echo PID=$! >> $GITHUB_ENV
sleep 120
# 念の為。
- name: Shutdown
if: always()
run: kill ${{ env.PID }}
こちらのCIを実行して以下のログが出力されました。
Run docker run --rm -p 8080:8080 $(ko publish --local .) &
docker run --rm -p 8080:8080 $(ko publish --local .) &
echo PID=$! >> $GITHUB_ENV
sleep 120
shell: /usr/bin/bash -e {0}
env:
VERSION: 87bada15034ea4b1e9f23e35ba3d632db56f268c
time="2023-0x-0xT00:00:00Z" level=info msg="download and unarchive the package" aqua_version=1.33.0 env=linux/amd64 exe_name=ko exe_path=/home/runner/.local/share/aquaproj-aqua/pkgs/github_release/github.com/ko-build/ko/v0.12.0/ko_0.12.0_Linux_x86_64.tar.gz/ko package=ko-build/ko package_name=ko-build/ko package_version=v0.12.0 program=aqua registry=standard
2023/0x/0x 00:00:00 Using base distroless.dev/static:latest@sha256:eae79cd3ef653a6233fa1f87d3643cb3ff279eebf78fd8ff83d1a44255a06628 for gobuildincludeversion
2023/0x/0x 00:00:00 Using build config go-build-include-version for gobuildincludeversion
2023/0x/0x 00:00:00 Building gobuildincludeversion for linux/amd64
2023/0x/0x 00:00:00 Loading ko.local/gobuildincludeversion-31abc168f0c3cbc7d0b2bce8e9fea564:64800cc9ddfa45f0e9e69e13ce22a45ce2336d09f51b8238e891f4c53cc587ca
2023/0x/0x 00:00:00 Loaded ko.local/gobuildincludeversion-31abc168f0c3cbc7d0b2bce8e9fea564:64800cc9ddfa45f0e9e69e13ce22a45ce2336d09f51b8238e891f4c53cc587ca
2023/0x/0x 00:00:00 Adding tag latest
2023/0x/0x 00:00:00 Added tag latest
Server Version: 87bada15034ea4b1e9f23e35ba3d632db56f268c
無事サーバーにversion値87bada15034ea4b1e9f23e35ba3d632db56f268c
が設定されて起動できていることが確認できました!
本格的に使う場合はGitHubActionsに以下のようなjobを追加してビルドしたコンテナをデプロイしてください。
- name: Docker login
run: ko login -u ${{ secrets.DOCKERHUB_USERNAME }} -p ${{ secrets.DOCKERHUB_PASSWORD }} index.docker.io
- name: Build and push container
run: |
KO_DOCKER_REPO=${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKERHUB_REPOSITORY }} \
SOURCE_DATE_EPOCH=$(date +%s) \
ko build --sbom=none --bare --tags=${{ env.VERSION }},latest ./ --platform=linux/amd64
環境・ツールバージョン
❯ go version
go version go1.19.6 darwin/arm64
※ golangci-lintが通らず1.20.1に上げられない...
❯ aqua version
aqua version 1.33.0
❯ ko version
v0.12.0
おわりに
今回作成したものは以下のリポジトリに置いておきます。
無事version値を返すGoサーバーコンテナを作成することができました。
ただ、今回はmain
指定であったので他のファイルおよびパッケージの場合はどうするのかもう少し確認する必要がありそうです。
Discussion