Docker 1.13 马上就要发布了。从 7 月 29 日发布 1.12 发布以来,已经过去 4 个多月了,对于活跃的 Docker 社区来说,已经很久了,让我们看看都 1.13 都新增了什么内容吧。
1.13 有一千二百多个 issue/pull request,四千多个 commits,是历史上最高的。这并不是一个简单的小版本变化,里面有大量的更新。
要想测试 1.13.0 的新功能,可以起一个新的机器,然后在里面运行:curl -fsSL https://test.docker.com/ | sh,这样会安装最新的测试版本。
1、正式支持服务栈 docker stack
2、正式支持插件:docker plugin
3、添加在 Swarm 集群环境下对密码、密钥管理的 secret 管理服务:docker secret
4、增加 docker system 命令
5、可以直接使用 docker-compose.yml 进行服务部署
6、添加 docker service 滚动升级出故障后回滚的功能
7、增加强制再发布选项 docker service update –force
8、允许 docker service create 映射宿主端口,而不是边界负载均衡网络端口
9、允许 docker run 连入指定的 swarm mode 的 overlay 网络
10、解决中国 GFW 墙掉 docker-engine apt/yum 源的问题
Docker 镜像构建
我们都知道使用 Dockerfile 构建镜像的时候,会充分利用分层存储的特性进行缓存,之前构建过的层,如果没有变化,那么会直接使用缓存的内容,避免没有意义的重复构建。不过使用缓存的前提条件是曾经在本地构建过这个镜像。这在 CI 进行集群构建时是一个比较麻烦的问题,因为构建任务可能会被分配到不同的机器上,而该机器没有构建过该镜像,因此缓存总是用不上,因此大量的时间浪费在了重复构建已经构建过的层上了。
在 1.13 中,为 docker build 增加了一个新的参数 –cache-from,利用镜像中的 History 来判断该层是否和之前的镜像一致,从而避免重复构建。
比如我们先下载获取作为缓存的镜像:
$ docker pull mongo:3.2
3.2: Pulling from library/mongo
386a066cd84a: Pull complete
524267bc200a: Pull complete
476d61c7c43a: Pull complete
0750d0e28b90: Pull complete
4bedd83d0855: Pull complete
b3b5d21a0eda: Pull complete
7354b6c26240: Pull complete
db792d386b51: Pull complete
a867bd77950c: Pull complete
Digest: sha256:532a19da83ee0e4e2a2ec6bc4212fc4af26357c040675d5c2629a4e4c4563cef
Status: Downloaded newer image for mongo:3.2
然后我们使用更新后的 Dockerfile 构建镜像时,如果加上 –cache-from mongo:3.2 后,会发现如果是已经在 mongo:3.2 中存在并没有修改的层,就会用 mongo:3.2 中的该层做缓存。
$ docker build –cache-from mongo:3.2 -t mongo:3.2.1 .
Sending build context to Docker daemon 4.608 kB
Step 1/18 : FROM debian:jessie
—> 73e72bf822ca
Step 2/18 : RUN groupadd -r mongodb && useradd -r -g mongodb mongodb
—> Using cache
—> 0f6297900a5e
Step 3/18 : RUN apt-get update && apt-get install -y –no-install-recommends numactl && rm -rf /var/lib/apt/lists/*
—> Using cache
—> a465f2e906fc
Step 4/18 : ENV GOSU_VERSION 1.7
—> Using cache
—> d448ddca2126
…
对于总是把 Dockerfile 当做 bash 文件来用的人,会发现很快由于太多的 RUN 导致镜像有特别多的层,镜像超级臃肿,而且甚至会碰到超出最大层数限制的问题。这些人往往不从自身找问题,反而去寻找旁门左道,比如导出镜像做一些特殊处理,合并为一层,然后再导入等等,这种做法是很错误的,除了导致构建缓存失败外,还导致 docker history 丢失,导致镜像变为黑箱镜像。其实正确的做法是遵循 Dockerfile 最佳实践,应该把多个命令合并为一个 RUN,每一个 RUN 要精心设计,确保安装构建最后进行清理。这样才可以降低镜像体积,以及最大化的利用构建缓存。
在 Docker 1.13 中,为了应对这群用户,实验性的提供了一个 –squash 参数给 docker build,其功能就是如上所说,将 Dockerfile 中所有的操作,压缩为一层。不过,与旁门左道不同,它保留了 docker history。
比如如下的 Dockerfile:
FROM busybox
RUN echo hello > /hello
RUN echo world >> /hello
RUN touch remove_me /remove_me
ENV HELLO world
RUN rm /remove_me
如果我们正常的构建的话,比如 docker build -t my-not-squash .,其 history 是这样子的:
而如果我们用 –squash 构建:
docker build -t mysquash –squash .
其 history 则是这样子:
我们可以注意到,所有层的层ID都 <missing> 了,并且多了一层 merge。
要注意,这并不是解决懒惰的办法,撰写 Dockerfile 的时候,依旧需要遵循最佳实践,不要试图用这种办法去压缩镜像。
安装
官方的 apt/yum 源使用的是 AWS 的服务,并且为了确保安全使用了 HTTPS,因此伟大的墙很乐于干扰大家使用。没办法的情况下,各个云服务商纷纷建立自己官方源镜像,阿里云、DaoCloud、Azura 等等,并且自己做了个修订版的 https://get.docker.com 的脚本来进行安装。
现在这个发生改变了,官方的 https://get.docker.com 将支持 –mirror 参数,你可以用这个参数指定国内镜像源,目前支持微软的 Azure 云,(或阿里云?)。使用方法如下,将原来官网安装命令:
curl -sSL https://get.docker.com/ | sh
替换为:
curl -sSL https://get.docker.com/ | sh -s — –mirror AzureChinaCloud
如果是阿里云的话,将 AzureChinaCloud 替换为 Aliyun。
此时,https://get.docker.com/ 尚未更新,所以暂时无法使用,在 1.13 正式发布后,即可使用。
在这次发布中,增加了 Ubuntu 16.10 的安装包,而且对 Ubuntu 系统增加了 PPC64LE 和 s390x 构架的安装包。此外,还正式支持了 VMWare Photon OS 系统的 RPM 安装包,以及在 https://get.docker.com 的支持。并且支持了 Fedora 25。同时也由于一些系统生命周期的结束,而被移除支持,比如 Ubuntu 15.10、Fedora 22 都不在支持了。
网络
在 Docker 1.12 发布新的 Swarm Mode 之后,很多人都问过这样的问题,怎么才能让 docker run 连入服务的 overlay 网络中去?答案是不可以,因为 swarm 的 overaly 是为了 swarm service 准备的,相对更健壮,而直接使用 docker run,会破坏了这里面的安全模型。
但是由于大家需求很多,于是提供了一种折衷的办法。1.13 允许建立网络的时候,设定该网络为 attachable,允许之后的 docker run 的容器连接到该网络上。
我们创建一个不允许之后 attach 的网络:
$ docker network create -d overlay mynet1
xmgoco2vfrtp0ggc5r0p5z4mg
然后再创建一个允许 attach 的网络,这里会使用 1.13 新加入的 –attachable 参数:
$ docker network create -d overlay –attachable mynet2
yvcyhoc6ni0436jux9azc4cjt
然后我们启动一个 web 服务,连入这两个网络:
$ docker service create
–name web
–network mynet1
–network mynet2
nginx
vv91wd7166y80lbl833rugl2z
现在我们用 docker run 启动一个容器连入第一个网络:
$ docker run -it –rm –network mynet1 busybox
docker: Error response from daemon: Could not attach to network mynet1: rpc error: code = 7 desc = network mynet1 not manually attachable.
由于 mynet1 不允许手动 attach 所以这里报错了。
在 1.12 的情况下,会报告该网络无法给 docker run 使用:
docker: Error response from daemon: swarm-scoped network (mynet1) is not compatible with `docker create` or `docker run`. This network can only be used by a docker service.
See ‘docker run –help’.
不过,–attachable 实际上是将网络的安全模型打开了一个缺口,因此这不是默认设置,而且并不推荐使用。用户在使用这个选项建立网络的时候,一定要知道自己在做什么。
首先,docker service create 中的 –publish 将改为 –port(缩写还是 -p 不变)。之所以这么做,是因为对映射开放端口有了更进一步的发展,原来的 –publish 1234:1234 的格式已无法满足需求。
在 1.12 中,docker service create 允许使用参数 –publish 80:80 这类形式映射边界(ingress)网络的端口,这样的映射会享受边界负载均衡,以及 routing mesh。
从 1.13 开始,增加另一种映射模式,被称为 host 模式,也就是说,用这种模式映射的端口,只会映射于容器所运行的主机上。这就和一代 Swarm 中一样了。虽然失去了边界负载均衡,但是确定了映射点,有的时候更方便管理。
现在新的 –port 的参数形式和 –mount 差不多。参数值为 , 逗号分隔的键值对,键值间以 = 等号分隔。目前支持 4 项内容:
比如,与 -p 8080:80 等效的 –port 选项为:
–port protocol=tcp,mode=ingress,published=8080,target=80
当然我们可以继续使用 -p 8080:80,但是新的选项格式增加了更多的可能。比如,使用 1.13 开始加入的 host 映射模式:
ubuntu@d1:~$ docker service create –name web
–port mode=host,published=80,target=80
nginx
运行成功后,查看一下服务容器运行的节点:
我们可以看到,集群有3个节点,而服务就一个副本,跑到了 d3 上。如果这是以前的使用边界负载均衡的网络 ingress 的话,那么我们访问任意节点的 80 端口都会看到页面。
但是,host 模式不同,它只映射容器所在宿主的端口。因此,如果我们 curl d1 的话,应该什么看不到网页,而 curl d3 的话就会看到页面:
root@d1:~$ curl localhost
curl: (7) Failed to connect to localhost port 80: Connection refused
root@d3:~$ curl localhost
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
…
从默认允许改为默认拒绝,从而避免容器外露的问题。
Show peer nodes in docker network inspect for swarm overlay networks #28078
在 1.12 的二代 Swarm 排障过程中,常见的一个问题就是跨节点的服务 VIP 不可以 ping,所以很多时候很多时候搞不懂是 overlay 网络不通呢?还是服务没起来?还是服务发现有问题?这个问题在 1.13 解决了,VIP 可以随便 ping,跨宿主也没关系。
插件
在 1.12 引入了插件概念后,作为试验特性得到了很多关注。包括服务端的 Docker Store 开始准备上线,以及第三方的插件的开发。现在 1.13 插件作为正式功能提供了。
$ docker plugin
Usage: docker plugin COMMAND
Manage plugins
Options:
–help Print usage
Commands:
create Create a plugin from a rootfs and config
disable Disable a plugin
enable Enable a plugin
inspect Display detailed information on one or more plugins
install Install a plugin
ls List plugins
push Push a plugin to a registry
rm Remove one or more plugins
set Change settings for a plugin
Run ‘docker plugin COMMAND –help’ for more information on a command.