回答

收藏

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

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

给出二进制文件,使用 GoGOOS=linux和编译GOARCH=amd64,部署到docker基于的容器alpine:3.3,如果 docker 发动机主机是 Ubuntu (15.10)二进制文件不会运行:5 c( f2 x2 n! Q+ x
    sh: /bin/artisan: not found# G! |+ v+ n5 ^1 O/ }, W1 g+ V1 e* U
如果 docker 发动机主机部署在 Mac OS X 上的 VirtualBox VM 中,相同的二进制文件(编译相同的操作系统和架构)将被编译成运行得很好。busybox``alpine- l; S; Q5 A, ^' U* ^7 E. f; f
若容器基于 Ubuntu 图像之一,同样的二进制文件也会运行得很好。
: z0 p: P5 ^7 t' y你知道这个二进制文件缺少什么吗?1 d( n$ }' d8 f$ U$ I) S& T
这是我为重现而做的(没有显示在 OS X 上的 VirtualBox/busybox 成功运行):
! ?0 |7 C( K" R结构(即使拱门匹配,也采用标志显式结构):
  m7 @4 ]8 B2 D% t9 Z% R) G5 F& H' j
    ?  artisan gitmaster) ? GOOS=linux GOARCH=amd64 go build
    0 T. H! D9 ?+ `
检查它是否能在主机上运行:
! A5 t& i* `$ _
    ?  artisan gitmaster) ? ./artisan 10:14:04.925 [ERROR] artisan: need a command,one of server,provision or build
      N! U" p) h  Y2 K9 k
复制到 docker 目录、构建、运行:
3 r& s  R6 ]+ x0 S  i: G6 D
    ?  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 found' Y3 d: g7 u' p6 k1 G7 i5 y
现在将图像库改为phusion/baseimage:
1 n/ S4 S% O# I+ o7 i% Z/ @
    ?  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 1 j3 H$ U0 Z: s! i
               
8 I2 O6 K) v1 A# e5 y7 _- B    解决方案:                                                               
7 x+ P0 ], d0 z' r                                                                默认情况下使用的话net包,构建可能会生成一个带有一些动态链接的二进制文件,如 libc。动态检查和静态链接可以通过态链接ldd output.bin
5 o2 _+ Y' _9 t1 p) V3 ]4 }1 f我遇到过两种解决方案:
# i6 ~2 i9 z  P1 D2 p禁用 CGO,通过 CGO_ENABLED=0
# R# O& z8 q  S; L强制使用网络依赖 Go 实现,netgo via go build -tags netgo -a -v,这是针对特定平台实现的
来自https://golang.org/doc/go1.2:
8 j9 r8 Y5 x1 X! R$ anet 包默认需要 cgo,因为主机操作系统通常需要调解网络调用设置。然而,在某些系统中,没有 cgo 的情况下使用网络,这样做很有用,例如避免动态链接。新的构建标记 netgo(默认关闭)在可能的情况下允许纯 Go 中构建 net 包。* C( C- u2 z" m# S% J
唯一的 CGO 依赖项为标准库net包。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则