一、Docker容器概述
1、docker中的容器技术演进
lxc --> libcontainer --> runC
2、容器的遵循协议规范Open Container Initiative
Linux基金会于2015年6月成立OCI(Open Container Initiative)组织,旨在围绕容器格式和运行时制定一个开放的工业化标准。OCI规范包含两个规格运行规范(runtime-spec)和形象规范(image-spec);
OCI定义了容器运行时标准,runC是Docker按照开放容器格式标准(OCF, Open Container Format)制定的一种具体实现。
runC是从Docker的libcontainer中迁移而来的,实现了容器启停、资源隔离等功能。Docker默认提供了docker-runc实现,事实上,通过containerd的封装,可以在Docker Daemon启动的时候指定runc的实现。
3、 Docker应用
- Docker是一个开源的引擎,可以轻松的为任何应用创建一个轻量级的、可移植的、自给自足的容器。开发者在笔记本上编译测试通过的容器可以批量地在生产环境中部署,包括VMs(虚拟机)、bare metal、OpenStack 集群和其他的基础应用平台。
Docker通常用于如下场景:
web应用的自动化打包和发布;
自动化测试和持续集成、发布;
在服务型环境中部署和调整数据库或其他的后台应用;
从头编译或者扩展现有的OpenShift或Cloud Foundry平台来搭建自己的PaaS环境。
4、docker的核心组件
(1)、Docker daemon
- Docker 守护进程(dockerd)侦听请求和Docker的API,管理Docker核心对象,如镜像、容器、网络、和卷。
(2)、 Docker client
- Docker客户端,命令使用DockerAPI。
(3)、Docker registries
- Docker注册镜像库保存了Docker镜像。
- Docker公共镜像库和Docker云是公共注册中心,任何人都可以使用,配置后的Docker镜像都可以上传到注册镜像库。
- 你可以创建和运行自己的私有Docker镜像库。
5、docker的依赖基础环境
依赖的基础环境
- 处理器要求 64 bits CPU
- 内核要求 Linux Kernel 3.10+
- Linux Kernel cgroups and namespaces
- 发行版要求 CentOS 7
- docker使用的仓库必须有“Extras”仓库
6、docker的守护进程安装和启动
#查询是否有extras仓库
[root@node-65 ~]# yum repolist
Loaded plugins: fastestmirror
Repodata is over 2 weeks old. Install yum-cron? Or run: yum makecache fast
Determining fastest mirrors
* base: mirrors.aliyun.com
* extras: mirrors.tuna.tsinghua.edu.cn
* updates: mirrors.tuna.tsinghua.edu.cn
repo id repo name status
!base/7/x86_64 CentOS-7 - Base 10,019
!extras/7/x86_64 CentOS-7 - Extras 314
!updates/7/x86_64 CentOS-7 - Updates 598
repolist: 10,931
#安装docker
[root@node-65 ~]# yum install docker -y
#配置文件目录
[root@node-65 ~]# vim /etc/sysconfig/docker
#启动
[root@node-65 ~]# systemctl start docker.service
#默认docker监听在本机,不能远程
[root@node-65 ~]# ls /var/run/docker/libcontainerd/
containerd docker-containerd.pid docker-containerd.soc
7、docker容器的简单运行
#在公共库查询一个镜像
[root@node-65 ~]# docker search busybox
INDEX NAME DESCRIPTION STARS OFFICIAL AUTOMATED
docker.io docker.io/busybox Busybox base image. 1470 [OK]
docker.io docker.io/progrium/busybox 68 [OK]
docker.io docker.io/hypriot/rpi-busybox-httpd Raspberry Pi compatible Docker Image with ... 45
docker.io docker.io/radial/busyboxplus Full-chain, Internet enabled, busybox made... 21
下载一个镜像
[root@node-65 ~]# docker pull docker.io/busybox
Using default tag: latest
Trying to pull repository docker.io/library/busybox ...
latest: Pulling from docker.io/library/busybox
b4a6e23922dd: Pull complete
Digest: sha256:8ccbac733d19c0dd4d70b4f0c1e12245b5fa3ad24758a11035ee505c629c0796
Status: Downloaded newer image for docker.io/busybox:latest
查询本地镜像
[root@node-65 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/busybox latest 758ec7f3a1ee 15 hours ago 1.15 MB
启动容器方法
方法一,docker create
方法二,docker run
格式: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
--name string 容器名称
--rm 容器停止立即删除
-i 交互界面
--tty 容器启动自动添加一个终端
--network string 自动创建网络
docker安装后会自动生成一个网桥,并启动DHCP服务,为生成的容器服务,容器启动后会自动获取ip地址并连接此网桥。
[root@node-65 ~]# ifconfig
docker0: flags=4099 mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 0.0.0.0
ether 02:42:46:9a:3b:6d txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
使用下载镜像启动docker容器
[root@node-65 ~]# docker run --name bbox1 -it docker.io/busybox
/ #
/ # ifconfig #已经获取到IP地址
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:0.0.0.0 Mask:255.255.0.0
............
/ # exit #退出
查询运行的容器
[root@node-65 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f1984d2b64a2 docker.io/busybox "sh" 3 minutes ago Exited (0) 2 minutes ago bbox1
容器的删除
[root@node-65 ~]# docker rm bbox1或者ID号
查询docker版本
[root@node-65 ~]# docker version
Client: #客户端信息
Version: 1.13.1
API version: 1.26
Package version: docker-1.13.1-88.git07f3374.el7.centos.x86_64
Go version: go1.9.4
Git commit: 07f3374/1.13.1
Built: Fri Dec 7 16:13:51 2018
OS/Arch: linux/amd64
Server: #服务端信息
Version: 1.13.1
API version: 1.26 (minimum version 1.12)
Package version: docker-1.13.1-88.git07f3374.el7.centos.x86_64
Go version: go1.9.4
Git commit: 07f3374/1.13.1
Built: Fri Dec 7 16:13:51 2018
OS/Arch: linux/amd64
Experimental: false
查询docker信息
[root@node-65 ~]# docker info
二、Docker容器应用
1、Docker组件:
物理组件有:客户端Client <--> 守护进程Daemon <--> 镜像库Registry Server
逻辑组件有:Containers容器,Images镜像、映像,Registry镜像库
2、常用的容器的相关命令
doker官方操作文档:https://docs.docker.com/engine/reference/commandline/docker/
- 容器的运行状态
created:创建
runing:运行
paused:暂停
stopped:停止
deleted:删除
- docker容器命令
docker ps : 查询运行的容器
docker run:创建并运行一个容器;
docker create:创建一个容器;
docker start:启动一个处于停止状态容器;
docker kill : 停止容器进程
docker stop:停止容器
docker restart:重启重启
docker pause:暂停容器
docker unpause:继续运行容器
docker rm :删除容器
docker run --rm:运行结束后自动删除容器
- 查看docker相关的信息命令:
docker version :查看版本
docker info :查看信息
- 镜像相关命令:
docker images 查询
docker rm 删除镜像
docker pull 拉取镜像
3、容器命令应用:
- 创建容器是基于“镜像文件”,镜像文件中必须有默认要运行的程序,创建方法是联合挂载分层镜像;
注意:
- 运行的容器内部必须有一个工作前台的运行的进程;
- docker的容器的通常也是仅为运行一个程序;
- 要想在容器内运行多个程序,一般需要提供一个管控程序,例如supervised。
创建容器命令:
docker run
docker create
--name CT_NAME
--rm:容器运行终止即自行删除
--network BRIDGE:让容器加入的网络;
默认为docker0;
交互式启动一个容器:
-i:--interactive,交互式;
-t:Allocate a pseudo-TTY
从终端拆除容器:
ctrl+p, ctrl+q
附加至某运行状态的容器的终端设备;
docker attach
让运行中的容器运行一个额外的程序;
docker exec
查看容器内部程序运行时输出到终端的信息;
[root@node-65 ~]# docker logs bbox1
查看运行的容器
docker ps -a
-a, --all:列出所有容器;
--filter, -f:过滤器条件显示
name=XXXXXX
status={stopped|running|paused} #某种状态的容器
动态方式显示容器的资源占用状态:
[root@node-65 ~]# docker stats bbox1
CONTAINER CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
bbox1 -- -- / -- -- -- -- --
显示正在运行的流程的一个容器
[root@node-65 ~]# docker top bbox1
三、Docker的镜像
1、概述和命令
- Docker镜像(Image):可理解为一个面向Docker引擎的只读模板,包含了文件系统。如:一个镜像可以只包含一个完整的操作系统环境,也可以安装了其他的应用程序。通过版本管理和增量的文件系统,Docker提供了一套十分简单的机制来创建和更新现有的镜像。
- 可见的字段信息:来源于哪一个仓库、镜像的标签信息、镜像的ID(唯一标识了镜像)、创建的时间、镜像的大小。
获取镜像:
docker pull; 命令格式为:docker pull NAME[:TAG], TAG是版本号。默认是latest最新版本。
查看镜像信息:
docker images (查看本地主机上已有的镜像)
为本地镜像添加新的标签:
docker tag(镜像的指向一致,因为不同标签的镜像ID是完全一致的,只是别名不同)
获取镜像的详细信息:
docker inspect, 返回的是JSON格式的消息,可以使用-f参数指定其中的一项内容(docker inspect -f {{“要查看的内容”}}) 镜像ID,可以使用若干个字符组成的可区分字串来代替完整的ID。
搜索镜像:
docker search。可以搜索远端仓库中共享的镜像,默认搜索Docker Hub官方仓库中的镜像。用法为dockersearch TERM,包括的参数有镜像的名字、描述、星级(镜像受欢迎程度)、是否官方支持、是否自动创建。默认的输出结果将按照星级评价进行排序。
删除镜像:
docker rmi IMAGE[IMAGE...], 其中IMAGE可以为标签或ID。当同一个镜像拥有多个标签的时候,docker rmi命令只是删除了该镜像多个标签中的指定标签,并不影响镜像文件。但当镜像只剩下一个标签的时候,再使用docker rmi命令会彻底删除该镜像,会删除这个镜像文件的所有AUFS层。
2、Docker Hub使用:
-
使用docker最简单的方式莫过于从现有的容器镜像开始。Docker官方网站专门有一个页面来存储所有可用的镜像,网址是:http://index.docker.io/你可以通过浏览这个网页来查找你想要使用的镜像,或者使用命令行的工具来检索。
首先到Docker Hub官方网站https://hub.docker.com/注册用户
docker login登录docker hub
docker logout注销登出docker hub
[root@node-65 ~]# docker login -u 用户名
#显示docker hub上的镜像
[root@node-65 ~]# docker images
- docker push 上传到docker hub
#给指定的镜像添加标签
[root@node-65 ~]# docker tag docker.io/busybox;latest docker.io/用户名/bbox:v0.1.0
#上传镜像到docker hub
[root@node-65 ~]# docker push docker.io/用户名/bbox:v0.1.0
#显示docker hub上的镜像
[root@node-65 ~]# docker images
docker pull 下载docker hub上的镜像,如果是私有的需要登录才可下载,公共的不需要登录
[root@node-65 ~]# docker docker.io/用户名/bbox:v.0.1.0
#显示docker hub上的镜像
[root@node-65 ~]# docker images
四、docker的卷
Docker Data Volume
- Docker镜像由多个只读层叠加而成,启动容器时,Docker会加
载只读镜像层并在镜像栈顶部添加一个读写层 -
如果运行中的容器修改了现有的一个已经存在的文件,那该文
件将会从读写层下面的只读层复制到读写层,该文件的只读版
本仍然存在,只是已经被读写层中该文件的副本所隐藏,此即“写时复制(COW)”机制
- 关闭并重启容器,其数据不受影响;但删除Docker容器,则其更改将会全部丢失
1、 存在的问题
- 存储于联合文件系统中,不易于宿主机访问;
- 容器间数据共享不便
- 删除容器其数据会丢失
2、 解决方案:“卷(volume)”
-
“卷”是容器上的一个或多个“目录”,此类目录可绕过联合文件系统,与宿主机上的某目录“绑定(关联)”
3、挂载卷分类
(1)docker自行挂载卷
- 容器启动后,docker会自动在宿主机上生成对应目录,修改容器内部文件,只需修改宿主机上对应文件即可。
- 有卷管理的docker,容器关闭后,在宿主机自动生成的卷也会自动删除。
#启动一个容器,创建一个可读写目录
[root@node-65 ~]# docker run --name h1 --rm -v /data/html -it docker.io/busybox
/ # cd /data/html
/data/html # vi index.html #编辑
H1 Container
#回到宿主机上,docker会自动在宿主机上创建对应的卷
#列出当前所有的卷
[root@node-65 ]# docker volume list
DRIVER VOLUME NAME
local c927500bb873a851e37cb8af94663252ea039a296e296a1f586defa9da674944
#查看对应卷内容
[root@node-65 ~]# cat /var/lib/docker/volumes/c927500bb873a851e37cb8af94663252ea039a296e296a1f586defa9da674944/_data/index.html
H1 Container
#与容器内部的内容一致
#探测卷的信息
[root@node-65 ~]# docker inspect -f "{{.Mounts}}" h1
[{volume c927500bb873a851e37cb8af94663252ea039a296e296a1f586defa9da674944 /var/lib/docker/volumes/c927500bb873a851e37cb8af94663252ea039a296e296a1f586defa9da674944/_data /data/html local true }]
(2)用户指定的挂载卷
#在宿主机上创建卷
[root@node-65 ~]# mkdir /appdata/html -pv
mkdir: created directory ‘/appdata’
mkdir: created directory ‘/appdata/html’
#编辑内容
[root@node-65 ~]# vim /appdata/html/index.html
Test Page
~
#指定容器内部目录和宿主机对应的卷,并启动容器
[root@node-65 ~]# docker run --name h2 -d -it -v /appdata/html:/data/html docker.io/hehe/bbox:v0.1.1-httpd
#测试
[root@node-65 ~]# curl http://172.17.0.2
Test Page
4、删除卷
- 删除容器之时删除相关的卷
为docker rm命令使用-v选项 - 删除指定的卷
docker volume rm
[root@node-65 ~]# docker kill h2
h2
#删除容器时,-v 同时删除宿主机上的卷
[root@node-65 ~]# docker rm -v h2
h2
5、多个容器的卷使用同一个主机目录
-
例如
~]# docker run –it --name c1 -v /docker/volumes/v1:/data busybox
~]# docker run –it --name c2 -v /docker/volumes/v1:/data busybox
6、复制使用其它容器的卷
-
为docker run命令使用--volumes-from选项
~]# docker run -it --name bbox1 -v /docker/volumes/v1:/data busybox
~]# docker run -it --name bbox2 --volumes-from bbox1 busybox
五、Docker容器的网络
1、桥接Bridge类型
- lsolated:隔离桥接,仅容器间网络通信
- Host-only:仅主机桥接,宿主机和各个容器网络通信
- NAT:地址转换桥接,容器有内网地址,通过宿主机核心转发,与外网主机网络通信
-
Phy Bridged:物理桥接,使容器与物理网卡同一网络地址的,与外网网络通信
2、Docker网桥类型
Docker安装完成后,会自动创建三个网络,可使用“dockernetwork ls”命令查看
bridge 桥接式网络
host 开放式网络
none 封闭式网络
3、Docker网桥创建命令
- 创建容器时,可为docker run命令使用--net选项指定要加入的网络
(1) none 封闭式网络
~]# docker run --rm --net none busybox:latest ifconfig -a
(2) bridge 桥接式网络
- 桥接式容器一般拥有两个接口:一个环回接口和一个连接至主
机上某桥设备的以太网接口 - docker daemon启动时默认会创建一个名为docker0的网络桥,并且创建的容器为桥接式容器,其以太网接口桥接至docker0
- --net bridge即为将容器接口添加至docker0桥
- docker0桥为NAT桥,因此,桥接式容器可通过此桥接口访问外部网络,但防火墙规则阻止了一切从外部网络访问桥接式容器的请求
~]# docker run --rm --net bridge busybox:latest ifconfig -a
配合docker run命令使用网络选项
- “--hostname HOSTNAME”选项为容器指定主机名
- “--dns DNS_SERVER_IP”选项能够为容器指定所使用的dns服务
器地址 - “--add-host HOSTNAME:IP”选项能够为容器指定本地主机名解
析项
[root@node-65 ~]# docker run --name bbox1 --rm --net bridge -it --hostname bbox1.hehe.com --dns 192.167.1.1 --add-host www.hehe.com:192.167.0.1 busybox
/ # cat /etc/hosts #主机名称
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
192.167.0.1 www.hehe.com
172.17.0.2 bbox1.hehe.com
/ # cat /etc/resolv.conf #查询dns解析
nameserver 192.167.1.1
/ # hostname #查询主机名
bbox1.hehe.com
(3)联盟式桥接
- 联盟式容器是指使用某个已存在容器的网络接口的容器,接口被联盟内的各容器共享使用;因此,联盟式容器彼此间完全无隔离
- 例如
# 创建一个监听于2222端口的http服务容器
~]# docker run -d -it --rm -p 2222 busybox:latest /bin/httpd -p 2222 -f
# 创建一个联盟式容器,并查看其监听的端口
~]# docker run -it --rm --net container:web --name joined busybox:latest
netstat -tan
- 联盟式容器彼此间虽然共享同一个网络名称空间,但其它名称空间
如User、Mount等还是隔离的 - 联盟式容器彼此间存在端口冲突的可能性,因此,通常只会在多个容器上的程序需要程序loopback接口互相通信、或对某已存的容器的网络属性进行监控时才使用此种模式的网络模型
(4) host 开放式网络
- 开放式容器共享主机网络名称空间的容器,它们对主机的网络名称空间拥有全部的访问权限,包括访问那些关键性服务,这对宿主机安全性有很大潜在威胁
- 为docker run命令使用“--net host”选项即可创建开放式容器,
例如:
~]# docker run -it --rm --net host busybox:latest /bin/s
4、容器的端口暴露
- 将指定的容器端口映射至主机所有地址的一个动态端口
-p:
#将容器的80端口映射到宿主机的随机端口
[root@node-65 ~]# docker run --name h1 --rm --net bridge -d -p 80 docker.io/hehe/bbox:v0.1.1-httpd /bin/httpd -f -h /data/html
#查询映射到那个随机端口
[root@node-65 ~]# docker port h1
80/tcp -> 0.0.0.0:32769
#测试访问
[root@node-65 ~]# curl 192.168.1.65:32769
BUSY BOX SERVER
- 将容器端口
映射至指定的主机端口
-p::
#指明容器的80端口映射到宿主机的90端口
[root@node-65 ~]# docker run --name h1 --rm --net bridge -d -p 90:80 docker.io/hehe/bbox:v0.1.1-httpd /bin/httpd -f -h /data/html
#查询端口映射
[root@node-65 ~]# docker port h1
80/tcp -> 0.0.0.0:90
#测试
[root@node-65 ~]# curl 192.168.1.65:90
BUSY BOX SERVER
- 将指定的容器端口
映射至主机指定 的动态端口
-p: :
#指定容器80端口映射到宿主机的指定ip的随机端口
[root@node-65 ~]# docker run --name h1 --rm --net bridge -d -p 192.168.1.65::80 docker.io/hehe/bbox:v0.1.1-httpd /bin/httpd -f -h /data/html
#查询端口映射
[root@node-65 ~]# docker port h1
80/tcp -> 192.168.1.65:32768
#测试
[root@node-65 ~]# curl 192.168.1.65:32768
BUSY BOX SERVER
- 将指定的容器端口
映射至主机指定 的端口
#指定容器的80端口映射到宿主机的指定ip的90端口
[root@node-65 ~]# docker run --name h1 --rm --net bridge -d -p 192.168.1.65:90:80 docker.io/hehe/bbox:v0.1.1-httpd /bin/httpd -f -h /data/html
#查询映射端口
[root@node-65 ~]# docker port h1
80/tcp -> 192.168.1.65:90
#测试
[root@node-65 ~]# curl 192.168.1.65:90
BUSY BOX SERVER
多端口暴露一
[root@node-65 ~]# docker run --name h1 --rm --net bridge -d -p 192.168.1.65:90:80 -p 8090:8080 -p 10080:10080 docker.io/hehe/bbox:v0.1.1-httpd /bin/httpd -f -h /data/html
#查询映射端口
[root@node-65 ~]# docker port h1
10080/tcp -> 0.0.0.0:10080
80/tcp -> 192.168.1.65:90
8080/tcp -> 0.0.0.0:8090
多端口暴露二
- 使用“-P”选项或“--publish-all”将容器的所有计划要暴露端口全部映射至主机端口
- 计划要暴露的端口使用使用--expose选项指定
- 例如:
[root@node-65 ~]# docker run --name h3 --rm --net bridge -d -P --expose 2222 --expose 3333 docker.io/hehe/bbox:v0.1.1-httpd /bin/httpd -f -h /data/html
#查询映射端口
[root@node-65 ~]# docker port h3
2222/tcp -> 0.0.0.0:32772
3333/tcp -> 0.0.0.0:32771
- “动态端口”指随机端口,具体的映射结果可使用docker port命令查看
5、docker默认网络配置
- 如果不想使用默认的docker0桥接口,或者需要修改此桥接口
的网络属性,可通过为docker daemon命令使用-b、--bip、--
fixed-cidr、--default-gateway、--dns以及--mtu等选项进行设定
#修改默认启动容器的网络配置
[root@node-65 ~]# vim /etc/sysconfig/docker-network
# /etc/sysconfig/docker-network
DOCKER_NETWORK_OPTIONS="添加--b、--dns、--bip等选项"
6、自定义网桥
docker创建一个新网桥
[root@node-65 ~]# docker network create -d bridge --subnet=172.16.0.0/16 --ip-range=172.16.0.0/16 --gateway=172.16.0.254 mybr0
6f3b263dfd24f2184209a7884a44caf151c3ed934eed7200ed0d491ae1c8f214
#查询docker网络
[root@node-65 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
..........
6f3b263dfd24 mybr0 bridge local
...........
--subnet:指明子网
--driver:指明设备
--ip-range:容器加入时获取的地址范围
--gateway:指明网关
创建容器使用mybr0网桥
[root@node-65 ~]# docker run --name h2 --rm -it --net mybr0 -v /appdata/html:/data/html docker.io/hehe/bbox:v0.1.1-httpd
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:10:00:01
inet addr:172.16.0.1 Bcast:0.0.0.0 Mask:255.255.0.0 #以获取ip地址
给运行的容器添加网桥
[root@node-65 ~]# docker network connect bridge h2
#在容器内部查询网络
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:10:00:01
inet addr:172.16.0.1 Bcast:0.0.0.0 Mask:255.255.0.0 #连接指定的mybr0网桥
.........
eth1 Link encap:Ethernet HWaddr 02:42:AC:11:00:03
inet addr:172.17.0.3 Bcast:0.0.0.0 Mask:255.255.0.0 #多出来一个设备连接默认docker的网桥
.............
给运行的容器撤销网桥
[root@node-65 ~]# docker network disconnect bridge h2
#在容器内部查询网络
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:10:00:01
inet addr:172.16.0.1 Bcast:0.0.0.0 Mask:255.255.0.0 #只剩下一个网桥了
7、docker的叠加网络
$ docker network create -d overlay \
--subnet=192.168.1.0/25 \
--subnet=192.170.2.0/25 \
--gateway=192.168.1.100 \
--gateway=192.170.2.100 \
--aux-address="my-router=192.168.1.5" --aux-address="my-switch=192.168.1.6" \
--aux-address="my-printer=192.170.1.5" --aux-address="my-nas=192.170.1.6" \
my-multihost-network
--aux-address:辅助网络地址
参考链接:https://docs.docker.com/engine/reference/commandline/docker/
https://www.douban.com/note/527688389/
https://blog.csdn.net/qq_27211267/article/details/81160706