cloudbuildでビルドしたgo言語ファイルがdockerのubuntuイメージ上で実行できない

問題

cloudbuildでビルドしたGo言語のプログラム(ELF形式)を、dockerコンテナ( ubuntu:latest )上で実行しようとしすると実行に失敗する。

# file myapp
myapp: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-, not stripped

# ./myapp
bash: ./myapp: No such file or directory

原因

ELFファイルを readelf すると以下のように、 ubuntu:latest 上には存在しない ld-musl-x86_64 に対しinternal linkが張られていることがわかる。

# readelf -a ./myapp  | grep Requesting
      [Requesting program interpreter: /lib/ld-musl-x86_64.so.1]

go言語のビルド設定である、 cloudbuild.yaml のビルド設定は以下のようにしていた。以下の書き方の場合、明示的にタグを指定していないため latest タグのついたイメージが取得される。

  - name: 'gcr.io/cloud-builders/go'
    id: 'GO_BUILD'
    args: ['install', '.']
    env:
      - 'PROJECT_ROOT=github.com/shinmatsuzaki/myapp'

gcr.io/cloud-builders/go の場合、latest タグはalpineベースのイメージに対し付与される。 そのために、go言語のビルドが実行される際、ELFに対しalpine linux上のライブラリがリンクされる。同名のライブラリがubuntuイメージ上にない場合、ELFの実行に失敗する。

$ gcloud container images list-tags gcr.io/cloud-builders/go | head -4
DIGEST        TAGS           TIMESTAMP
dfabdc5d6ad7  debian         2020-02-15T18:23:35
c3bf65790cab  alpine,latest  2020-02-15T18:23:12

対処

不足するライブラリをubuntuイメージにインストールする方向で、Dockerfileに RUN apt update && apt install -y musl-dev を追加。

※以下の記事のように、 cloudbuild.yaml でgoのbuildに指定するイメージとして gcr.io/cloud-builders/go:debian を指定する方法でも問題を解消できると思います。

参考

/* https://sunrise033.com/entry/hatena-blog-how-to-hierarchicalize-categories */