by Renée French CC BY 3.0
はじめに
こんにちわ。Wano株式会社エンジニアのnariと申します。
今回は、alpineイメージにGoをインストールする際にはまった事案について備忘録を残したいと思います。
TL;DR
- alpineベースのイメージにGoをインストールしたいなら、wgetとかcurlとか使わずにapkを使おう
今回やりたいこと
- codebuild(CI)上でhashicorp/terraformイメージにて、apexコマンドでlambdaを自動デプロイしたい
- そのため今回は、lambdaをGo言語で書いていたためhookのbuildにGoのコンパイル環境が必要なので、hashicorp/terraformイメージに追加でGoをインストールする必要がある
問題
- hashicorp/terraformはalpineベース そこにGoをcodebuildのbuildspec.ymlにて以下のようにインストールしようとした
export GO_VERSION=1.12.4
wget https://storage.googleapis.com/golang/go{GO_VERSION}.linux-amd64.tar.gz
tar -C /usr/local -xzf go${GO_VERSION}.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
go version
すると、go version実行時に、以下のようなエラーがでた
sh: go: not found
エラー解決策
- docker - How to install Go in alpine linux - Stack Overflowに同じようなケースがあったので参考にした
With Alpine, you have libmusl instead of glibc. Alpine's libmusl is not a 1 for 1 replacement. Code linked against glibc will show a not found error which is actually from the dynamic linker. You can see what libraries are linked to the binary with ldd:
どうやら、glibcの代わりに入っているlibmusl(linux標準のCライブラリ)の挙動が異なるようです。
# ldd /usr/local/go/bin/go
/lib64/ld-linux-x86-64.so.2 (0x7f63ceed1000)
libpthread.so.0 => /lib64/ld-linux-x86-64.so.2 (0x7f63ceed1000)
libc.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7f63ceed1000)
なるほど、/lib64/ld-linux-x86-64.so.2 がalpineにはないので、そこへのdynamic linkを有する/usr/local/go/bin/goは、not found errorを返しちゃうわけですね
このかたは、Goバイナリを実行する形(go自体のダウンロードをしない)にするか、glibcを入れちゃうか(それならCentOSとかDebianつかえよ)って言ってるんですが、どちらの解決案も使わず以下のように解決しました。
apk add --update --no-cache vim git make musl-dev go curl
# Configure Go
export GOPATH=/root/go
export PATH=${GOPATH}/bin:/usr/local/go/bin:$PATH
export GOBIN=$GOROOT/bin
mkdir -p ${GOPATH}/src ${GOPATH}/bin
export GO111MODULE=on
go version
元も子もないapkでのdownload作戦、、、apkはやっぱ便利ですねというお話でした。
終わりに
既存のイメージに追加で環境を打ち込みたい際には、まずそのイメージのベースイメージを、dockerHubから辿ってDockerfileから確認するのが大事ですね。
Cライブラリ群の知識など全然ないなぁと痛感することになりましたが、今はStackOverflowなどにかなりニアリーなケースに陥っていた先人のケースがあってとても助かります。
こう言った付け焼き刃のソリューションだけでなく、どこかしらで深いところまでCライブラリの勉強などもしていきたいですね。