塀の備忘録

上伊那ぼたん描いてます

go installしても$GOPATH/binにバイナリができない

はじめに

M1 Mac上でDockerコンテナにdelveAirをインストールしたところ、$GOPATH/bin下に実行バイナリが作成されなかった。

結論

$GOPATH/
└── bin/
    └── $GOOS_$GOARCH/
        └── dlv

ロスコンパイルされていたことで、$GOPATH/binでなく$GOPATH/bin/$GOOS_$GOARCH下に実行バイナリが作成されていた。 go install前に環境変数GOOSGOARCHをexportしていたために起きており、実行順序を変更して解決した。

事象

M1 Mac上で、たとえば下記のようなDockerfileに基づき、docker-composeを使ってDocker Imageのビルドを試みたとする。

FROM deps AS development

# クロスコンパイルのための環境変数
ENV CGO_ENABLED=0
ENV GOOS=linux
ENV GOARCH=amd64

WORKDIR /tmp/hoge/app
RUN go install github.com/go-delve/delve/cmd/dlv@latest
…
RUN go build -mod=mod -o /app -gcflags="all=-N -l" 

すると、下記のようなErrorが出てビルドに失敗する。 この場合、delveの実行バイナリが$GOPATH/bin配下に無いと怒られた。

ERROR: for hoge-app_1  Cannot start service hoge-app: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "/go/bin/dlv": stat /go/bin/dlv: no such file or directory: unknown

docker-composeを定義するYAML内で下記のようにdelveを呼び出しているためである。

command: dlv exec /app --listen=:13100 --headless --api-version=2 --continue --accept-multiclient -hoge-api

調査

方針

件の実行バイナリの行方を追った。

$ go install github.com/go-delve/delve/cmd/dlv@latestの結果、実行バイナリは$GOPATH/bin以外のどこかにいるのか、あるいはいないのか。

手順

一手目

上述のDockerfile内で指定していた、構築したいGo環境と同versionのOfficial Image Simple tagを利用してDockerコンテナを立ち上げる。 今回はgolang:1.16.6を指定。コンテナ内に入る。

$ docker run -it golang:1.16.6 /bin/sh

ここからはDockerfileの実行順に従う。 まず、コンテナ内で下記の環境変数を指定。

$ export CGO_ENABLED=0
$ export GOOS=linux
$ export GOARCH=amd64

次に、go installで任意のパッケージ(ここではdelve)をインストールする。

$ go install github.com/go-delve/delve/cmd/dlv@latest

ここで$GOPATH/bin配下を確認すると、delveの実行バイナリであるdlvファイルでなく、linux_amd64なるディレクトリが作成されていた。 そして、linux_amd64の配下にdlvファイルが格納されていた。

二手目

dlvファイルは存在していた。ただし$GOPATH/bin配下ではなかった。 そこで、再度Goコンテナを立ち上げ、今度は環境変数GOOSGOARCHをexportする前に、任意のパッケージ(ここではdelve)をgo installした。

すると、今度は$GOPATH/bin配下にdlvファイルが作成されていることを確認できた。

先に確認した$GOOS_$GOARCHからなるディレクトリは、環境変数GOOSGOARCHを設定すると作成され、以降go installしたパッケージの実行バイナリはその配下に格納されるようだ。

まだ分かっていないこと

本事象の確認環境についてM1 Macと明記したのは、筆者の周囲で本事象が再現したのはM1 Macユーザーのみだったからだ。

IntelモデルのMacを使用しているユーザーの環境では、パッケージインストール前にGOOSGOARCHを指定しても$GOOS_$GOARCHディレクトリは切られず、$GOPATH/bin直下に実行バイナリが作成されていた。

この差異については本校執筆時点で未調査のため、原因が分かれば追って記載する。