这篇文章是关于如何为Go程序创建一个最小的Docker映像。本站觉得很实用,就分享给大家参考,跟着本站看了看。
前言
之前介绍了关于在docker部署golang项目的相关内容,对你入门有一定的参考价值。本文将向您介绍如何使用docker来打包golang编写的应用程序,最终产品是一个Dockerfile。不要小看这短短的几行代码,其中涉及到很多知识点。接下来我们仔细分析一下。
来自德国:阿尔卑斯山
ADDsrc/go/src
RUNgoinstall-vtest
ENTRYPOINT[\’/go/bin/test\’]
1. 基础镜像选择
第一行是指定一个基本图像,并基于它创建我们的图像。这里我们使用golang:alpine版本。
这是一个相对较小的linux系统。linux中的很多工具都被切断了。包管理工具使用apk。你可以拉这个图像Docker玩玩。默认外壳是sh。执行命令docker pull-t-I Golang : Alpine/bin/sh进入命令行。输入后执行env查看环境变量,因为其环境变量GOPATH对后续环境部署很有用,可以看到环境变量GOPATH的默认值是/go
2. 映射代码文件并安装
使用ADD src /go/src将主机scr文件映射到/go/src目录。为什么一定是这个/go/src目录?没错,就是上面的GOPATH环境变量的路径,因为我们需要执行go install命令来稍后安装,否则,我们需要重置GOPATH来安装编译后的二进制文件。
此时,在
需要注意的是:
本地主机的src目录中的文件组织必须严格遵循将要安装时生成的包的文件结构。test是程序的主程序,glog是使用的开源日志库。整个文件结构如下。因为main.go在导入包时使用了“github.com/golang/glog\’”路径,所以有必要给它一个合理的路径。
Dockerfile
src
github.com
golang
活动:慈云数据爆款香港服务器,CTG+CN2高速带宽、快速稳定、平均延迟10+ms 速度快,免备案,每月仅需19元!! 点击查看 glog
glog_file.go
glog.go
glog_test.go
LICENSE
README
test
main.go还有一个小提示,程序的日志库使用了第三方开源glog。当我们使用git对我们上面的代码进行版本管理的时候,我们不需要重复包含glog的代码,直接添加一个引用就可以了。这样有很多好处。当库中的代码被修改时,可以直接更新到远程代码仓库,克隆时可以自动导入库,也就是说具体的代码会被本地拉出来。
Glog可以通过命令生成:gi子模式添加https://github.com/golang/glog.git src/github.com/golang/glog。
注意:
的git remoule命令中引用的位置是src/github.com/golang而不是src/direct,因为执行这个命令后,本地代码仓库会把glog克隆为代码仓库,下拉它的代码,只把glog创建为目录,所以之前的一些父目录需要自己创建。
有关命令的更多信息,请参见Git。
Go install可以在组织好文件结构后进行,生成的文件可以在$GOPATH/bin中执行,后面是基本的指定入口程序和参数。通过docker build -t=\’name \’生成图像。
3.更进一步:提前编译
上面的方法是把代码复制到基本镜像里面编译。毫无疑问golang:alpine包含了一系列的程序运行依赖,这些库会在程序运行时动态加载。我们可以使用ldd命令来查看生成的二进制文件的依赖关系:
Linux-vdso . so . 1=(0x 00007 ffc 5b 1 e 4000)
libpthread . so . 0=/lib/x86 _ 64-Linux-GNU/libpthread . so . 0(0x 00007 f 50 a1 f 13000)
libc . so . 6=/lib/x86 _ 64-Linux-GNU/libc . so . 6(0x 00007 f 50 a1 B4 a 000)
/lib64/ld-linux-x86-64.so.2
(0x00005611a4b0a000)
那么问题来了? 如果将这些依赖静态编译至可执行文件中那就不需要在环境中保存这些多余的信息了,就可以创建一个更小的镜像了。幸运的是无论是golang的编译机制还是docker的基础镜像都提供这样的实现:
使用命令生成静态编译的二进制文件:
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main
.
此时用ldd查看生成的可执行文件的依赖,可以看到显示
not a dynamic executable
,这里我们禁用CGO使其生成静态二进制文件,同时设置系统为linux。我们将基础镜像设置为 scratch,这是一个很小的的镜像。
重新编写的Dockerfile如下:
FROMscratchADDmain/ENTRYPOINT[\"/main\"]CMD[\"-logtostderr\"]
执行
docker build -t example-scratch
.生成镜像,可以看到该镜像的大小只有8.27M大小,并且可以正常执行。
在实际情况中有时会将两种情况结合使用,先在一个镜像中构建,在另一个镜像中执行。下面的Dockerfile摘自prometheus这个第三方监控的演示案例的Dockerfile,可以看到它是首先在builder镜像中下载对应的依赖并且编译程序,最后在scratch基础镜像中执行程序。
#ThisDockerfilebuildsanimageforaclient_golangexample.##Useas(fromtherootfortheclient_golangrepository):jingx#dockerbuild-fexamples/$name/Dockerfile-tprometheus/golang-example-$name.#Builderimage,wherewebuildtheexample.FROMgolang:1.9.0ASbuilderWORKDIR/go/src/github.com/prometheus/client_golangCOPY..WORKDIR/go/src/github.com/prometheus/client_golang/prometheusRUNgoget-dWORKDIR/go/src/github.com/prometheus/client_golang/examples/simpleRUNCGO_ENABLED=0GOOS=linuxgobuild-a-tagsnetgo-ldflags\'-w\'#Finalimage.FROMscratchLABELmaintainer\"ThePrometheusAuthors\"COPY--from=builder/go/src/github.com/prometheus/client_golang/examples/simple.EXPOSE8080ENTRYPOINT[\"/simple\"]
感谢各位的阅读!关于“怎么为Go程序创建一个最小的Docker Image”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!
《怎么为Go程序创建一个最小的Docker Image》来自互联网同行内容,若有侵权,请联系我们删除!
还没有评论,来说两句吧...