如何创建一个安全的Docker基础镜像


这里写图片描述

背景

我最初使用Docker的时候,每个人都在说它用起来有多简单方便,它内部的机制是有多么好,它为我们节省了多少时间。但是当我一使用它就发现,几乎所有镜像都是臃肿而且不安全的(没有使用包签名,盲目相信上游的镜像库以curl | sh的方式安装),而且也没有一个镜像能实现Docker的初衷:隔离,单进程,容易分发,简洁。

Docker镜像本来不是为了取代复杂的虚拟机而设计的,后者有完整的日志、监控、警报和资源管理模块。而Docker则倾向于利用内核的cgroupsnamespaces特性进行封装组合,这就好像:

在物理机器环境下,一旦内核完成了初始化,init进程就起来了。

这也是为什么当你在Dockerfile的CMD指令启动的进程PID是1,这是与Unix中的进程机制类似的。

现在请查看一下你的进程列表,使用top或者ps,你会看到init进程占用的也是这个PID,这是每个类Unix系统的核心进程,所有进程的父进程,一旦你理解这个概念:在类Unix系统上每个进程都是init进程的子进程,你会理解Docker容器里不应该有无关的修饰文件,它应该是刚好满足进程运行需要。

如何开始

现在的应用多数是大型复杂的系统,通常都需要很多依赖库,例如有调度,编译和很多其他相关工具类应用,它们的架构通常封装性良好,通过一层层的抽象和接口把底层细节隐藏了,从某种程度上说,这也算是一种容器,但是从系统架构视角看,我们需要一种比以往虚拟环境更简单的方案了。

以Java为例

从零开始,思考你要构建一个最通用的基础容器,想想你的应用本身,它运行需要什么?

可能性有很多,如果你要运行Java应用,它需要Java运行时;如果运行Rails应用,它需要Ruby解释器,对Python应用也一样。Go和其他一些编译型语言有些许不同,我以下会提到。

在Java例子中,下一步要想的是:JRE需要什么依赖才能运行?因为它是让应用能运行的最重要的组件,所以很自然的下一步就是要想清楚JRE运行依赖于什么。

而实际上JRE并没太多依赖,它本来就是作为操作系统的抽象层,使代码不依赖于宿主系统运行,因此安装好JRE就基本准备就绪了。

(实际上,对操作系统的独立性并不是理所当然的事,有非常多的系统特有API和专有的系统扩展,但是便于举例,我们把注意力放在简单的情况下)

在Linux上,JVM主要是调用系统的C语言库,Oracle的官方JRE,使用的是libc,也就是glibc,这意味着你要运行任何Java程序,都需要先装好glibc。另外你可能需要某种shell来管理环境,还有一个与外部通讯的接口,例如网络和资源的接口。

我们总结一下Java应用示例需要的最低配置是:

  • JRE,在例子中我们使用Oracle JRE
  • glibc,JRE的依赖
  • 一个基础环境(包含网络、内存、文件系统等资源管理工具)

走进Alpine Linux

Alpine Linux最近得到很多关注,主要是因为它打包了一系列的经过验签的可信任的依赖,并且还保持体积在2MB!而在本文发布时,其他的一些镜像分发版如下:

  • ubuntu:latest: 66MB (已经瘦身了非常多了,以前有些版本超过600MB)
  • debian:latest: 55MB (同上,一开始是200MB以上的)
  • arch:latest: 145MB
  • busybox:latest: 676KB (是的!KB,我稍后会讨论它)
  • alpine:latest: 2MB (2MB,包含一个包管理工具的Linux系统)

Busybox是最小的竞争者?

从上边的对比中你可以看到,在体积上唯一能打败Alpine Linux的是Busybox,所以现在几乎所有嵌入式系统都是使用它,它被应用在路由器,交换机,ATM,或者你的吐司机上。它作为一个最最基础的环境,但是又提供了足够容易维护的shell接口。

在网上有很多文章解释了为什么人们会选择Alpine Linux而不是Busybox,我在这总结一下:

  • 开放活跃的软件包仓库:Alpine Linux使用apk包管理工具,它集成在Docker镜像中,而Busybox你需要另外安装一个包管理器,例如opkg,更甚者,你需要寻找一个稳定的包仓库源(这几乎没有),Alpine的包仓库中提供了大量常用的依赖包,例如,如果你仍然需要在容器中编译NodeJS或Ruby之类的代码,你可以直接运行apk来添加nodejs和ruby,这在几秒内便可以完成。
  • 体积确实重要,但是当你在功能性,灵活性,易用性和1.5MB之间衡量,体积就不那么重要了,Alpine上添加的包使这些方面都大大增强了。
  • 广泛的支持:Docker公司已经聘请了Alpine Linux的作者来维护它,所有官方镜像,在以后都将基于Alpine Linux来构建。没有比这个更有说服力的理由去让你在自己的容器中使用它了吧。
  • 希云cSphere很早就意识到镜像越来越庞大的问题,因此在去年推出微镜像,也是引导大家如何更好地构建和理解镜像,镜像只是一种软件包格式而已。

构建一个Java环境基镜像

正如我刚解释的,Alpine Linux是一个构建自有镜像时不错的选择,因此,我们在此将使用它来构建简洁高效的Docker镜像,我们开始吧!

组合:Alpine + bash

每个Dockerfile第一个指令都是指定它的父级容器,通常是用于继承,在我们的例子中是alpine:latest:

<code class="language-sh hljs css has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-tag" style="color: rgb(0, 0, 0); box-sizing: border-box;">FROM</span> <span class="hljs-tag" style="color: rgb(0, 0, 0); box-sizing: border-box;">alpine</span><span class="hljs-pseudo" style="color: rgb(0, 0, 0); box-sizing: border-box;">:latest</span>
<span class="hljs-tag" style="color: rgb(0, 0, 0); box-sizing: border-box;">MAINTAINER</span> <span class="hljs-tag" style="color: rgb(0, 0, 0); box-sizing: border-box;">cSphere</span> <<span class="hljs-tag" style="color: rgb(0, 0, 0); box-sizing: border-box;">docker</span><span class="hljs-at_rule" style="box-sizing: border-box;">@<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">csphere.cn></span></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

我们同时声明了谁为这个镜像负责,这个信息对上传到Docker Hub的镜像是必要的。

就这样,你就有了往下操作的基础,接下来安装我们选好的shell,把下边的命令加上:

<code class="language-sh hljs livecodeserver has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">RUN apk <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">add</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">--no-cache --update-cache bash</span>
CMD [<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"/bin/bash"</span>]</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

最终的Dockerfile是这样:

<code class="language-sh hljs lasso has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">FROM alpine:latest
MAINTAINER cSphere <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;"><</span>docker@csphere<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">.</span><span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">cn</span><span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">></span>

RUN apk add <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">--</span>no<span class="hljs-attribute" style="box-sizing: border-box;">-cache</span> <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">--</span>update<span class="hljs-attribute" style="box-sizing: border-box;">-cache</span> bash
CMD <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">[</span><span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"/bin/bash"</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">]</span><span class="hljs-markup" style="box-sizing: border-box;"></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>

好了,现在我们构建容器:

<code class="language-sh hljs haml has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">$ docker build -t my-java-base-image .
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM alpine:latest
 -<span class="ruby" style="box-sizing: border-box;">--> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2314</span>ad3eeb9<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>
</span>Step 2 : MAINTAINER cSphere <docker@csphere.cn>
 -<span class="ruby" style="box-sizing: border-box;">--> <span class="hljs-constant" style="box-sizing: border-box;">Running</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">63433312</span>d77e
</span> -<span class="ruby" style="box-sizing: border-box;">--> bfe94713797a
</span>Removing intermediate container 63433312d77e
... 省略若干行
Step 4 : CMD /bin/bash
 -<span class="ruby" style="box-sizing: border-box;">--> <span class="hljs-constant" style="box-sizing: border-box;">Running</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> d2291684b797
</span> -<span class="ruby" style="box-sizing: border-box;">--> ecc443d68f27
</span>Removing intermediate container d2291684b797
Successfully built ecc443d68f27</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li></ul>

并且运行它:

<code class="language-sh hljs lasso has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">$ docker run <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">--</span>rm <span class="hljs-attribute" style="box-sizing: border-box;">-ti</span> my<span class="hljs-attribute" style="box-sizing: border-box;">-java</span><span class="hljs-attribute" style="box-sizing: border-box;">-base</span><span class="hljs-attribute" style="box-sizing: border-box;">-image</span>
bash<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">-</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4.3</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">#</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

成功了!我们有了一个运行着bash的Alpine Linux。

glibc and friends

前边提到,Oracle的JRE依赖于glibc,Alpine Linux上并没有glibc,它使用一个更小体积的替代版,叫musl libc。glibc发展了这么多年,几乎包含了所有C语言中需要的依赖包,显然这样会很不灵活,一个glibc库被编译进Alpine Linux,勉强能维持在5MB的体积,而它的替代者musl-libc是一个二进制文件,只有897KB,并且支持了所有Linux架构上的C依赖。

对Oracle的JRE,没有办法不把glibc加上,幸运的是,Andy Shinn已经做过了这些,他提供了一个预编译的glibc镜像给Alpine Linux,在Github上的alpine-pkg-glibc,最新版是2.23-r1。

这样把这相关依赖加到Dockerfile中:

<code class="language-sh hljs perl has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">ENV GLIBC_PKG_VERSION=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2.23</span>-r1

RUN apk add --<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">no</span>-cache --update-cache curl ca-certificates bash && \
  curl -Lo /etc/apk/<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">keys</span>/andyshinn.rsa.pub <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"https://github.com/andyshinn/alpine-pkg-glibc/releases/download/<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>/andyshinn.rsa.pub"</span> && \
  curl -Lo glibc-<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"https://github.com/andyshinn/alpine-pkg-glibc/releases/download/<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>/glibc-<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk"</span> && \
  curl -Lo glibc-bin-<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"https://github.com/andyshinn/alpine-pkg-glibc/releases/download/<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>/glibc-bin-<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk"</span> && \
  curl -Lo glibc-i18n-<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"https://github.com/andyshinn/alpine-pkg-glibc/releases/download/<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>/glibc-i18n-<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk"</span> && \
  apk add glibc-<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk glibc-bin-<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk glibc-i18n-<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk && \</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>

现在我们的Dockerfile看起来是这样:

<code class="language-sh hljs perl has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">FROM alpine:latest
MAINTAINER cSphere <docker<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">@csphere</span>.cn>

ENV GLIBC_PKG_VERSION=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2.23</span>-r1

RUN apk add --<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">no</span>-cache --update-cache curl ca-certificates bash && \
  curl -Lo /etc/apk/<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">keys</span>/andyshinn.rsa.pub <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"https://github.com/andyshinn/alpine-pkg-glibc/releases/download/<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>/andyshinn.rsa.pub"</span> && \
  curl -Lo glibc-<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"https://github.com/andyshinn/alpine-pkg-glibc/releases/download/<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>/glibc-<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk"</span> && \
  curl -Lo glibc-bin-<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"https://github.com/andyshinn/alpine-pkg-glibc/releases/download/<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>/glibc-bin-<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk"</span> && \
  curl -Lo glibc-i18n-<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"https://github.com/andyshinn/alpine-pkg-glibc/releases/download/<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>/glibc-i18n-<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk"</span> && \
  apk add glibc-<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk glibc-bin-<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk glibc-i18n-<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk

CMD [<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"/bin/bash"</span>]</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul>

我们一句句解释一下这些指令:

<code class="language-sh hljs fix has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-attribute" style="box-sizing: border-box;">ENV GLIBC_PKG_VERSION</span>=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">2.23-r1</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

我们通过变量指定GitHub上的glibc版本,所以每当一个新版本发布,都不需要更改URL,而直接更改这个变量即可。

<code class="language-sh hljs livecodeserver has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">RUN apk <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">add</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">--update-cache curl ca-certificates bash && \</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

这个指令会使用apk命令安装我们需要的包,包括curl和ca-certificates(以便使用TLS的页面),最后的bash是我们Dockerfile上个版本已经有的了。

<code class="language-sh hljs perl has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">  curl -Lo /etc/apk/<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">keys</span>/andyshinn.rsa.pub <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"https://github.com/andyshinn/alpine-pkg-glibc/releases/download/<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>/andyshinn.rsa.pub"</span> && \
  curl -Lo glibc-<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"https://github.com/andyshinn/alpine-pkg-glibc/releases/download/<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>/glibc-<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk"</span> && \
  curl -Lo glibc-bin-<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"https://github.com/andyshinn/alpine-pkg-glibc/releases/download/<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>/glibc-bin-<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk"</span> && \
  curl -Lo glibc-i18n-<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"https://github.com/andyshinn/alpine-pkg-glibc/releases/download/<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>/glibc-i18n-<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk"</span> && \</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>

这些命令会接着刚刚的RUN指令,它们会从GitHub下载相关公钥和依赖包。

<code class="language-sh hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">  apk <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">add</span> glibc-${GLIBC_PKG_VERSION}<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.apk</span> glibc-bin-${GLIBC_PKG_VERSION}<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.apk</span> glibc-i18n-${GLIBC_PKG_VERSION}<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.apk</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

所有包下载完成后,我们会用这一行命令安装全部,由于我们之前添加了公钥,所以它们的签名会被验证。

好了!我们现在有了一个能运行几乎全部依赖于glibc包的环境。

Java运行环境

一般来说,Oracle不提供软件仓库的形式让人们下载,但是人们总是会找到一些方法绕过它,你可以使用以下命令把JRE添加到Docker镜像中:

<code class="language-sh hljs tex has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">
ENV JAVA_VERSION_MAJOR=8 <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>    JAVA_VERSION_MINOR=73 <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>    JAVA_VERSION_BUILD=02 <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>    JAVA_PACKAGE=server-jre

WORKDIR /tmp

RUN curl -jksSLH "Cookie: oraclelicense=accept-securebackup-cookie" <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  "http://download.oracle.com/otn-pub/java/jdk/<span class="hljs-formula" style="box-sizing: border-box; font-style: italic; background-color: rgb(238, 238, 238);">$<span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">{</span>JAVA_VERSION_MAJOR<span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">}</span>u$</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">{</span>JAVA_VERSION_MINOR<span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">}</span>-b<span class="hljs-formula" style="box-sizing: border-box; font-style: italic; background-color: rgb(238, 238, 238);">$<span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">{</span>JAVA_VERSION_BUILD<span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">}</span>/$</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">{</span>JAVA_PACKAGE<span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">}</span>-<span class="hljs-formula" style="box-sizing: border-box; font-style: italic; background-color: rgb(238, 238, 238);">$<span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">{</span>JAVA_VERSION_MAJOR<span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">}</span>u$</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">{</span>JAVA_VERSION_MINOR<span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">}</span>-linux-x64.tar.gz" | gunzip -c - | tar -xf - <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  apk del curl ca-certificates <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  mv jdk1.<span class="hljs-formula" style="box-sizing: border-box; font-style: italic; background-color: rgb(238, 238, 238);">$<span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">{</span>JAVA_VERSION_MAJOR<span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">}</span>.0_$</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">{</span>JAVA_VERSION_MINOR<span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">}</span>/jre /jre <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  rm /jre/bin/jjs <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  rm /jre/bin/keytool <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  rm /jre/bin/orbd <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  rm /jre/bin/pack200 <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  rm /jre/bin/policytool <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  rm /jre/bin/rmid <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  rm /jre/bin/rmiregistry <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  rm /jre/bin/servertool <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  rm /jre/bin/tnameserv <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  rm /jre/bin/unpack200 <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  rm /jre/lib/ext/nashorn.jar <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  rm /jre/lib/jfr.jar <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  rm -rf /jre/lib/jfr <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  rm -rf /jre/lib/oblique-fonts <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  rm -rf /tmp/* /var/cache/apk/* <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  echo 'hosts: files mdns4_minimal <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">[</span>NOTFOUND=return<span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">]</span> dns mdns4' >> /etc/nsswitch.conf

ENV JAVA_HOME /jre
ENV PATH <span class="hljs-formula" style="box-sizing: border-box; font-style: italic; background-color: rgb(238, 238, 238);">$<span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">{</span>PATH<span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">}</span>:$</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">{</span>JAVA_HOME<span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">}</span>/bin</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li></ul>

这堆命令究竟做了什么,我们还是一句句来看一下吧:

<code class="language-sh hljs autohotkey has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">ENV JAV<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">A_VERSION</span>_MAJOR=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span> \
    JAV<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">A_VERSION</span>_MINOR=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">73</span> \
    JAV<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">A_VERSION</span>_BUILD=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">02</span> 
    JAV<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">A_PACKAGE</span>=server-jre

WORKDIR /tmp</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>

这句非常简单,它定义了我们要从Oracle服务器上要下载的软件版本,本文编写时,上边的版本号是最新的,以后可能会变化,你可以从Oracle官网上查看。它同时也指定了WORKDIR工作目录,我们需要从一个临时目录开始运行,所以这里设置了/tmp。

<code class="language-sh hljs bash has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">RUN curl -jksSLH <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Cookie: oraclelicense=accept-securebackup-cookie"</span> \
  <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"http://download.oracle.com/otn-pub/java/jdk/<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${JAVA_VERSION_MAJOR}</span>u<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${JAVA_VERSION_MINOR}</span>-b<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${JAVA_VERSION_BUILD}</span>/<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${JAVA_PACKAGE}</span>-<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${JAVA_VERSION_MAJOR}</span>u<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${JAVA_VERSION_MINOR}</span>-linux-x64.tar.gz"</span> | gunzip -c - | tar -xf - && \</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

这句稍微有点复杂,它使用curl传了一个指定的头信息(“Cookie: oraclelicense=accept-securebackup-cookie”),以从Oracle上获取真正的下载包,这是必须的,不然会返回一个错误页。然后它会把下载好的包通过管道传给gunzip和tar ,换言之,它并不会保存下载回来的tar包,而是直接解压出来到磁盘上。

<code class="language-sh hljs python has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">apk <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">del</span> curl ca-certificates && \</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

这时curl和ca-certificates两个包都完成了它们的使命,可以删除了它们以节省空间。

<code class="language-sh hljs tex has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">  rm /jre/bin/jjs <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  rm /jre/bin/keytool <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  rm /jre/bin/orbd <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  rm /jre/bin/pack200 <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  rm /jre/bin/policytool <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  rm /jre/bin/rmid <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  rm /jre/bin/rmiregistry <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  rm /jre/bin/servertool <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  rm /jre/bin/tnameserv <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  rm /jre/bin/unpack200 <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  rm /jre/lib/ext/nashorn.jar <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  rm /jre/lib/jfr.jar <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  rm -rf /jre/lib/jfr <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  rm -rf /jre/lib/oblique-fonts <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> <span class="hljs-command" style="box-sizing: border-box; color: rgb(0, 0, 136);">\
</span>  rm -rf /tmp/* /var/cache/apk/* <span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span><span class="hljs-special" style="box-sizing: border-box; color: rgb(102, 102, 0);">&</span> \</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li></ul>

JRE自带了一些工具包,可能永远都不会用到的,我们也将它们删掉。 最后一行,会把全部临时文件和apk的包缓存也清理了。

<code class="language-sh hljs bash has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">echo</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4'</span> >> /etc/nsswitch.conf</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

这一行中,我们修改了nsswitch.conf,以确保网络正常,这会被glibc等包所用到。

最后,我们的Dockerfile会是下边这样:

<code class="language-sh hljs nginx has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">FROM</span> alpine:latest
MAINTAINER cSphere <docker<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">@csphere</span>.cn>

ENV JAVA_VERSION_MAJOR=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span> \
    JAVA_VERSION_MINOR=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">73</span> \
    JAVA_VERSION_BUILD=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">02</span> \
    JAVA_PACKAGE=server-jre \
    GLIBC_PKG_VERSION=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>.<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">23</span>-r1 \
    LANG=en_US.UTF8

WORKDIR /tmp

RUN apk add --<span class="hljs-built_in" style="color: rgb(155, 133, 157); box-sizing: border-box;">no</span>-cache --update-cache curl ca-certificates bash && \
  curl -Lo /etc/apk/keys/andyshinn.rsa.pub <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"https://github.com/andyshinn/alpine-pkg-glibc/releases/download/<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>/andyshinn.rsa.pub"</span> && \
  curl -Lo glibc-<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"https://github.com/andyshinn/alpine-pkg-glibc/releases/download/<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>/glibc-<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk"</span> && \
  curl -Lo glibc-bin-<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"https://github.com/andyshinn/alpine-pkg-glibc/releases/download/<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>/glibc-bin-<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk"</span> && \
  curl -Lo glibc-i18n-<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"https://github.com/andyshinn/alpine-pkg-glibc/releases/download/<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>/glibc-i18n-<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk"</span> && \
  apk add glibc-<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk glibc-bin-<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk glibc-i18n-<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${GLIBC_PKG_VERSION}</span>.apk && \
  curl -jksSLH <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Cookie: oraclelicense=accept-securebackup-cookie"</span> \
  <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"http://download.oracle.com/otn-pub/java/jdk/<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${JAVA_VERSION_MAJOR}</span>u<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${JAVA_VERSION_MINOR}</span>-b<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${JAVA_VERSION_BUILD}</span>/<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${JAVA_PACKAGE}</span>-<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${JAVA_VERSION_MAJOR}</span>u<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${JAVA_VERSION_MINOR}</span>-linux-x64.tar.gz"</span> | gunzip -c - | tar -xf - && \
  apk del curl ca-certificates && \
  mv jdk1.<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${JAVA_VERSION_MAJOR}</span>.0_<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${JAVA_VERSION_MINOR}</span>/jre /jre && \
  rm /jre/bin/jjs && \
  rm /jre/bin/keytool && \
  rm /jre/bin/orbd && \
  rm /jre/bin/pack200 && \
  rm /jre/bin/policytool && \
  rm /jre/bin/rmid && \
  rm /jre/bin/rmiregistry && \
  rm /jre/bin/servertool && \
  rm /jre/bin/tnameserv && \
  rm /jre/bin/unpack200 && \
  rm /jre/lib/ext/nashorn.jar && \
  rm /jre/lib/jfr.jar && \
  rm -rf /jre/lib/jfr && \
  rm -rf /jre/lib/oblique-fonts && \
  rm -rf /tmp/* /var/cache/apk/* && \
  echo <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4'</span> >> /etc/nsswitch.conf

ENV JAVA_HOME=/jre
ENV PATH=<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${PATH}</span>:<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">${JAVA_HOME}</span>/bin</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li></ul>

注意这里,我整合了两个ENV和RUN指令,因为最好是用更少的中间层,特别是这个容器是作为通用的构建单元。

简单来说,有一个规则:你需要更大的灵活性,那你需要更多的层;如果你需要减小体积和降低复杂度,你需要更少的层。这完全取决于你的需求。

在顶部我还加上了这句:

<code class="language-sh hljs fix has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-attribute" style="box-sizing: border-box;">ENV LANG</span>=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">en_US.UTF-8</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

这句是为了确保运行在这个系统环境的应用能指定语言。你可以根据需要设定这个LANG环境变量。

另外,JAVA_HOME和PATH也要设置好,以使用刚刚装好的JRE。

CMD指令会怎么运行?

我之前提到,我们这是在构建一个能提供给其他服务作为基础的镜像,它不需要带上CMD指令,因为它永远不会运行,但是一旦一个服务关联上它,就需要用到了。

不过你还是可以通过其他方式启动这个容器,例如docker rundocker exec指令:

<code class="language-sh hljs lasso has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">$ docker run <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">--</span>rm <span class="hljs-attribute" style="box-sizing: border-box;">-ti</span> my<span class="hljs-attribute" style="box-sizing: border-box;">-java</span><span class="hljs-attribute" style="box-sizing: border-box;">-base</span><span class="hljs-attribute" style="box-sizing: border-box;">-image</span> /bin/bash</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

构建最终镜像

最后,我们终于到了构建镜像这步了:

<code class="language-sh hljs haml has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">$ docker build -t my-java-base-image .
Sending build context to Docker daemon 60.42 kB
Step 1 : FROM alpine:latest
 -<span class="ruby" style="box-sizing: border-box;">--> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2314</span>ad3eeb9<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>
</span>Step 2 : MAINTAINER cSphere <docker@csphere.cn>
 -<span class="ruby" style="box-sizing: border-box;">--> <span class="hljs-constant" style="box-sizing: border-box;">Using</span> cache
</span> -<span class="ruby" style="box-sizing: border-box;">--> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">93</span>cc2bc0bd6<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>
</span>Step 3 : ENV JAVA_VERSION_MAJOR 8 JAVA_VERSION_MINOR 73 JAVA_VERSION_BUILD 02 JAVA_PACKAGE server-jre GLIBC_PKG_VERSION 2.23-r1 LANG en_US.UTF8
 -<span class="ruby" style="box-sizing: border-box;">--> <span class="hljs-constant" style="box-sizing: border-box;">Running</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>f0ffeaeca78
</span> -<span class="ruby" style="box-sizing: border-box;">--> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>dcfd34b0f1a
</span>Removing intermediate container 3f0ffeaeca78
... 省略若干行
Removing intermediate container 0a98b36a6e37
Step 7 : ENV PATH ${PATH}:${JAVA_HOME}/bin
 -<span class="ruby" style="box-sizing: border-box;">--> <span class="hljs-constant" style="box-sizing: border-box;">Running</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">54</span>d0dfb04f98
</span> -<span class="ruby" style="box-sizing: border-box;">--> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">493399</span>ac9ca6
</span>Removing intermediate container 54d0dfb04f98
Successfully built 493399ac9ca6</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li></ul>

哈哈!它执行成功了。我们运行容器里的java来验证一下吧:

<code class="language-sh hljs lasso has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">$ docker run <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">--</span>rm <span class="hljs-attribute" style="box-sizing: border-box;">-ti</span> my<span class="hljs-attribute" style="box-sizing: border-box;">-java</span><span class="hljs-attribute" style="box-sizing: border-box;">-base</span><span class="hljs-attribute" style="box-sizing: border-box;">-image</span> java <span class="hljs-attribute" style="box-sizing: border-box;">-version</span>
java version <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"1.8.0_73"</span>
Java(TM) SE Runtime Environment (build <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.8</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">.0</span>_73<span class="hljs-attribute" style="box-sizing: border-box;">-b02</span>)
Java HotSpot(TM) <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">64</span><span class="hljs-attribute" style="box-sizing: border-box;">-Bit</span> Server VM (build <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">25.73</span><span class="hljs-attribute" style="box-sizing: border-box;">-b02</span>, mixed mode)</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>

太好了,这正是我们要看到的结果,我们已经有了一个独立的Oracle JRE环境,以后我们只需要基于这个镜像来构建应用镜像即可:

<code class="language-sh hljs r has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">FROM my-java-base-image

[<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>]</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

最终镜像有多大?

我们来看看:

<code class="language-sh hljs lasso has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">$ docker images <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">|</span> grep my<span class="hljs-attribute" style="box-sizing: border-box;">-java</span><span class="hljs-attribute" style="box-sizing: border-box;">-base</span><span class="hljs-attribute" style="box-sizing: border-box;">-image</span> <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">|</span> awk <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'{print $7,$8}'</span>
<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">130.4</span> MB</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

说实话,这还是挺大的,但是毕竟里边装的是Java嘛~

总结

我们现在构建了一个安全、轻量的Docker镜像,基本上可以运行任何Java应用在上面,当然你也可以根据实际情况调整这个Dockerfile,但是主要的思想还是像上边说的那样,减小体积,使用安全的软件源。

一旦你明白Docker容器只是一个基础的单进程容器,只是一个应用运行的环境,它能让你专注于应用的构建而不是其他杂七杂八的依赖关系,你就会把Docker应用到得心应手。

以下是简单的几点指引:

  • 在每个容器中运行一个进程,如果你需要多个进程,那就构建多个容器,并且使用如docker-compose之类的工具去组合这些组件。
  • 从一个非常小的镜像开始构建。你不需要整个Debian或者Ubuntu镜像,特别是当你使用的是编译型语言(例如 C / C++ / Golang)。几乎所有的应用加上Alpine Linux就足够了。
  • 高效地使用层:添加更多的文件层会便于打标签和调试,但是这样会使镜像体积膨胀。你需要平衡这两点。
  • 安全性是非常重要的,确保从安全的仓库拉取镜像,从安全的安装源安装相关软件包。(Alpine Linux镜像从Docker官方或希云微镜像拉取,JRE从Oracle官方下载)
<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">docker login index<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.csphere</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.cn</span> <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"># 账号在 https://csphere.cn/hub 上获取</span>
docker pull index<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.cspehre</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.cn</span>/microimages/alpine:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3.3</span>
docker pull index<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.csphere</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.cn</span>/microimages/alpine-glibc:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3.3</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
创建一个Docker镜像可以通过以下步骤完成: 1. 编写Dockerfile:Dockerfile是一个文本文件,用于定义镜像的构建过程。在Dockerfile中,你可以指定基础镜像、安装软件、复制文件等操作。 2. 构建镜像:使用Docker命令行工具,通过执行`docker build`命令来构建镜像。该命令会根据Dockerfile的定义,自动执行构建过程。 3. 运行容器:构建完成后,你可以使用`docker run`命令来创建并运行一个容器,该容器是基于你所构建的镜像创建的。 下面是一个简单的示例Dockerfile,用于创建一个基于Ubuntu的镜像,并安装了Nginx服务器: ``` # 使用Ubuntu作为基础镜像 FROM ubuntu:latest # 更新软件包列表并安装Nginx RUN apt-get update && apt-get install -y nginx # 复制Nginx配置文件到容器中 COPY nginx.conf /etc/nginx/nginx.conf # 暴露80端口 EXPOSE 80 # 启动Nginx服务 CMD ["nginx", "-g", "daemon off;"] ``` 在上述示例中,首先指定了基础镜像为最新版的Ubuntu。然后通过`RUN`命令更新软件包列表并安装Nginx。接着使用`COPY`命令将本地的nginx.conf文件复制到容器中的/etc/nginx/nginx.conf路径下。最后使用`EXPOSE`命令暴露容器的80端口,并使用`CMD`命令启动Nginx服务。 你可以将上述Dockerfile保存为一个文件,然后在该文件所在的目录下执行以下命令来构建镜像: ``` docker build -t my-nginx-image . ``` 其中,`-t`参数用于指定镜像的名称和标签,`.`表示Dockerfile所在的当前目录。 构建完成后,你可以使用以下命令来运行容器: ``` docker run -d -p 8080:80 my-nginx-image ``` 其中,`-d`参数表示以后台模式运行容器,`-p`参数用于将容器的80端口映射到主机的8080端口。 希望以上信息对你有所帮助!如果你还有其他问题,请继续提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值