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

给定一个二进制,用围棋编译GOOS=linuxGOARCH=amd64 ,部署到docker基于容器alpine:3.3 ,如果码头工人发动机主机的Ubuntu(15.10)二进制将不会运行:

sh: /bin/artisan: not found

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

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

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

这是我所做的重现(在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的结果来动态检查与静态链接

我遇到了两种解决方案:

  • 通过CGO_ENABLED=0禁用CGO
  • 强制使用Go执行net依赖关系,netgo通过go build -tags netgo -a -v ,这是为某些平台实现的
  • 来自https://golang.org/doc/go1.2:

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

    上面假设唯一的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"]
    

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

    链接地址: http://www.djcxy.com/p/18189.html

    上一篇: compiled binary won't run in an alpine docker container on Ubuntu host

    下一篇: How to run a windows docker container on linux host?