本站教程收集整理的这篇文章主要介绍了如何为你的Go应用创建轻量级Docker镜像?,本站教程本站觉得挺不错的,现在分享给大家,也给大家做个参考。
刘明 译分布式实验室
恭喜!你已经创建了一个出色的go应用程序,现在你想创建一个Docker容器来分发你的应用。
但是,如何尽可能为你的Golang应用程序打造一个最小的镜像呢?提示:我们将会使用多阶段构建(自从Docker 17.05版本提供的方法)来完成这个目标。介绍
多什么?
简单来讲,多阶段。
多阶段允许在创建Dockerfile时使用多个from,它非常有用,因为它使我们能够使用所有必需的工具构建应用程序。举个例子,首先我们使用Golang的基础镜像,然后在第二阶段的时候使用构建好的镜像的二进制文件,最后阶段构建出来的镜像用于发布到我们自己的仓库或者是用于上线发布。
在上述的案例中,我们总共有三个阶段:
-
build编译阶段
-
certs(可选,可有可无)证书认证阶段
-
prod生产阶段
在build阶段主要是编译@R_814_9616@程序,证书认证阶段将会安装我们所需要的CA证书,最后的生产发布阶段会将我们构建好的镜像推到镜像仓库中。而且发布阶段将会使用build阶段编译完毕的二进制文件和certs阶段安装的证书。
项目发布的多个build阶段
示例工程
对于这个方法,我们将使用一个非常简单的项目。它只是一个运行在8080端口的http服务,并且返回结果为传递过去的URL的内容结果。
举例
GET http://localhost:8080url=https://google.com 返回结果为goole页面内容展示。
你也可以在这里[1]找到代码仓库。
在master分支上只包含了应用程序,final分支上还包含本篇教程中使用的Dockerfile文件。
如果你想跟着本教程来做,只需要拉下master上的代码并且跟着我来创建Dockerfile。
步骤1 - 编译阶段
第一阶段主要是使用Golang基础镜像来将@R_814_9616@程序打包为二进制文件。这个基础镜像包含了将@R_814_9616@程序编译成可执行二进制文件的所有工具。
下面是我们最原始的Dockerfile:
-
第4行:使用的基础镜像(golang:1.10)并且我们使用as给当前阶段一个别名,也可以使用阶段索引来引用前一阶段,但这使得它更清晰。
-
第7行:我们将工作目录设置为Golang基础镜像的默认$GOPATH中的应用程序目录。
-
第10行:添加@R_814_9616@程序源文件。
-
第13行:编译二进制文件。使用不同的参数来创建一个完整的静态库,因为在生产环境拉取镜像时可能不一定需要所有的Golang VM以及C语言库。
-
第16行:使用设定的命令来启动应用程序。
现在我们进行编译并使用Docker容器,@R_814_9616@程序如我们预期正常运行:
我们可以使用curl命令来请求,并且它会返回http://google.com页面内容。
在终端运行curl localhost:8080。
让我们使用docker images,来看看镜像的大小:
荒唐,太荒唐了,一个这么小的应用居然占了磁盘818M内存空间。
推送到镜像仓库后,镜像大小被压缩到309M。
docker hub 占用309M
接下来我们来改善这种情况,把镜像的大小降低到10M!
步骤2 - 生产阶段
上面提供的镜像是完全可以进行部署使用的,但是它真的是太大了。每次在Kubernetes上启动你的容器时需要拉取309M的镜像?真的是太浪费时间和带宽。
让我们来为我们的镜像构建一个生产阶段,正如上面解释的,这个阶段只是从build阶段拷贝二进制文件到容器中。
我们新的Dockerfile将会如下所示:
如你所见,同一个Dockerfile文件中我们添加了第二个FROM语句。这次,我们直接拉取二进制文件,不需要添加任何其他依赖。
-
第23行:拉取基础镜像
-
第26行:从/go/src/github.com/scboffspring/blog-multistage-go/blog-multistage-go拷贝build阶段编译的文件
-
第27行:使用设定的命令来启动应用程序
简单吧。
让我们像之前一样编译并使用Docker容器:
我们可以看到服务正常启动,也就是意味着它正确的启动了!我们完成了!
让我们使用docker images,来看看镜像的大小:
如我们之前所说,镜像的大小变为10MB以下。而且镜像被推送到镜像仓库后,它有2MB。当你启动容器时,只需下载2MB即可,相比于之前节省了大量的时间和带宽呢。
使用prod阶段编译的容器仅2MB
但是,它在我们的例子中不起作用。 如果运行curl localhost:8080,你看到的返回的结果为500。
如果你查看容器的日志,你可以找到如下错误:发生了一个错误:Get http://google.com:X509:加载系统根目录失败并且没有根目录可以使用。我们尝试使用https来连接Goole服务器,但是我们没有用于验证Google的SSL证书的CA(证书颁发机构)证书或是其他网站的CA证书。如果你的应用不需要使用SSL的话,可以选择跳到下一节,否则,让我们来改善我们的软件使得其可以进行访问。
阶段3 - (可选)认证阶段
-
第23行:我们新的certs阶段,使用alpine镜像
-
第25行:安装最新版的CA证书
-
第33行:从certs层拷贝证书,并保存为/etc/ssl/certs/ca-certificates.crt
让我们再次编译并使用Docker容器:
现在,curl localhost:8080将会返回真实页面!它真的奏效了!
使用docker images查看,镜像依然还是非常小的:
额外福利:在指定的阶段为镜像添加tag
有时候我们可能会在各个阶段为镜像创建一个tag,在我们的示例中,我们可能也会将build阶段产生的结果发布到Docker,因为它对开发真的十分有用。
要想这样做的话,只需要在build镜像的时候简单的使用--target=NAMEOFTHESTAGE。
举个例子:
总结
现在你已经能够为你的Golang应用程序创建一个非常轻量级的应用程序。阶段构建的概念对其他许多案例也是非常有用的。
我在NodeJS世界中的一个用法是第一阶段编译TypeScript项目。然后第一个阶段编译以便使得该镜像可以运行测试。此镜像也能够用于开发环境,因为它包含了所有开发环境所需的依赖。
当第一阶段测试通过后,第二阶段只是简单的安装项目中的package.json中的依赖(并不是测试环境依赖)。它只将编译和缩小的代码复制到镜像中,然后将该镜像推送并部署到生产中。
相关链接:
-
https://github.com/scboffspring/blog-multistage-go
原文链接:https://blog.zysset.me/lightweight-docker-go-images/
本站总结
以上是本站教程为你收集整理的如何为你的Go应用创建轻量级Docker镜像?全部内容,希望文章能够帮你解决如何为你的Go应用创建轻量级Docker镜像?所遇到的程序开发问题。
如果觉得本站教程网站内容还不错,欢迎将本站教程推荐给好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。