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

给出一个二进制文件,并使用 GOOS = linux </ code>和 GOARCH = amd64 </ code>部署到基于 alpine:3.3 </ code>的 docker </ code>容器中,如果docker引擎主机为Ubuntu(15.10),则二进制文件将不会运行:</ p >

  sh:/ bin / artisan:找不到
</ code> </ pre>

该相同的二进制文件(针对相同的OS和Arch编译)将 如果Docker引擎主机是在Mac OS X上的VirtualBox VM中部署的 busybox </ code>( alpine </ code>的基础),则运行得很好</ strong>。< / p>

如果该容器基于Ubuntu映像之一,则同样的二进制文件也可以正常运行。</ p>

任何想法,该二进制文件将丢失什么 ?</ strong> </ p>

这是我要做的复制操作(未在OS X的VirtualBox / busybox中成功运行):</ p>

构建(即使拱门匹配,也将使用标志显式构建):</ p>

 ➜工匠git:(master)✗GOOS = linux  GOARCH = amd64 go build 
</ code> </ pre>

检查它是否可以在主机上运行:</ p>

 ➜artisan git:(master  )✗./artisan 
10:14:04.925 [ERROR] artisan:需要一个命令,一个服务器,配置或构建
</ code> </ pre>

复制到docker dir,进行构建 ,运行:</ p>

 ➜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。
将构建上下文发送到Docker守护进程10.15 MB
第1步:从docker:1.10

...
➜docker git:(master)✗docker run -it artisan sh
/#/ bin / artisan
sh:/ bin / artisan:找不到
</ code> </ pre> \ n

现在将映像库更改为 phusion / baseimage </ code>:</ p>

 ➜docker git:(master)✗cat Dockerfile 
# FROM docker:1.10
FROM Phusion / baseimage
COPY build / /
➜docker git:(master)✗docker build -t artisan。
将构建上下文发送到 Docker守护程序10.15 MB
第1步:来自phusion / baseimage
...
➜docker git:(master)✗docker run -it artisan sh
#/bin/artisan
08:16:39.424 [ERROR] artisan :需要一个命令,一个服务器,提供或构建
</ code> </ pre>
</ div>

展开原文

原文

Given a binary, compiled with Go using GOOS=linux and GOARCH=amd64, deployed to a docker container based on alpine:3.3, the binary will not run if the docker engine host is Ubuntu (15.10):

sh: /bin/artisan: not found

This same binary (compiled for the same OS and arch) will run just fine if the docker engine host is busybox (which is the base for alpine) deployed within a VirtualBox VM on Mac OS X.

This same binary will also run perfectly fine if the container is based on one of Ubuntu images.

Any idea what this binary is missing?

This is what I've done to reproduce (successful run in VirtualBox/busybox on OS X not shown):

Build (building explicitly with flags even though the arch matches):

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

Check it can run on the host:

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

Copy to docker dir, build, run:

➜  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

Now changing the image base to 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 

douba7784
douba7784 您还可以尝试一些高山glibc基本映像来解决问题
4 年多之前 回复
doulu3399
doulu3399 谢谢你的提示。我将尝试一下,即使将所有内容静态链接都是我的偏爱。
4 年多之前 回复
doulu5109
doulu5109 这似乎类似于我在此处解决的问题:stackoverflow.com/questions/34729748/…
4 年多之前 回复
dsbckxk165039
dsbckxk165039 使用CGO时,二进制文件与glibc链接,但是alpine使用musllibc。(此外,tls软件包不使用cgo,除了在darwin上获取根证书外)
4 年多之前 回复
dtng5978
dtng5978 太好了,非常感谢您的帮助和解释!
4 年多之前 回复
doukuo9116
doukuo9116 默认情况下,CGO可以用于net软件包-使用上面的标记或CGO_ENABLED=0强制使用Gostd实现进行查找-您可以做的是:对每个构建变体使用lddoutput.bin来查看它们是否重新真正地静态编译,或者是否存在任何动态链接。
4 年多之前 回复
douyinbo3361
douyinbo3361 如您所建议,这有助于CGO_ENABLED=1生成-tagsnetgo-a-v。如果与CGO_ENABLED=0相比我理解正确,那么这还将在网络软件包中保留TLS功能,否则将丢失该功能,对吗?我能以某种方式看到静态链接到二进制文件的内容以及动态链接剩下的内容吗?
4 年多之前 回复
douji9734
douji9734 您可以尝试使用CGO_ENABLED=1来构建-tagsnetgo-a-vstd吗?我认为这可能是网络软件包的问题,​​导致动态链接。
4 年多之前 回复
douxia1988
douxia1988 魔术,确实如此。您能否详细说明一个答案,我会接受。
4 年多之前 回复
dqkx69935
dqkx69935 添加CGO_ENABLED=0有帮助吗?
4 年多之前 回复

3个回答



默认情况下,如果使用 net </ code>包,则构建可能会生成带有某些动态链接的二进制文件,例如 到libc。 您可以通过查看 ldd output.bin </ code> </ p>

的结果来动态检查还是静态检查链接。我遇到过两种解决方案:</ p> \ n


  • 通过 CGO_ENABLED = 0 </ code> </ li>
  • 禁用CGO强制使用Net依赖的Go实现,通过 go build -tags netgo -a -v </ code>,这是针对某些平台实现的</ li>
    </ ul>

    来自 https://golang.org/doc/go1.2 :</ p>


    默认情况下,net软件包需要cgo 因为主机操作系统通常必须中介网络呼叫设置。 但是,在某些系统上,可以使用不带cgo的网络,这样做很有用,例如,避免动态链接。 新的构建标记netgo(默认情况下为关闭)允许在可能的系统上使用纯Go构建网络软件包。</ p>
    </ blockquote>

    以上假设 标准库的 net </ code>包是唯一的CGO依赖项。</ p>
    </ div>

展开原文

原文

By default, if using the net package a build will likely produce a binary with some dynamic linking, e.g. to libc. You can inspect dynamically vs. statically link by viewing the result of ldd output.bin

There are two solutions I've come across:

  • Disable CGO, via CGO_ENABLED=0
  • Force the use of the Go implementation of net dependencies, netgo via go build -tags netgo -a -v, this is implemented for a certain platforms

From https://golang.org/doc/go1.2:

The net package requires cgo by default because the host operating system must in general mediate network call setup. On some systems, though, it is possible to use the network without cgo, and useful to do so, for instance to avoid dynamic linking. The new build tag netgo (off by default) allows the construction of a net package in pure Go on those systems where it is possible.

The above assumes that the only CGO dependency is the standard library's net package.

dongzhang7961
dongzhang7961 我认为另一种可选解决方案是将源代码复制到image中,然后exec在image中进行构建。
大约一年之前 回复
doubaran2438
doubaran2438 感谢您提供此答案,因此在Google上进行了大量查找。
一年多之前 回复
doujiao0110
doujiao0110 对于使用Bazel的任何人,都可以使用--features = static --features = pure标志来完成上述操作。
大约 2 年之前 回复
dow5001
dow5001 CGO_ENABLED = 0也解决了我的问题:尝试在非高山docker上运行高山内置的go程序。 在我的情况下,错误仅表示docker:来自守护程序的错误响应:找不到或不存在Container命令。
大约 4 年之前 回复



我在使用go二进制文件时遇到了同样的问题,将其添加到我的docker文件后,我可以使它工作:</ p>


RUN APK添加--no-cache \
libc6-compat
</ code> </ p>
</ div>

展开原文

原文

I had the same issue with a go binary, and I got it to work after adding this to my docker file:

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

doukan6564
doukan6564 我正在Alpine docker容器中运行别人的go二进制文件,我不想自己重新编译它。 我宁愿使用公开可用的二进制文件。 此解决方案解决了该问题,并让我在Alpine docker容器中运行go二进制文件
12 个月之前 回复
duanguochi6194
duanguochi6194 您需要在相同的环境中构建和运行。 例如,如果您在本地计算机中构建二进制文件并在docker内部运行,则可能会导致问题
大约一年之前 回复
duanluo9369
duanluo9369 不幸的是,这对我不起作用,并提供了错误重定位...:fprintf chk:未找到符号
大约一年之前 回复
doupu1727
doupu1727 节省了很多时间。 +1
大约一年之前 回复
douchen2011
douchen2011 帮助我在我的高山图像中运行CGO
接近 2 年之前 回复
dptt66700
dptt66700 这应该是公认的答案,更简单的解决方案
接近 2 年之前 回复



构建计算机中的Go编译器可能会将您的二进制文件链接到库中,而不是在Alpine中。 在我的情况下,它是使用/ lib64下的依赖项编译的,但是Alpine不使用该文件夹。</ p>

  FROM alpine:edge AS build 
RUN apk更新
RUN apk升级
RUN apk 添加--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获取服务器#服务器是名称 我们的应用程序
RUN CGO_ENABLED = 1 GOOS = linux转到安装-a服务器

FROM alpine:edge
WORKDIR / app
RUN cd / app
COPY --from = build / app / bin / server / app / bin / server
CMD [“ bin / server”]
</ code> </ pre>

我正在研究有关此问题的文章。 您可以在此处 http://kefblog.com/2017-07找到草稿 -04 / Golang-ang-docker 。</ p>
</ div>

展开原文

原文

Go compiler from your build machine probably links your binary with libraries on different location than in Alpine. In my case it was compiled with dependencies under /lib64 but Alpine does not use that folder.

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"]

I'm working on article about this issue. You can find draft with this solution here http://kefblog.com/2017-07-04/Golang-ang-docker .

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐