首页 > 代码库 > Docker 1.13 – 新增功能大揭秘

Docker 1.13 – 新增功能大揭秘

前言

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,这样会安装最新的测试版本。

  • Top 10 新增功能

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

  • 压扁(squash)镜像(实验阶段)

对于总是把 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 的时候,依旧需要遵循最佳实践,不要试图用这种办法去压缩镜像。

安装 

  • 解决 GFW 影响 Docker 安装问题

官方的 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 run 连入指定的 swarm mode 的网络

在 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 映射宿主端口,而不是边界负载均衡网络端口

首先,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 项内容:

  • protocol: 支持 tcp 或者 udp
  • mode: 支持 ingress 或者 host
  • target: 容器的端口号
  • published: 映射到宿主的端口号

比如,与 -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>

  • iptables 的转发规则将默认拒绝

从默认允许改为默认拒绝,从而避免容器外露的问题。

  • 在 docker network inspect 里显示连入节点

Show peer nodes in docker network inspect for swarm overlay networks #28078

  • 允许 service VIP 可以被 ping

在 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.

相比于 1.12 的试验版本而言,增加了 docker plugin create 命令,指定 rootfs 和 config.json 即可创建插件。

Docker 1.13 – 新增功能大揭秘