1. ホーム
  2. go

[解決済み] Ubuntuホスト上のalpine dockerコンテナでGoコンパイルされたバイナリが実行されない

2023-01-28 08:54:11

質問

Goでコンパイルされたバイナリが GOOS=linuxGOARCH=amd64 にデプロイされ docker をベースとしたコンテナ alpine:3.3 の場合、Docker Engine のホストが Ubuntu (15.10) の場合、バイナリは実行されません。

sh: /bin/artisan: not found

この同じバイナリ(同じOS、同じアーキテクチャ用にコンパイルされたもの)は うまく動作します。 もしドッカーエンジンのホストが busybox (のベースになっています)。 alpine ) を Mac OS X 上の VirtualBox VM 内にデプロイしました。

この同じバイナリは、コンテナーが Ubuntu イメージの 1 つをベースにしている場合にも完全に問題なく実行されます。

このバイナリは何が欠けているのか、何か心当たりはありませんか?

これは私が再現したものです(OS XのVirtualBox/busyboxで成功したものは表示されていません)。

ビルド (アーカイブが一致してもフラグで明示的にビルド)。

➜  artisan git:(master) ✗ GOOS=linux GOARCH=amd64 go build

ホスト上で実行できることを確認します。

➜  artisan git:(master) ✗ ./artisan 
10:14:04.925 [ERROR] artisan: need a command, one of server, provision or build 

dockerディレクトリにコピーして、ビルド、実行。

➜  artisan git:(master) ✗ cp artisan docker/build/bin/        
➜  artisan git:(master) ✗ cd docker 
➜  docker git:(master) ✗ cat Dockerfile 
FROM docker:1.10
COPY build/ /
➜  docker git:(master) ✗ docker build -t artisan .
Sending build context to Docker daemon 10.15 MB
Step 1 : FROM docker:1.10
...
➜  docker git:(master) ✗ docker run -it artisan sh
/ # /bin/artisan 
sh: /bin/artisan: not found

ここで、画像ベースを phusion/baseimage :

➜  docker git:(master) ✗ cat Dockerfile 
#FROM docker:1.10
FROM phusion/baseimage
COPY build/ /
➜  docker git:(master) ✗ docker build -t artisan .
Sending build context to Docker daemon 10.15 MB
Step 1 : FROM phusion/baseimage
...
➜  docker git:(master) ✗ docker run -it artisan sh
# /bin/artisan
08:16:39.424 [ERROR] artisan: need a command, one of server, provision or build 

どのように解決するのですか?

デフォルトでは、もし net パッケージを使用する場合、ビルドはおそらく libc などの動的リンクのあるバイナリを生成します。動的リンクか静的リンクかは ldd output.bin

私が遭遇した解決策は2つあります。

  • CGO を無効にする。 CGO_ENABLED=0
  • net dependencies の Go の実装、netgo を強制的に使用するようにしました。 go build -tags netgo -a -v これは特定のプラットフォーム用に実装されています。

から https://golang.org/doc/go1.2 :

一般にホスト OS はネットワークコールのセットアップを仲介しなければならないので、 net パッケージはデフォルトで cgo を要求します。しかし、システムによっては、cgo なしでネットワークを使用することが可能であり、 例えばダイナミックリンクを避けるためにそうすることが有用です。新しいビルドタグ netgo (デフォルトではオフ) は、それが可能なシステムにおいて、純粋な Go で net パッケージを構築することを可能にします。

上記では、CGO の依存関係が標準ライブラリの net パッケージであると仮定しています。