Docker 是PaaS供应商dotCloud开源的一个基于LXC 的高级容器引擎,源代码托管在 GitHub 上, 基于Go语言开发并遵从Apache 2.0协议开源。正如DockerPool在免费Docker电子书 Docker —— 从入门到实践 中这样提到的:
作为一种新兴的虚拟化方式,Docker 跟传统的虚拟化方式相比具有众多的优势。
首先,Docker 容器的启动可以在秒级实现,这相比传统的虚拟机方式要快得多。 其次,Docker 对系统资源的利用率很高,一台主机上可以同时运行数千个 Docker 容器。
容器除了运行其中应用外,基本不消耗额外的系统资源,使得应用的性能很高,同时系统的开销尽量小。传统虚拟机方式运行 10 个不同的应用就要起 10 个虚拟机,而Docker 只需要启动 10 个隔离的应用即可。
Docker让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app)。几乎没有性能开销,可以很容易地在机器和数据中心中运行。最重要的是,他们不依赖于任何语言、框架包括系统。
本文不会介绍Docker原理和操作,而是介绍如何使用Docker创建一个Golang应用程序的镜像,这样我们就可以在其它机器上运行这个镜像。本文参考了很多的文章,这些文章列在了本文的底部。
编写一个Golang服务器
这里我在研究 endless 库的时候写了一个测试程序,就用它来测试一下docker镜像的创建。
endless可以允许我们在重启网络服务器的时候零时间宕机, 英语是graceful restart,我称之为无缝重启。
服务器监听4242端口,顺便使用raymond模版引擎替换golang自带的模版引擎,采用bone这个高性能的mux库。
代码如下:
Golang镜像
Docker官方提供了Golang各版本的镜像: Official Repository - golang .
它包含了Golang的编译和运行时环境。最简单的使用方法就是在你的 Dockerfile
文件中加入
这个镜像包含了多个 ONBUILD
触发器。你可以编译和运行你的镜像:
为编译好的Golang应用创建小的镜像
上面的Golang容器相当的大,因为它包含了Golang的编译和运行环境。官方网站上列出了镜像的大小:
golang:1.5.1-onbuild
$ docker pull library/golang@sha256:f938465579d1cde302a447fef237a5a45d7e96609b97c83b9144446615ad9e72
Total Virtual Size: 709.5 MB (709470237 bytes)Total v2 Content-Length: 247.0 MB (246986021 bytes)
实际上我们并不需要那么多的软件,因为我们的Golang应用程序是预先编译好的,而不是在Golang容器中现场编译运行,因此我们不需要Golang的编译环境等。如果你查看golang:1.5的Dockerfile,会发现它基于buildpack-deps:jessie-scm,会安装GCC及一堆的build工具,下载Go的发布文件并安装。基本上这些对于我们来说并不需要。我们需要的是:
一个可以运行我们编译好的Golang应用的镜像。
我们可以从 scratch
镜像创建。
scratch
镜像是一个空的镜像文件,特别适合创建超级小的镜像。
Dockerfile
文件如下:
运行输出如下
这样镜像就创建成功了,查看一下:
只有8M左右,非常的小。
但是运行这个镜像,容器无法创建:
原因是我们的main文件生成的时候依赖的一些库如libc还是动态链接的,但是scratch 镜像完全是空的,什么东西也不包含,所以生成main时候要按照下面的方式生成,使生成的main静态链接所有的库:
然后重新生成镜像并运行:
容器运行成功,在浏览器中访问 http://宿主IP:4242/index成功返回结果
发布
可以方便的将刚才的镜像发布到docker.io上。首先将刚才的镜像打tag:
运行 docker login
登录,然后运行下面的命令push到docker.io上。
访问 https://hub.docker.com/r/smallnest/example-scratch/ 可以看到刚刚push的这个镜像,这样我们就可以pull到其它机器上运行了。