回答

收藏

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

技术问答 技术问答 344 人阅读 | 0 人回复 | 2023-09-12

给出二进制文件,使用 GoGOOS=linux和编译GOARCH=amd64,部署到docker基于的容器alpine:3.3,如果 docker 发动机主机是 Ubuntu (15.10)二进制文件不会运行:
( [# A( S( o: x5 `
    sh: /bin/artisan: not found
    . N2 ?) s" `9 J9 j7 k0 O
如果 docker 发动机主机部署在 Mac OS X 上的 VirtualBox VM 中,相同的二进制文件(编译相同的操作系统和架构)将被编译成运行得很好。busybox``alpine
3 Z. w3 I! a' M  V' k若容器基于 Ubuntu 图像之一,同样的二进制文件也会运行得很好。- O/ X! [6 p1 g1 ]
你知道这个二进制文件缺少什么吗?
* a1 D) L+ w7 d- Z- E; m这是我为重现而做的(没有显示在 OS X 上的 VirtualBox/busybox 成功运行):; a+ a" k1 O* u1 P! k" ?3 t. b2 K
结构(即使拱门匹配,也采用标志显式结构):
& B' \3 C* w0 H: T9 u9 ?# K& p7 _  C
    ?  artisan gitmaster) ? GOOS=linux GOARCH=amd64 go build
    $ M. i. W# G' ^1 E# Z
检查它是否能在主机上运行:3 U! g# I* ?  l5 D8 \
    ?  artisan gitmaster) ? ./artisan 10:14:04.925 [ERROR] artisan: need a command,one of server,provision or build 9 D, A4 {/ ]! f# g8 E3 Q" S
复制到 docker 目录、构建、运行:
0 f) x! j, w5 l
    ?  artisan gitmaster) ? cp artisan docker/build/bin         artisan gitmaster) ? cd docker ?  docker gitmaster) ? cat Dockerfile FROM docker:1.10COPY build docker gitmaster) ? docker build -t artisan .Sending build context to Docker daemon 10.15 MBStep 1 : FROM docker:1.10...?  docker gitmaster) ? docker run -it artisan sh/ # /bin/artisan sh: /bin/artisan: not found1 K3 K; ~/ D/ E& B6 X( w
现在将图像库改为phusion/baseimage:
% u. }5 v5 [; Z! W( L
    ?  docker gitmaster) ? cat Dockerfile #FROM docker:1.10FROM phusion/baseimageCOPY build docker gitmaster) ? docker build -t artisan .Sending build context to Docker daemon 10.15 MBStep 1 : FROM phusion/baseimage...?  docker gitmaster) ? docker run -it artisan sh# /bin/artisan08:16:39.424 [ERROR] artisan: need a command,one of server,provision or build ; `4 g% J4 l3 N  ^5 A
               
" Z% T, M% V9 n0 E6 n/ {8 Z    解决方案:                                                               
+ p" ~0 m6 x1 q                                                                默认情况下使用的话net包,构建可能会生成一个带有一些动态链接的二进制文件,如 libc。动态检查和静态链接可以通过态链接ldd output.bin
5 j" P( I# t! G2 K  @+ h2 C我遇到过两种解决方案:
! t# D7 M% H! g: e& E- e+ ]禁用 CGO,通过 CGO_ENABLED=0/ N) h3 v7 g/ e# E! C$ B
强制使用网络依赖 Go 实现,netgo via go build -tags netgo -a -v,这是针对特定平台实现的
来自https://golang.org/doc/go1.2:
4 Q  U) i* O! k2 Nnet 包默认需要 cgo,因为主机操作系统通常需要调解网络调用设置。然而,在某些系统中,没有 cgo 的情况下使用网络,这样做很有用,例如避免动态链接。新的构建标记 netgo(默认关闭)在可能的情况下允许纯 Go 中构建 net 包。
0 ?! _5 {" g; |8 G( b# X. P唯一的 CGO 依赖项为标准库net包。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则