web-dev-qa-db-ja.com

Go-compiledバイナリは、UbuntuホストのAlpineドッカーコンテナでは実行されません。

GOOS=linuxおよびGOARCH=AMD64を使用してGoでコンパイルされ、Alpine:3.3に基づいてdockerコンテナーにデプロイされたバイナリを考えると、DockerエンジンホストがUbuntuの場合、バイナリは実行されません。 (15.10):

sh: /bin/artisan: not found

この同じバイナリ(同じOSとArch用にコンパイル)は、正常に実行ドッカーエンジンホストがbusyboxAlpineのベース)内にデプロイされている場合VirtualBox VM。

コンテナがUbuntuイメージの1つに基づいている場合、この同じバイナリも完全に正常に実行されます。

このバイナリが欠落しているものは何ですか?

これは私が再現するために行ったことです(OS XのVirtualBox/busyboxでの実行は表示されていません):

ビルド(Archが一致しても、フラグを使用して明示的にビルド):

➜  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 dirにコピー、ビルド、実行:

➜  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 
49
Oleg Sklyar

デフォルトでは、netパッケージを使用する場合、ビルドはおそらく動的リンクを含むバイナリを生成します。 libcへ。 ldd output.binの結果を表示することにより、動的リンクと静的リンクを検査できます

私が出会った2つのソリューションがあります:

  • CGO_ENABLED=0経由でCGOを無効にします
  • Net依存関係のGo実装の使用を強制する、go build -tags netgo -a -vを介したnetgo。これは特定のプラットフォームに実装されます

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

一般に、ホストオペレーティングシステムはネットワークコールのセットアップを仲介する必要があるため、ネットパッケージにはデフォルトでcgoが必要です。ただし、一部のシステムでは、cgoを使用せずにネットワークを使用できます。これは、たとえば動的リンクを回避するために便利です。新しいビルドタグnetgo(デフォルトではオフ)を使用すると、可能な場合、それらのシステムで純粋なGoでネットパッケージを構築できます。

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

57

Goバイナリでも同じ問題が発生し、これをdockerファイルに追加すると動作するようになりました。

RUN apk add --no-cache \ libc6-compat

40
zakaria amine

ビルドマシンのGoコンパイラは、おそらくバイナリをAlpineとは異なる場所にあるライブラリにリンクします。私の場合、/ lib64の下の依存関係でコンパイルされましたが、Alpineはそのフォルダーを使用しません。

FROM Alpine:Edge AS build
RUN apk update
RUN apk upgrade
RUN apk add --update go=1.8.3-r0 gcc=6.3.0-r4 g++=6.3.0-r4
WORKDIR /app
ENV GOPATH /app
ADD src /app/src
RUN go get server # server is name of our application
RUN CGO_ENABLED=1 GOOS=linux go install -a server

FROM Alpine:Edge
WORKDIR /app
RUN cd /app
COPY --from=build /app/bin/server /app/bin/server
CMD ["bin/server"]

私はこの問題に関する記事に取り組んでいます。このソリューションのドラフトは、ここで http://kefblog.com/2017-07-04/Golang-ang-docker で見つけることができます。

8
Norbert Szydlik