前言

Docker 1.13 在 2017 年 1 月 18 日发布了。从 2016 年 7 月 29 日发布 1.12 发布以来,已经过去 5 个多月了,对于活跃的 Docker 社区来说,已经很久了,让我们看看都 1.13 都新增了什么内容吧。

1.13 有一千四百多个 issue/pull request,五千多个 commits,是 Docker 历史上最高的发布版本。这并不是一个简单的小版本变化,里面有大量的更新。

在发布之后,可以直接安装最新版本。在一个新的 Ubuntu / CentOS 系统中直接执行:

1
curl - fsSL https : //get.docker.com/ | sh -s -- --mirror AzureChinaCloud

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 源的问题

让我们来详细解读一下 1.13.0 新增功能 吧。

Docker 镜像构建

从已有镜像取得缓存

https://github.com/docker/docker/pull/26839

我们都知道使用 Dockerfile 构建镜像的时候,会充分利用分层存储的特性进行缓存,之前构建过的层,如果没有变化,那么会直接使用缓存的内容,避免没有意义的重复构建。不过使用缓存的前提条件是曾经在本地构建过这个镜像。这在 CI 进行集群构建时是一个比较麻烦的问题,因为构建任务可能会被分配到不同的机器上,而该机器没有构建过该镜像,因此缓存总是用不上,因此大量的时间浪费在了重复构建已经构建过的层上了。

在 1.13 中,为 docker build 增加了一个新的参数 --cache-from,利用镜像中的 History 来判断该层是否和之前的镜像一致,从而避免重复构建。

比如我们先下载获取作为缓存的镜像:

1
2
3
4
5
6
7
8
9
10
11
12
13

$ 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 中的该层做缓存。

1
2
3
4
5
6
7
8
9
10
11
12
13
14

$ 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
-- - & gt ; 73e72bf822ca
Step 2 / 18 : RUN groupadd - r mongodb & amp ; & amp ; useradd - r - g mongodb mongodb
-- - & gt ; Using cache
-- - & gt ; 0f6297900a5e
Step 3 / 18 : RUN apt - get update    & amp ; & amp ; apt - get install - y -- no - install - recommends       numactl      & amp ; & amp ; rm - rf / var / lib / apt / lists / *
-- - & gt ; Using cache
-- - & gt ; a465f2e906fc
Step 4 / 18 : ENV GOSU _VERSION 1.7
-- - & gt ; Using cache
-- - & gt ; d448ddca2126
. . .

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

https://github.com/docker/docker/pull/22641

对于总是把 Dockerfile 当做 bash 文件来用的人,会发现很快由于太多的 RUN 导致镜像有特别多的层,镜像超级臃肿,而且甚至会碰到超出最大层数限制的问题。这些人往往不从自身找问题,反而去寻找旁门左道,比如导出镜像做一些特殊处理,合并为一层,然后再导入等等,这种做法是很错误的,除了导致构建缓存失败外,还导致docker history 丢失,导致镜像变为黑箱镜像。其实正确的做法是遵循 Dockerfile 最佳实践,应该把多个命令合并为一个 RUN,每一个 RUN 要精心设计,确保安装构建最后进行清理。这样才可以降低镜像体积,以及最大化的利用构建缓存。

在 Docker 1.13 中,为了应对这群用户,实验性的提供了一个 --squash 参数给 docker build,其功能就是如上所说,将 Dockerfile 中所有的操作,压缩为一层。不过,与旁门左道不同,它保留了 docker history

比如如下的 Dockerfile

1
2
3
4
5
6

FROM busybox
RUN echo hello & gt ; / hello
RUN echo world & gt ; & gt ; / hello
RUN touch remove_me / remove_me
ENV HELLO world
RUN rm / remove_me

如果我们正常的构建的话,比如 docker build -t my-not-squash .,其 history 是这样子的:

1
2
3
4
5
6
7
8
9

$ docker history my - not - squash
IMAGE               CREATED               CREATED BY                                       SIZE                 COMMENT
305297a526e2          About a minute ago    / bin / sh - c rm / remove _me                          0 B
60b8e896d443          About a minute ago    / bin / sh - c #(nop)  ENV HELLO=world              0 B
a21f3c75b6b0         About a minute ago    / bin / sh - c touch remove_me / remove _me            0 B
038bca5b58cb          About a minute ago    / bin / sh - c echo world & gt ; & gt ; / hello                  12 B
f81b1006f556         About a minute ago    / bin / sh - c echo hello & gt ; / hello                    6 B
e02e811dd08f          5 weeks ago            / bin / sh - c #(nop)  CMD ["sh"]                   0 B
& lt ; missing & gt ;            5 weeks ago            / bin / sh - c #(nop) ADD file:ced3aa7577c8f97...   1.09 MB

而如果我们用 --squash 构建:

1
docker build - t mysquash -- squash .

其 history 则是这样子:

1
2
3
4
5
6
7
8
9
10

$ docker history mysquash
IMAGE               CREATED             CREATED BY                                       SIZE                 COMMENT
a557e397ff56          15 seconds ago                                                        12 B                  merge sha256 : 305297a526e218e77f1b4b273442f8ac6283e2907e6513ff36e9048aa130dea6 to sha256 : e02e811dd08fd49e7f6032625495118e63f597eb150403d02e3238af1df240ba
& lt ; missing & gt ;            15 seconds ago        / bin / sh - c rm / remove _me                          0 B
& lt ; missing & gt ;            15 seconds ago        / bin / sh - c #(nop)  ENV HELLO=world              0 B
& lt ; missing & gt ;            15 seconds ago        / bin / sh - c touch remove_me / remove _me            0 B
& lt ; missing & gt ;            16 seconds ago        / bin / sh - c echo world & gt ; & gt ; / hello                  0 B
& lt ; missing & gt ;            16 seconds ago        / bin / sh - c echo hello & gt ; / hello                    0 B
& lt ; missing & gt ;            5 weeks ago          / bin / sh - c #(nop)  CMD ["sh"]                   0 B
& lt ; missing & gt ;            5 weeks ago          / bin / sh - c #(nop) ADD file:ced3aa7577c8f97...   1.09 MB

我们可以注意到,所有层的层ID都 <missing> 了,并且多了一层 merge

要注意,这并不是解决懒惰的办法,撰写 Dockerfile 的时候,依旧需要遵循最佳实践,不要试图用这种办法去压缩镜像。

构建镜像时支持用 --network 指定网络

https://github.com/docker/docker/pull/27702 https://github.com/docker/docker/issues/10324

在一些网络环境中,我们可能需要定制 /etc/hosts 文件来提供特定的主机和 IP 地址映射关系,无论是应对 GFW,还是公司内部 Git 服务器,都有可能有这种需求,这个时候构建时修改 /etc/hosts 是一个比较麻烦的事情。使用内部 DNS 虽然是一种解决办法,但是这将是全引擎范围的,而且并非所有环境都会有内部 DNS。更好地做法是使用宿主网络进行构建。另外,有的时候,或许这个构建所需 Git 服务器位于容器内网络,我们需要指定某个 overlay 网络来给镜像构建所需。

在 1.13 中,为 docker build 提供了 --network 参数,可以指定构建时的网络。

比如,我们有一个 Dockerfile 内容为:

1
2

FROM ubuntu
RUN cat / etc / hosts

内容很简单,就是看看构建时的 /etc/hosts 的内容是什么。假设我们宿主的 /etc/hosts 中包含了一条 1.2.3.4 到example.com 的映射关系。

1
1.2.3.4    example . com

如果我们如同以往,使用默认网络进行构建。那么结果会是这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

$ docker build -- no - cache - t build - network .
Sending build context to Docker daemon 2.048 kB
Step 1 / 2 : FROM ubuntu
-- - & gt ; 104bec311bcd
Step 2 / 2 : RUN cat / etc / hosts
-- - & gt ; Running in 42f0c014500f
127.0.0.1    localhost
:: 1 localhost ip6 - localhost ip6 - loopback
fe00 :: 0 ip6 - localnet
ff00 :: 0 ip6 - mcastprefix
ff02 :: 1 ip6 - allnodes
ff02 :: 2 ip6 - allrouters
172.17.0.2    2866979c4d77
-- - & gt ; 5f0b3dd56a32
Removing intermediate container 42f0c014500f
Successfully built 5f0b3dd56a32

可以注意到,这次构建所看到的是容器默认网络的 /etc/hosts,其内没有宿主上添加的条目 1.2.3.4 example.com

然后我们使用 docker build --network=host 来使用宿主网络构建:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

$ docker build -- no - cache - t build - network -- network = host .
Sending build context to Docker daemon 2.048 kB
Step 1 / 2 : FROM ubuntu
-- - & gt ; 104bec311bcd
Step 2 / 2 : RUN cat / etc / hosts
-- - & gt ; Running in b990c4e55424
# Your system has configured 'manage_etc_hosts' as True.
# As a result, if you wish for changes to this file to persist
# then you will need to either
# a.) make changes to the master file in /etc/cloud/templates/hosts.tmpl
# b.) change or remove the value of 'manage_etc_hosts' in
#     /etc/cloud/cloud.cfg or cloud-config from user-data
#
127.0.1.1 d1 . localdomain d1
127.0.0.1 localhost
# The following lines are desirable for IPv6 capable hosts
:: 1 ip6 - localhost ip6 - loopback
fe00 :: 0 ip6 - localnet
ff00 :: 0 ip6 - mcastprefix
ff02 :: 1 ip6 - allnodes
ff02 :: 2 ip6 - allrouters
ff02 :: 3 ip6 - allhosts
1.2.3.4    example . com
-- - & gt ; 63ef6cb93316
Removing intermediate container b990c4e55424
Successfully built 63ef6cb93316

这次由于使用了 --network=host 参数,于是使用的是宿主的网络命名空间,因此 /etc/hosts 也是宿主的内容。我们可以在其中看到 1.2.3.4 example.com 条目。

开始允许 docker build 中定义 Dockerfile 未使用的参数(ARG)

https://github.com/docker/docker/pull/27412

我们都知道镜像构建时可以用 --build-arg 来定义参数,这样 Dockerfile 就会使用这个参数的值来进行构建。这对于 CI/CD 系统很重要,我们可以使用一套 Dockerfile 来构建不同条件下的镜像。

但在 1.13 以前,这里有个问题,在 CI 系统中,我们有时希望用一套构建命令、脚本,通过给入不同的 Dockerfile来构建不同的镜像,而 --build-arg 的目的是定义一些有可能会用到的全局变量,但是如果有的 Dockerfile 中没用这个变量,那么构建就会失败。#26249

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

$ cat Dockerfile
FROM ubuntu
RUN env
$ docker build - t myapp -- build - arg VERSION = 1.2.3 -- no - cache .
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM ubuntu
-- - & gt ; 104bec311bcd
Step 2 : RUN env
-- - & gt ; Running in 81f4ba452a49
HOSTNAME = 2866979c4d77
HOME = / root
PATH = / usr / local / sbin : / usr / local / bin : / usr / sbin : / usr / bin : / sbin : / bin
PWD = /
-- - & gt ; f78b4696a1ca
Removing intermediate container 81f4ba452a49
One or more build - args [ VERSION ] were not consumed , failing build .

其背后的思想是,如果 --build-arg 指定了,但是没用,那么很可能是因为拼写错误、或者忘记了应该使用这个变量而出现的问题。最初 docker build 对于这类情况的处理,是直接报错退出,构建失败。

但是在上面的 CI 的案例中,--build-arg 只是定义一些可能用到的环境变量,并不强制使用,这种情况下,如果因为Dockerfile没有使用可能用到的变量就报错就有些过了。因此在 1.13 中,将其降为警告,并不终止构建,只是提醒用户有些变量未使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14

$ docker build -- no - cache - t myapp -- build - arg VERSION = 1.2.3 .
Sending build context to Docker daemon 2.048 kB
Step 1 / 2 : FROM ubuntu
-- - & gt ; 104bec311bcd
Step 2 / 2 : RUN env
-- - & gt ; Running in bb5e605cb4d0
HOSTNAME = 2866979c4d77
HOME = / root
PATH = / usr / local / sbin : / usr / local / bin : / usr / sbin : / usr / bin : / sbin : / bin
PWD = /
-- - & gt ; 97207d784048
Removing intermediate container bb5e605cb4d0
[ Warning ] One or more build - args [ VERSION ] were not consumed
Successfully built 97207d784048

安装

解决 GFW 影响 Docker 安装问题

https://github.com/docker/docker/pull/27005

官方的 apt/yum 源使用的是 AWS 的服务,并且为了确保安全使用了 HTTPS,因此伟大的墙很乐于干扰大家使用。没办法的情况下,各个云服务商纷纷建立自己官方源镜像,阿里云、DaoCloud、Azura 等等,并且自己做了个修订版的https://get.docker.com 的脚本来进行安装。

现在这个发生改变了,官方的 https://get.docker.com 将支持 --mirror 参数,你可以用这个参数指定国内镜像源,目前支持微软的 Azure 云,(或阿里云?(更新:由于阿里云镜像源不支持 HTTPS,所以不会支持阿里云))。使用方法如下,将原来官网安装命令:

1
curl - sSL https : //get.docker.com/ | sh

替换为:

1
curl - sSL https : //get.docker.com/ | sh -s -- --mirror AzureChinaCloud

增加更多的系统支持

在这次发布中,增加了 Ubuntu 16.10 的安装包,而且对 Ubuntu 系统增加了 PPC64LE 和 s390x 构架的安装包。此外,还正式支持了 VMWare Photon OS 系统的 RPM 安装包,以及在 https://get.docker.com 的支持。并且支持了Fedora 25,甚至开始支持 arm64。同时也由于一些系统生命周期的结束,而被移除支持,比如Ubuntu 15.10Fedora 22都不在支持了。

网络

允许 docker run 连入指定的 swarm mode 的网络

https://github.com/docker/docker/pull/25962

在 Docker 1.12 发布新的 Swarm Mode 之后,很多人都问过这样的问题,怎么才能让 docker run 的容器连入 Swarm Mode 服务的 overlay 网络中去?答案是不可以,因为 swarm 的 overlay网络是为了 swarm mode service 准备的,相对更健壮,而直接使用 docker run,会破坏了这里面的安全模型。

但是由于大家需求很多,于是提供了一种折衷的办法。1.13 允许建立网络的时候,设定该网络为 attachable,允许之后的 docker run 的容器连接到该网络上。

我们创建一个默认的、不允许之后 attach 的网络:

1
2

$ docker network create - d overlay mynet1
xmgoco2vfrtp0ggc5r0p5z4mg

然后再创建一个允许 attach 的网络,这里会使用 1.13 新加入的 --attachable 参数:

1
2

$ docker network create - d overlay -- attachable mynet2
yvcyhoc6ni0436jux9azc4cjt

然后我们启动一个 web 服务,连入这两个网络:

1
2
3
4
5
6

$ docker service create \
     -- name web \
     -- network mynet1 \
     -- network mynet2 \
     nginx
vv91wd7166y80lbl833rugl2z

现在我们用 docker run 启动一个容器连入第一个网络:

1
2

$ 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 使用:

1
2

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

https://github.com/docker/docker/pull/27917 https://github.com/docker/docker/pull/28943

docker service create 中的 --publish 格式有进一步的变化。(在 1.13 的 RC 期间,曾经去掉 --publish,改为--port,经过讨论后,决定保持一致性,继续使用 --publish,不使用新的 --port 选项。)

在 1.12 中,docker service create 允许使用参数 --publish 80:80 这类形式映射边界(ingress)网络的端口,这样的映射会享受边界负载均衡,以及 routing mesh。

从 1.13 开始,增加另一种映射模式,被称为 host 模式,也就是说,用这种模式映射的端口,只会映射于容器所运行的主机上。这就和一代 Swarm 中一样了。虽然失去了边界负载均衡,但是确定了映射点,在有的时候这种情况是需要的。

现在 --publish 的新的参数形式和 --mount 差不多。参数值为 , 逗号分隔的键值对,键值间以 = 等号分隔。目前支持 4 项内容:

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

比如,与 -p 8080:80 等效的 --publish 新格式选项为:

1
-- publish protocol = tcp , mode = ingress , published = 8080 , target = 80

当然我们可以继续使用 -p 8080:80,但是新的选项格式增加了更多的可能。比如,使用 1.13 开始加入的 host 映射模式:

1
2
3

ubuntu @ d1 : ~ $ docker service create -- name web \
     -- publish mode = host , published = 80 , target = 80 \
     nginx

运行成功后,查看一下服务容器运行的节点:

1
2
3
4
5
6
7
8

ubuntu @ d1 : ~ $ docker node ls
ID                           HOSTNAME   STATUS   AVAILABILITY   MANAGER STATUS
ntjybj51u6zp44akeawuf3i05     d2         Ready   Active
tp7icvjzvxla2n18j3nztgjz6     d3         Ready   Active
vyf3mgcj3uonrnh5xxquasp38 *    d1         Ready   Active         Leader
ubuntu @ d1 : ~ $ docker service ps web
ID             NAME     IMAGE         NODE   DESIRED STATE   CURRENT STATE           ERROR   PORTS
5tij5sjvfpsf    web . 1    nginx : latest   d3     Running         Running 5 minutes ago         * : 80 - & gt ; 80 / tcp

我们可以看到,集群有3个节点,而服务就一个副本,跑到了 d3上。如果这是以前的使用边界负载均衡的网络 ingress的话,那么我们访问任意节点的 80 端口都会看到页面。

但是,host 模式不同,它只映射容器所在宿主的端口。因此,如果我们 curl d1 的话,应该什么看不到网页,而curl d3 的话就会看到页面:

1
2

root @ d1 : ~ $ curl localhost
curl : ( 7 ) Failed to connect to localhost port 80 : Connection refused

1
2
3
4
5
6

root @ d3 : ~ $ curl localhost
& lt ; ! DOCTYPE html & gt ;
& lt ; html & gt ;
& lt ; head & gt ;
& lt ; title & gt ; Welcome to nginx ! & lt ; / title & gt ;
. . .

iptables 的转发规则将默认拒绝

https://github.com/docker/docker/pull/28257

从默认 FORWARD 改为 DROP,从而避免容器外露的安全问题。

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

我们都是知道,在 swarm mode 中创建的 overlay 网络,并不是一下子就在集群中的每个节点上 docker network ls就可以看到这个网络,这完全没有必要。只有当使用该网络的容器调度到某个节点上后,才会将该节点连入此 overlay网络。在网络排障过程中,经常会有这种需求,需要得知现在连入该 overlay 网络中的节点到底有哪些,这在 1.13之前不容易做到。

从 1.13 开始,docker network inspect 将显示连接到了这个网络的节点(宿主)有哪些。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

$ docker network inspect mynet
[
   {
       "Name" : "mynet" ,
       "Id" : "jjpnbdh8vu4onjojskntd2jhh" ,
       "Created" : "2017-01-18T00:00:31.742146058Z" ,
       "Scope" : "swarm" ,
       "Driver" : "overlay" ,
       "EnableIPv6" : false ,
       "IPAM" : {
           "Driver" : "default" ,
           "Options" : null ,
           "Config" : [
               {
                   "Subnet" : "10.0.0.0/24" ,
                   "Gateway" : "10.0.0.1"
               }
           ]
       } ,
       "Internal" : false ,
       "Attachable" : false ,
       "Containers" : {
           "3cafea27c53de34724e46d4fe83c9e60311b628b82e9be66d8d2e0812669d575" : {
               "Name" : "myapp.2.qz2hs1eqq3ikx59ydh0w7u1g4" ,
               "EndpointID" : "0e26b08254e851b7b238215cec07acdd8b0b68dc4671f55235e203a0c260522f" ,
               "MacAddress" : "02:42:0a:00:00:04" ,
               "IPv4Address" : "10.0.0.4/24" ,
               "IPv6Address" : ""
           }
       } ,
       "Options" : {
           "com.docker.network.driver.overlay.vxlanid_list" : "4097"
       } ,
       "Labels" : { } ,
       "Peers" : [
           {
               "Name" : "d1-23348b84b134" ,
               "IP" : "138.197.213.116"
           } ,
           {
               "Name" : "d2-8964dea9e75c" ,
               "IP" : "138.197.221.47"
           }
       ]
   }
]

从上面的例子可以看出,一共有两个宿主连入了这个 mynet 的 overlay 网络,分别为 138.197.213.116 和138.197.221.47

允许 service VIP 可以被 ping

https://github.com/docker/docker/pull/28019

在 1.12 的二代 Swarm 排障过程中,常见的一个问题就是跨节点的服务 VIP 不可以 ping,所以很多时候很多时候搞不懂是 overlay 网络不通呢?还是服务没起来?还是服务发现有问题?这个问题在 1.13 解决了,VIP 可以随便ping,跨宿主也没关系。

插件

插件功能正式启用

https://github.com/docker/docker/pull/28226

在 1.12 引入了插件概念后,作为试验特性得到了很多关注。包括 Docker Store 开始准备上线,以及第三方的插件的开发。现在 1.13 插件作为正式功能提供了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

$ 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 命令,可以指定一个包含有 config.json 文件和 rootfs 目录的目录来创建插件。

1
2
3
4
5
6
7
8
9
10
11

$ ls - ls / home / pluginDir
4 - rw - r -- r --    1 root root 431 Nov    7 01 : 40 config . json
0 drwxr - xr - x 19 root root 420 Nov    7 01 : 40 rootfs
$ docker plugin create plugin / home / pluginDir
plugin
$ docker plugin ls
ID                   NAME                 TAG                 DESCRIPTION                   ENABLED
672d8144ec02          plugin               latest                A sample plugin for Docker   false

命令行

checkpoint 功能(试验功能)

https://github.com/docker/docker/pull/22049

checkpoint 功能可以将运行中的容器状态冻结并保存为文件,并在将来可以从文件加载恢复此时的运行状态。

准备工作

目前它所依赖的是 criu 这个工具,因此在 Linux 上需要先安装这个工具。(目前尚无法在 Docker for Mac 中使用docker/for-mac#1059)

如果未安装 criu 则会出现如下报错:

1
Error response from daemon : Cannot checkpoint container myapp1 : rpc error : code = 2 desc = exit status 1 : "Unable to execute CRIU command: criu\n"

对于 Ubuntu 系统,可以执行下面的命令安装 criu

1
$ sudo apt - get install - y criu

由于这个是试验功能,因此需要在 docker.service 中 ExecStart= 这行后面添加 --experimental 选项。其它试验功能也需如此配置。

然后不要忘了 systemctl daemon-reload 和 systemctl restart docker

创建 Checkpoint 及恢复

执行 docker checkpoint create 就可以为容器创建 checkpoint

1
2

$ docker checkpoint create myapp1 checkpoint1
checkpoint1

可以为一个容器创建多个 checkpoint,每个起不同的名字就是了。

然后可以用 docker checkpoint ls 来列出已经创建的 checkpoint

1
2
3

$ docker checkpoint ls myapp1
CHECKPOINT NAME
checkpoint1

如果不加 --leave-running 参数的话,容器就会在创建完 checkpoint 就会被停止运行。

然后我们可以通过 docker start --checkpoint 来从某个 checkpoint 恢复运行:

1
$ docker start -- checkpoint checkpoint1 myapp1

容器就会从 checkpoint1 这个点恢复并继续运行。

备份时可以用 --checkpoint-dir 指定具体的保存 checkpoint 的目录:

1
2

$ docker checkpoint create -- checkpoint - dir $ PWD / backup -- leave - running myapp1 checkpoint1
checkpoint1

然后我们可以在 backup 中看到实际保存的文件内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

$ tree backup /
backup /
└── checkpoint1
   ├── cgroup . img
   ├── config . json
   ├── core - 1.img
   ├── core - 54.img
   ├── criu . work
   │   ├── dump . log
   │   └── stats - dump
   ├── descriptors . json
   ├── fdinfo - 2.img
   ├── fdinfo - 3.img
   ├── fs - 1.img
   ├── fs - 54.img
   ├── ids - 1.img
   ├── ids - 54.img
   ├── inventory . img
   ├── ip6tables - 9.img
   ├── ipcns - var - 10.img
   ├── iptables - 9.img
   ├── mm - 1.img
   ├── mm - 54.img
   ├── mountpoints - 12.img
   ├── pagemap - 1.img
   ├── pagemap - 54.img
   ├── pages - 1.img
   ├── pages - 2.img
   ├── pipes - data . img
   ├── pipes . img
   ├── pstree . img
   ├── reg - files . img
   ├── seccomp . img
   ├── sigacts - 1.img
   ├── sigacts - 54.img
   ├── tmpfs - dev - 46.tar.gz.img
   ├── tmpfs - dev - 49.tar.gz.img
   ├── tmpfs - dev - 50.tar.gz.img
   ├── unixsk . img
   └── utsns - 11.img

docker stats 终于可以显示容器名了

https://github.com/docker/docker/pull/27797 https://github.com/docker/docker/pull/24987

docker stats 可以显示容器的资源占用情况,用来分析不同容器的开销很有帮助。不过一直以来有个很讨厌的问题,docker stats 不显示容器名:

1
2
3
4

$ docker stats
CONTAINER           CPU %                MEM USAGE / LIMIT       MEM %                NET I / O              BLOCK I / O            PIDS
e8cb2945b156          0.00 %                1.434 MiB / 488.4 MiB    0.29 %                1.3 kB / 648 B        12.3 kB / 0 B        2
61aada055db8          0.00 %                3.598 MiB / 488.4 MiB    0.74 %                1.3 kB / 1.3 kB      2.29 MB / 0 B        2

这让人根本没办法知道到底谁是谁。于是有各种变通的办法,比如:

1
$ docker stats $ ( docker ps -- format = { { . Names } } )

但是这个列表是静态的,容器增加、删除都得重新运行这个命令。

从 1.13 开始,虽然依旧默认没有容器名,但是增加了 --format 参数可以自己设计输出格式:

1
2
3
4

$ docker stats -- format 'table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}\t{{.NetIO}}\t{{.BlockIO}}\t{{.PIDs}}'
NAME                               CPU %                MEM USAGE / LIMIT       MEM %                NET I / O              BLOCK I / O            PIDS
app2 . 1.5tij5sjvfpsft2lctxh8m8trn    0.00 %                1.434 MiB / 488.4 MiB    0.29 %                1.3 kB / 648 B        12.3 kB / 0 B        2
app1 . 1.mjmb8b0f0w5sy2v41jth3v9s4    0.00 %                3.598 MiB / 488.4 MiB    0.74 %                1.3 kB / 1.3 kB      2.29 MB / 0 B        2

给 docker ps 增加 is-task 过滤器

https://github.com/docker/docker/pull/24411

开始使用 Swarm Mode 后,经常碰到的一个问题就是,docker ps所看到的这些容器到底哪些是服务容器?哪些是docker run 跑起来的单独的容器?

从 1.13 开始,增加了 is-task 过滤器,以区分普通容器和 Swarm Mode 的服务容器:

1
2
3

docker ps - f 'is-task=true'
CONTAINER ID         IMAGE                                                                           COMMAND                   CREATED             STATUS               PORTS               NAMES
cdf0d35db1d3         nginx @ sha256 : 33ff28a2763feccc1e1071a97960b7fef714d6e17e2d0ff573b74825d0049303    "nginx -g 'daemon ..."    44 seconds ago       Up 44 seconds        80 / tcp , 443 / tcp     myservice . 1.6rdwhkb84j6ioyqlvk6h6bql8

再也不会出现客户端和服务端不同版本导致的错误了

https://github.com/docker/docker/pull/27745

在以前,docker 客户端和服务端必须版本一致,否则就会报 Client and server don't have the same version 这类错误。后来增加了 DOCKER_API_VERSION 环境变量,在客户端高于服务端版本时,可以通过这个环境变量指定服务端 API 版本,从而避免这类错误。

从 1.13 开始,将进行一些版本判断来进行处理,从而不会因为版本不一致而报错了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

$ docker version
Client :
Version :        1.13.0 - dev
API version :    1.24 ( downgraded from 1.25 )
Go version :    go1 . 7.3
Git commit :    ec3a34b
Built :          Wed Oct 26 00 : 54 : 51 2016
OS / Arch :        linux / amd64
Server :
Version :        1.12.2
API version :    1.24
Go version :    go1 . 6.3
Git commit :    bb80604
Built :          Tue Oct 11 17 : 00 : 50 2016
OS / Arch :        linux / amd64
Experimental : false

docker inspect 将可以查看任何 docker 对象

https://github.com/docker/docker/pull/23614

我们应该很熟悉 docker inspect,我们经常用它查看镜像、容器。从 1.13 开始,这将变的更高级,可以查看任何 Docker 对象。从网络、task、service、volume到之前的镜像、容器等等。

比如,我们用 docker service ps 列出了服务对应的 task 列表,得到 task id 后,我们可以直接 docker inspect 这个 task id

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

$ docker service ps myservice
ID             NAME         IMAGE         NODE   DESIRED STATE   CURRENT STATE           ERROR   PORTS
6rdwhkb84j6i    myservice . 1    nginx : latest    d1      Running          Running 13 minutes ago
$ docker inspect 6rdwhkb84j6i
[
     {
         "ID" : "6rdwhkb84j6ioyqlvk6h6bql8" ,
         "Version" : {
             "Index" : 17
         } ,
         "CreatedAt" : "2017-01-18T14:40:40.959516063Z" ,
         "UpdatedAt" : "2017-01-18T14:40:52.302378995Z" ,
         "Spec" : {
             "ContainerSpec" : {
                 "Image" : "nginx:latest@sha256:33ff28a2763feccc1e1071a97960b7fef714d6e17e2d0ff573b74825d0049303" ,
                 "DNSConfig" : { }
             } ,
             "Resources" : {
                 "Limits" : { } ,
                 "Reservations" : { }
             } ,
             "RestartPolicy" : {
                 "Condition" : "any" ,
                 "MaxAttempts" : 0
             } ,
             "Placement" : { } ,
             "ForceUpdate" : 0
         } ,
         "ServiceID" : "u7bidaojbndhrsgyj29unv4wg" ,
         "Slot" : 1 ,
         "NodeID" : "5s5nvnif1i4frentwidiu97mn" ,
         "Status" : {
             "Timestamp" : "2017-01-18T14:40:52.252715087Z" ,
             "State" : "running" ,
             "Message" : "started" ,
             "ContainerStatus" : {
                 "ContainerID" : "cdf0d35db1d37266af56b59dd8c3cd54de46442987e25e6fd25d38da1da7e459" ,
                 "PID" : 6563
             } ,
             "PortStatus" : { }
         } ,
         "DesiredState" : "running"
     }
]

运行时

不在分别构建试验可执行文件,直接使用 --experimental 参数

https://github.com/docker/docker/pull/27223

以前我们如果希望测试当前试验功能,必须添加试验分支源,重装 docker。这给测试试验分支带来了困难。现在变得简单了,不在分为两组可执行文件构建,合并为一个。如果需要测试试验功能,直接在 dockerd 后添加--experimental 即可。

在 overlay2 存储驱动使用于 xfs 时可以添加磁盘配额

https://github.com/docker/docker/pull/24771

在 1.13 之前,只有块设备文件系统驱动(如 devicemapperxfszfs等)支持磁盘配额能力,而所有 Union FS 的驱动,都不支持配额。现在针对使用 XFS 为后端的 overlay2 驱动支持了磁盘配额,理论上同样的方式可以在将来移植到 AUFS

增加 docker system 命令

https://github.com/docker/docker/pull/26108 https://github.com/docker/docker/pull/27525

很多人在以前搞不懂自己的镜像到底占了多少空间、容器占了多少空间,卷占了多少空间。怎么删除不用的东西以释放资源。从 1.13 开始,Docker 提供了一组 system 命令来帮助系统管理上的问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

$ docker system
Usage :    docker system COMMAND
Manage Docker
Options :
     -- help   Print usage
Commands :
df           Show docker disk usage
events       Get real time events from the server
info         Display system - wide information
prune       Remove unused data
Run 'docker system COMMAND --help' for more information on a command .

docker system df 是显示磁盘使用情况:

1
2
3
4
5

$ docker system df
TYPE                 TOTAL               ACTIVE               SIZE                 RECLAIMABLE
Images                3                    3                    700.3 MB              123 MB ( 17 % )
Containers            3                    3                    15 B                  0 B ( 0 % )
Local Volumes        1                    1                    219.4 MB              0 B ( 0 % )

显示的列表中列出了镜像、容器、本地卷所占用的磁盘空间,以及可能回收的磁盘空间。比如,我们看到镜像有 123MB 的空间可以回收,从 1.13 开始,docker 提供了一组 prune 命令,分别是:

  • docker image prune:删除无用的镜像
  • docker container prune:删除无用的容器
  • docker volume prune:删除无用的卷
  • docker network prune:删除无用的网络
  • docker system prune:删除无用的镜像、容器、卷、网络

还记得之前删除这些资源所用的 docker rmi $(docker images -f dangling=true -aq) 这种命令么?现在可以简单地 docker image prune 即可删除。

此外,从上面已经可以看到,从 1.13 开始,命令都开始归类于各个子命令了。之前默认的docker infodocker psdocker rmdocker run都开始归类于对应的 docker imagedocker container,docker system 下了。目前之前的命令依旧可以使用,会继续保持一段时间。但是从 1.13 开始,推荐使用各个子命令的版本了。

提升 overlay2 的优先级

https://github.com/docker/docker/pull/27932

由于 overlay2 在 4.+ 内核的系统上趋于稳定,因此将其优先级提到 devicemapper 之上(优先级最高的依旧是aufs

docker exec -t 自动添加 TERM 环境变量

https://github.com/docker/docker/pull/26461

对于在容器中使用 vihtop 之类工具的人来说是比较方便的。之前由于默认没有定义 TERM,这些需要终端页面布局的程序执行可能会不正常。比如:

1
2

$ htop
Error opening terminal : unknown .

现在直接为 docker exec -t 选项添加了继承自当前的 TERM 变量,可以让这类工具可以正常使用。

Windows 内置的运行 Windows 程序的 Docker on Windows 的改进

  • #28415:支持 Dockerfile 中的 USER 了;
  • #25736:支持 syslog 日志系统;
  • #28189:支持 fluentd 日志系统;
  • #28182:终于支持 overlay 网络了;
  • #22208:支持自定义网络指定静态IP了;
  • #23391:支持存储层驱动的磁盘配额;
  • #25737:终于可以用 docker stats 了;
  • #25891:终于可以用 docker top 了;
  • #27838:Windows 终于可以用 Swarm Mode 跑集群了;

Swarm Mode

正式支持 docker stack

1.12 中引入了二代 Swarm,也就是 Swarm Mode。由于基础理念变化很大,因此先行实现比较基本的服务(service),但是针对应用/服务栈(stack)没有成熟,只是试行使用 .DAB 文件进行集群部署。但是 DAB 是 JSON 文件,而且撰写较为复杂。相对大家已经习惯的 docker-compose.yml 却无法在 docker stack 中直接使用。只可以用docker-compose bundle 命令将 docker-compose.yml 转换为 .dab 文件,然后才能拿到集群部署,而且很多功能用不了。

从 1.13 开始,将允许直接使用 docker-compose.yml 文件来进行部署(#27998),大大方便了习惯了docker compose 的用户。不过需要注意的是,由于理念的演化,原有的 docker-compose.yml v2 格式无法使用,必须使用 v3 格式。

幸运的是 v3 和 v2 格式差距不大。

  • 将一些过时的东西去掉,如 volumes_from,需要共享数据用命名卷;
  • 去除 volume_driver,这种服务全局的东西没有必要,直接针对每个卷使用 volume 键下的 driver 即可;
  • 将 cpu_sharescpu_quotacpusetmem_limitmemswap_limit 移到 deploy 下的 resources 下进行管控,毕竟这是部署资源控制的部分。

具体差异可以看官方文档:https://github.com/docker/docker.github.io/blob/vnext-compose/compose/compose-file.md#upgrading

用我的 LNMP 的示例为例子,显然第一行的 version: '2' 需要换成 version: '3'

Docker 1.13版本新增功能说明相关推荐

  1. 虚幻引擎5.1版本新增功能

    虚幻引擎5.1版本新增功能 虚幻引擎5.1现已发布! 2022年11月15日 其他应用 功能 广播与实况活动 建筑 影视 模拟 汽车与运输 游戏 虚幻引擎5.1 虚拟制片 我们很高兴地宣布,虚幻引擎5 ...

  2. 华为运动健康服务Health Kit 6.10.0版本新增功能速览!

    华为运动健康服务(HUAWEI Health Kit)6.10.0 版本新增的能力有哪些? 阅读本文寻找答案,一起加入运动健康服务生态大家庭! 一. 支持三方应用查询用户测量的连续血糖数据 符合申请H ...

  3. python开发工具PyCharm最新版本新增功能介绍

    PyCharmV2022.1支持自定义包存储库的身份验证.改进的 TypedDict 和 Docker 的新服务UI. 点击获PyCharm官方正式版 改进IDE 支持自定义包存储库的身份验证 配置基 ...

  4. docker选择安装位置_如何使用docker 1.13版本更改centos 7中的docker安装目录

    我在下面附上了码头工人的详细信息, $docker info Containers: 3 Running: 3 Paused: 0 Stopped: 0 Images: 26 Server Versi ...

  5. C# 各版本新增功能

    https://www.cnblogs.com/SavionZhang/p/11229640.html 转载于:https://www.cnblogs.com/baiqian/p/11233126.h ...

  6. 燕千云 YQCloud 数智化业务服务管理平台 发布1.13版本

    2022年6月10日,燕千云 YQCloud 数智化业务服务管理平台发布1.13版本.本次燕千云1.13版本新增了远程桌面.知识库多人在线协作.移动端疫苗核酸信息管理.单据委托代理.技能管理.产品自助 ...

  7. ABP Framework 5.2 RC 版本发布及新增功能介绍

    本文将介绍 ABP Framework 5.2 RC 版新增的主要功能: •单层解决方案模板•API 版本控制•源代码控制移除libs文件夹•对 Swagger UI 隐藏 ABP 默认端点•CMS ...

  8. indesign2019怎么存低版本_新增功能和增强功能 | InDesign 2019 版

    2019 年 11 月版 (15.0) 的新增功能 2019 年 11 月版 InDesign 包含以下新增功能和增强功能: SVG 导入 现在,您可以在 InDesign 文档中导入并放置 SVG( ...

  9. 简易影视小程序v1.0.1版本新增过审功能

    简易影视小程序v1.0.1版本新增过审功能 v1.0.1版本更新日志 1.增加激励广告 2.增加插屏广告 3.增加视频贴片广告 4.增加原生广告 5.独立tk框架后台,简易操作 6.增加小程序过审核功 ...

最新文章

  1. [基础|理论|实验]linux下的文件读写
  2. git创建本地版本仓库及注意事项
  3. 面向对象——单例设计模式
  4. Vue指令篇_v-if、v-else、v-else-if
  5. 【BZOJ3512】DZY Loves Math IV(杜教筛)
  6. 2021年度公有云安全报告
  7. 精典排序,更新中。。。
  8. VS2019C++代码出现cout不明确
  9. javaScript = == ===的区别
  10. shell脚本中执行命令_如何在Shell脚本中执行命令?
  11. eclipse: workspace出错导致无法启用的解决
  12. UVALive 6198 A Terribly Grimm Problem 二分匹配 求字典序最小解
  13. O3DF执行董事Royal O’Brien:开源没有边界,所有共享的声音都会变成实际方向
  14. urp教务系统简单利用
  15. 实现抖音闪烁效果---OpenCV-Python开发指南(54)
  16. 知识图谱是什么,知识图谱有什么特点?
  17. Amazon EC2云计算体验
  18. 牛逼!java程序设计慕课版课后答案浪潮优派
  19. 单调队列————[USACO09MAR]向右看齐Look Up
  20. QuaggaJS在给定图像中定位条形码的工作原理

热门文章

  1. android app 加固后 重新签名
  2. 什么样的外贸词容易做推广?
  3. 结束该死的IT生涯,各位IT人士加油了
  4. CelebA-Spoof: Large-Scale Face Anti-Spoofing Dataset with Rich Annotations
  5. 【uiautomation】pc微信公众号点击
  6. 三星a70s升级android 10,三星Galaxy S8/Note 8确认无缘升级Android 10
  7. 手拍试卷的位置以及打印矫正
  8. websocket心跳检测
  9. 2022/07/17、18 day10/11:Stream流、方法引用
  10. Esxi 6.7.0版本导出虚拟机OVF网络错误问题解决办法【实测有用】