GOOS=linux
およびGOARCH=AMD64
を使用してGoでコンパイルされ、Alpine:3.3
に基づいてdocker
コンテナーにデプロイされたバイナリを考えると、DockerエンジンホストがUbuntuの場合、バイナリは実行されません。 (15.10):
sh: /bin/artisan: not found
この同じバイナリ(同じOSとArch用にコンパイル)は、正常に実行ドッカーエンジンホストがbusybox
(Alpine
のベース)内にデプロイされている場合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
デフォルトでは、net
パッケージを使用する場合、ビルドはおそらく動的リンクを含むバイナリを生成します。 libcへ。 ldd output.bin
の結果を表示することにより、動的リンクと静的リンクを検査できます
私が出会った2つのソリューションがあります:
CGO_ENABLED=0
経由でCGOを無効にしますgo build -tags netgo -a -v
を介したnetgo。これは特定のプラットフォームに実装されますhttps://golang.org/doc/go1.2 から:
一般に、ホストオペレーティングシステムはネットワークコールのセットアップを仲介する必要があるため、ネットパッケージにはデフォルトでcgoが必要です。ただし、一部のシステムでは、cgoを使用せずにネットワークを使用できます。これは、たとえば動的リンクを回避するために便利です。新しいビルドタグnetgo(デフォルトではオフ)を使用すると、可能な場合、それらのシステムで純粋なGoでネットパッケージを構築できます。
上記では、唯一のCGO依存関係は標準ライブラリのnet
パッケージであると想定しています。
Goバイナリでも同じ問題が発生し、これをdockerファイルに追加すると動作するようになりました。
RUN apk add --no-cache \ libc6-compat
ビルドマシンの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 で見つけることができます。