编译后的二进制文件不能在Ubuntu主机上的高山docker容器中运行

给定一个使用GO编译的二进制文件,使用GOOS=linuxGOARCH=amd64 ,部署到基于alpine:3.3 GOARCH=amd64容器,如果docker引擎主机是Ubuntu(15.10),二进制文件将不会运行:

 sh: /bin/artisan: not found 

如果Docker引擎主机是在Mac OS X上的VirtualBox虚拟机中部署的busybox (这是alpine的基础),那么这个相同的二进制文件(针对相同的操作系统和arch编译)将运行得很好

如果容器基于Ubuntu镜像之一,这个相同的二进制文件也可以很好的运行。

任何想法这个二进制丢失?

这是我所做的重现(成功运行在VirtualBox / OS X上的busybox未显示):

build立(即使拱门匹配,用标志显式build立):

 ➜ 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包,build可能会产生一个带有一些dynamic链接的二进制文件,例如libc。 您可以通过查看ldd output.bin的结果dynamic检查与静态链接

我遇到了两个解决scheme:

  • 禁用CGO,通过CGO_ENABLED=0
  • 强制使用Go执行net依赖,netgo通过go build -tags netgo -a -v ,这是针对某个平台实现的

来自https://golang.org/doc/go1.2

net包缺省需要cgo,因为主机操作系统通常必须调解networking呼叫设置。 但是,在某些系统上,可以在不使用cgo的情况下使用networking,并且可以这样做,例如避免dynamic链接。 新的构build标签netgo(默认closures)允许在可能的系统中构build纯Go的networking包。

上面假设唯一的CGO依赖是标准库的net包。

从你的编译机器去编译器可能会链接你的二进制文件,而不是在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"] 

我正在写关于这个问题的文章。 你可以在这里find这个解决scheme的草稿http://kefblog.com/2017-07-04/Golang-ang-docker