Docker引擎安装

基础准备

准备,1804 配置好ip和主机名

案例实施

1、基础环境配置
(1)配置YUM源
将提供的压缩包 Docker.tar.gz 上传至/root 目录并解压。

  1. [root@master ~]# tar -zxvf Docker.tar.gz

配置本地YUM源

[root@master ~]# cat /etc/yum.repos.d/local.repo 
[kubernetes]
name=kubernetes
baseurl=file:///root/Docker
gpgcheck=0
enabled=1

(2)升级系统内核

[root@master ~]# yum upgrade -y

(3)配置防火墙及SELinux
配置防火墙及SELinux,代码如下

[root@master ~]# systemctl stop firewalld && systemctl disable firewalld
[root@master ~]# iptables -t filter -F
[root@master ~]# iptables -t filter -X
[root@master ~]# sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
[root@master ~]# reboot

(4)开启路由转发

[root@master ~]# cat >>/etc/sysctl.conf<<EOF
> net.ipv4.ip_forward=1
> net.bridge.bridge-nf-call-ip6tables=1
> net.bridge.bridge-nf-call-iptables=1
> EOF
[root@master ~]# modprobe br_netfilter
[root@master ~]# sysctl -p
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1

2、Docker引擎安装
(1)安装依赖包

[root@master ~]# yum install -y yum-utils device-mapper-persistent-data

(2)安装docker-ce
此处安装指定版本的dockerCE

[root@master ~]# yum install -y docker-ce-18.09.6 docker-ce-cli-18.09.6 containerd.io

(3)启动docker
启动docker并设置开机自启动

[root@master ~]# systemctl daemon-reload
[root@master ~]# systemctl restart docker
[root@master ~]# systemctl enable docker

查看docker的系统信息

[root@master ~]# docker info

至此,Docker引擎的安装就完成了

Docker仓库的使用

基础准备

1084两台配好ip和主机名,两个节点都已经安装好docker-ce

案例实施

(1)运行Registry
将Registry镜像运行并生成一个容器

[root@master ~]# ./image.sh
[root@master ~]# docker run -d -v /opt/registry:/var/lib/registry -p 5000:5000 --restart=always --name registry registry:latest

(2)查看运行情况
使用docker ps命令查看容器运行情况

[root@master ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
350997f78a09        registry:latest     "/entrypoint.sh /etc…"   7 minutes ago       Up 7 minutes        0.0.0.0:5000->5000/tcp   registry

(3)查看状态
Registry容器启动后,打开浏览器输入地址http://10.30.59.221:5000/v2/查看是否运行正常
image.png
(4)上传镜像
创建好私有仓库之后,就可以使用 docker tag 命令来标记一个镜像,然后推送它到仓库。
先配置私有仓库

[root@master ~]# vi /etc/docker/daemon.json
{
 "insecure-registries":["10.30.59.221:5000"]
}
[root@master ~]# systemctl restart docker

使用docker tag命令将centos:latest这个镜像标记为10.30.59.221:5000/centos:latest

[root@master ~]# docker tag centos:latest 10.30.59.221:5000/centos:latest

使用docker push上传标记的镜像

[root@master ~]# docker push 10.30.59.221:5000/centos
[root@master ~]# curl -L 10.30.59.221:5000/v2/_catalog
{"repositories":["centos"]}
##也可以在浏览器中访问

(5)拉取镜像
登录slave节点,配置私有仓库地址

[root@slave ~]# vi /etc/docker/daemon.json
{
 "insecure-registries":["10.30.59.221:5000"]
}
[root@slave ~]# systemctl restart docker

拉取镜像并查看结果

[root@slave ~]# docker pull 10.30.59.221:5000/centos:latest
[root@slave ~]# docker images
REPOSITORY                 TAG                 IMAGE ID            CREATED             SIZE
10.30.59.221:5000/centos   latest              0f3e07c0138f        21 months ago       220MB

Docker镜像和容器的使用

基础准备

一台1804修改IP修改主机名 节点安装docker-ce

案例实施

1、镜像的基本管理和使用
(1)查看镜像列表
可以使用docker images命令来列出本地主机上的镜像。

docker images

(2)获取镜像
当本地主机上使用一个不存在的镜像时,Docker 会自动下载这个镜像。如果需要预先 下载这个镜像,可以使用 docker pull 命令来下载

docker pull

(3)查找镜像
查找镜像一般有两种方式,可以通过 Docker Hub(https://hub.docker.com/)网站来搜索 镜像,也可以使用 docker search 命令来搜索镜像

docker search [] TERM

(4)删除镜像
镜像删除使用 docker rmi 命令

docker rmi

2、容器的基本管理和使用
(1)运行容器
运行第一个容器,执行以下命令

[root@master ~]# docker run -it --rm -d -p 80:80 nginx:latest
e1f0c187209a6a4d9157b457519228dfca57190ffd23908165eb39ec4365fad8

参数说明:
 -i:交互式操作。
 -t:终端。
 -rm:容器退出后随之将其删除,可以避免浪费空间。
 -p:端口映射。
 -d:容器在后台运行。
启动容器的语法如下

docker start [ID]
启动所有的Docker容器
docker start $(docker ps -aq)

(2)操作容器
列出运行中的容器

docker ps
docker container ls

列出所有的容器 (包括终止状态)

docker ps -a

查看具体容器的信息

docker inspect [id or names]

查看容器的使用资源状况

docker stats [id or names]

查看容器日志

docker logs [OPTIONS] [id or names]
 OPTIONS 说明: 
--details:显示更多的信息。 
-f,--follow:跟踪实时日志。 
--sincestring:显示自某个 timestamp 之后的日志,或相对时间,如 42 分钟。 
--tailstring:从日志末尾显示多少行日志,默认是 all。 
-t,--timestamps:显示时间戳。 
--until string:显示自某个 timestamp 之前的日志,或相对时间,如 42 分钟。

进入容器

docker exec -it [id] bash

(3)终止容器

删除终止状态的容器
docker rm [CONTAINER ID]
删除所有处于终止状态的容器。
docker container prune
删除未被使用的数据卷。
docker volume prune
删除运行中的容器。
docker rm -f [CONTAINER ID]
批量停止所有的容器。
docker stop $(docker ps -aq)
批量删除所有的容器。
docker rm $(docker ps -aq)
终止容器进程,容器进入终止状态。
docker container stop [CONTAINER ID]

(4)导入/导出容器
将容器快照导出为本地文件

docker export [CONTAINER ID] > [tar file]

同样的,也可以把容器快照文件在导入为镜像

cat [tar file] | docker import - [name:tag]

使用 docker import 命令导入一个容器快照到本地镜像库时,将丢弃所有的历史记录和 元数据信息,即仅保存容器当时的快照状态。

3、构建自定义镜像
(1)docker commit
docker commit 命令用于从容器创建一个新的镜像

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
OPTIONS 说明:
 -a:提交的镜像作者。
 -c:使用 Dockerfile 指令来创建镜像。
 -m:提交时的说明文字。
 -p:在 commit 时,将容器暂停。

将容器e1f0c187209a保存为新的镜像,并添加提交人信息和说明信息。

[root@master ~]# docker commit -a "HXQ" -m "nginx_test" e1f0c187209a nginx:v1
sha256:b1c32c7d5dabad3495fd47cc3b3f877f6d5e7d1c7f2db14c4034270f4b550ca2

docker commit可用于被入侵后保存现场等操作
(2)dockerfile
Dockerfile 一般分为 4 部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时 执行指令,“#”为 Dockerfile 中的注释。

Dockerfile 主要指令如下:
 FROM:指定基础镜像,必须为第一个命令。
 MAINTAINER:维护者信息。
 RUN:构建镜像时执行的命令。
 ADD:将本地文件添加到容器中,tar 类型文件会自动解压(网络压缩资源不会被解
压),可以访问网络资源,类似 wget。
 COPY:功能类似 ADD,但是是不会自动解压文件,也不能访问网络资源。
 CMD:构建容器后调用,也就是在容器启动时才进行调用。
 ENTRYPOINT:配置容器,使其可执行化。配合 CMD 可省去“application”,只使
用参数。
 LABEL:用于为镜像添加元数据。
 ENV:设置环境变量。
 EXPOSE:指定与外界交互的端口。
 VOLUME:用于指定持久化目录。
 WORKDIR:工作目录,类似于 cd 命令。
 USER:指定运行容器时的用户名或 UID,后续的 RUN 也会使用指定用户。使用 USER
指定用户时,可以使用用户名、UID 或 GID,或是两者的组合。当服务不需要管理员权限
时,可通过该命令指定运行用户。
 ARG:用于指定传递给构建运行时的变量。
 ONBUILD:用于设置镜像触发器。

接下来以 centos:latest 为基础镜像,安装 jdk1.8 并构建新的镜像 centos-jdk。
新建文件夹用于存放 JDK 安装包和 Dockerfile 文件。

[root@master ~]# mkdir centos-jdk
[root@master ~]# mv jdk/jdk-8u141-linux-x64.tar.gz ./centos-jdk/
[root@master ~]# cd centos-jdk/

编写Dockerfile

[root@master centos-jdk]# vi Dockerfile
#centOS with JDK8
#Author HXQ
#指定基础镜像
FROM centos
#指定作者
MAINTAINER HXQ
#新建文件夹用于存放jdk文件
RUN mkdir /usr/local/java
#将JDK文件复制到镜像内并自动解压
ADD jdk-8u141-linux-x64.tar.gz /usr/local/java/
#创建软链接
RUN ln -s /usr/local/java/jdk1.8.0_141 /usr/local/java/jdk
#设置环境变量
ENV JAVA_HOME /usr/local/java/jdk
ENV JRE_HOME ${JAVA_HOME}/jre
ENV CLASSPATH .:${JAVA_HOME}/lib:${JRE_HOME}/lib
ENV PATH ${JAVA_HOME}/bin:$PATH

使用docker build命令构建新镜像

[root@master centos-jdk]# docker build -t="centos-jdk" .

查看构建的新镜像

[root@master centos-jdk]# docker images
REPOSITORY                 TAG                 IMAGE ID            CREATED             SIZE
centos-jdk                 latest              71cd3f76e898        9 seconds ago       596MB

使用新构建的镜像运行容器验证JDK是否安装成功

[root@master centos-jdk]# docker run -it centos-jdk /bin/bash
[root@9e7003167e1e /]# java -version
java version "1.8.0_141"
Java(TM) SE Runtime Environment (build 1.8.0_141-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.141-b15, mixed mode)

可以发现JDK已经安装成功了,至此,使用Dockerfile构建镜像已完成

Docker容器编排

基础准备

节点规划

ip 主机名 节点
10.30.59.221 master swarm集群Master节点
10.30.59.222 node swarm集群Node节点

所有节点配置好主机名和网卡,并安装好docker-ce

案例实施

1、部署Swarm集群
(1)配置主机映射
所有节点修改/etc/hosts文件配置主机映射

[root@master ~]# vi /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
10.30.59.221 master
10.30.59.222 node

(2)配置时间同步
所有节点安装chrony服务

[root@master ~]# yum install -y chrony

Master节点修改/etc/chrony.conf文件,注释默认NTP服务器,指定上游公共NTP服务器,并允许其他节点同步时间。

[root@master ~]# sed -i 's/^server/#&/' /etc/chrony.conf
[root@master ~]# cat >>/etc/chrony.conf<<EOF
> local stratum 10
> server master iburst
> allow all
> EOF

Master节点重启chronyd服务并设为开机启动,开启网络时间同步功能。

[root@master ~]# systemctl enable chronyd && systemctl restart chronyd
[root@master ~]# timedatectl set-ntp true

Node节点修改/etc/chrony.conf文件,指定内网Master节点为上游NTP服务器,重启服务并设为开机启动

[root@node ~]# sed -i 's/^server/#&/' /etc/chrony.conf 
[root@node ~]# echo server 10.30.59.211iburst >> /etc/chrony.conf 
[root@node ~]# systemctl enable chronyd && systemctl restart chronyd

所有节点执行chronyc sources命令,查询结果中如果存在以“^*”开头的行,即说明已经同步成功
(3)配置Docker API
所有节点开启Docker API

# vi /lib/systemd/system/docker.service
将
 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
修改为
 ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
# systemctl daemon-reload
# systemctl restart docker
# ./image.sh

(4)初始化集群
在Master节点创建Swarm集群。

[root@master ~]# docker swarm init --advertise-addr 10.30.59.221

初始化命令中 “—advertise-addr”选项表示管理节点公布它的IP是多少。其他节点必须通过这个IP找到管理节点。
输出结果中包含3个步骤
①Swarm创建成功,swarm-manager成为manager node。
②添加worker node需要执行的命令。
③添加manager node需要执行的命令。
(5)Node节点加入集群
复制前面的docker swarm join 命令,在node节点执行以加入swarm集群

[root@node ~]# docker swarm join --token SWMTKN-1-1hvc4qcv056kf1jz7zijkhys7ikn0dc0adhmx8z3mq0kyw31mv-4lyqbbrhqjuwfnecxkdqd2n93 10.30.59.221:2377
This node joined a swarm as a worker.

如果初始化时没有记录下 docker swarm init 提示的添加 worker 的完整命令,可以通过 docker swarm join-token worker 命令查看
(6)验证集群
登录Master节点,查看各节点状态

[root@master ~]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
2k91s59v2msoe9qis6v48jwh1 *   master              Ready               Active              Leader              18.09.6
1wd0b1kx2git8wqyk73w67jl3     node                Ready               Active                                  18.09.6

(7)安装Portainer
登录Master节点安装Portainer

[root@master ~]# docker service create --name portainer --publish 9000:9000 --replicas=1 --constraint 'node.role == manager' --mount type=bind,src=//var/run/docker.sock,dst=/var/run/docker.sock --mount type=volume,src=portainer_data,dst=/data portainer/portainer -H unix:///var/run/docker.sock

(8)登录Portainer
打开浏览器输入地址http://10.30.59.221:9000访问Portainer主页
image.png
2、运行service
现在已经创建好了Swarm集群,执行如下命令部署一个运行httpd进行的service

[root@master ~]# docker service create --name web_server httpd

部署service的命令形式与运行容器的docker run很相似,—name为service命名,httpd为镜像的名字

通过docker service ls 命令可以查看当前Swarm中的service

[root@master ~]# docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE                        PORTS
8u8y6d2semrf        portainer           replicated          1/1                 portainer/portainer:latest   *:9000->9000/tcp
o64li0afwaj6        web_server          replicated          1/1                 httpd:latest

REPLICAS 显示当前副本信息,1/1 意思是 web_server 这个 Service 期望的容器副本数 量为 1,目前已经启动的副本数量为 1,即当前 Service 已经部署完成。命令 docker service ps 可以查看 Service 每个副本的状态。

[root@master ~]# docker service ps web_server
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE           ERROR               PORTS
70u8sg5ep1f0        web_server.1        httpd:latest        node                Running             Running 4 minutes ago

可以查看到 Service 唯一的副本被分派到 node,当前的状态是 Running。
(2)service伸缩
刚刚仅部署了只有一个副本的 Service,不过对于 Web 服务,通常会运行多个实例。这 样可以负载均衡,同时也能提供高可用。
Swarm 要实现这个目标非常简单,增加 Service 的副本数就可以了。在 Master 节点上执 行如下命令 。

[root@master ~]# docker service scale web_server=5
web_server scaled to 5
overall progress: 5 out of 5 tasks 
1/5: running   [==================================================>] 
2/5: running   [==================================================>] 
3/5: running   [==================================================>] 
4/5: running   [==================================================>] 
5/5: running   [==================================================>] 
verify: Service converged 
[root@master ~]# docker service ps web_server
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
70u8sg5ep1f0        web_server.1        httpd:latest        node                Running             Running 8 minutes ago                        
o4eet3eaq7ut        web_server.2        httpd:latest        master              Running             Running 26 seconds ago                       
kqhy9q7m7au8        web_server.3        httpd:latest        node                Running             Running 46 seconds ago                       
a32z10l8key4        web_server.4        httpd:latest        master              Running             Running 26 seconds ago                       
zkinyfex2ibe        web_server.5        httpd:latest        node                Running             Running 46 seconds ago

5个副本已经分布在Swarm的所有节点上
既然可以通过 scale up 扩容服务,当然也可以通过 scale down 减少副本数

[root@master ~]# docker service scale web_server=2
web_server scaled to 2
overall progress: 2 out of 2 tasks 
1/2: running   [==================================================>] 
2/2: running   [==================================================>] 
verify: Service converged 
[root@master ~]# docker service ps web_server
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
70u8sg5ep1f0        web_server.1        httpd:latest        node                Running             Running 13 minutes ago                       
o4eet3eaq7ut        web_server.2        httpd:latest        master              Running             Running 4 minutes ago

可以看到 web_server.3、web_server.4 和 web_server.5 这 3 个副本已经被删除了。
(3)访问service
要访问 http 服务,首先得保证网络通畅,其次需要知道服务的 IP。查看容器的网络配置。

[root@master ~]# docker ps
CONTAINER ID        IMAGE                        COMMAND                  CREATED             STATUS              PORTS                    NAMES
cd68f0434301        httpd:latest                 "httpd-foreground"       6 minutes ago       Up 6 minutes        80/tcp                   web_server.2.o4eet3eaq7utf87t8aczm7dqx
451dbfdee177        portainer/portainer:latest   "/portainer -H unix:…"   21 minutes ago      Up 21 minutes       9000/tcp                 portainer.1.vsg2f2gnqzat5hl3z21bas8lu
350997f78a09        registry:latest              "/entrypoint.sh /etc…"   22 hours ago        Up 2 hours          0.0.0.0:5000->5000/tcp   registry

在 Master 上运行了一个容器,是 web_server 的一个副本,容器监听了 80 端口,但并没 有映射到 Docker Host,所以只能通过容器的 IP 访问。但是服务并没有暴露给外部网络,只 能在 Docker 主机上访问,外部无法访问。要将 Service 暴露到外部,方法其实很简单,执行 下面的命令即可。

[root@master ~]# docker service update --publish-add 8080:80 web_server
web_server
overall progress: 2 out of 2 tasks 
1/2: running   [==================================================>] 
2/2: running   [==================================================>] 
verify: Service converged

—publish-add 8080:80 将容器的 80 映射到主机的 8080 端口,这样外部网络就能访问到 Service 了。通过 http://任意节点 IP:8080 即可访问 Service
(4)Service存储数据
Service 的容器副本可能会伸缩,甚至失败,会在不同的主机上创建和销毁,这就引出 一个问题,如果 Service 有需要管理的数据,那么这些数据应该如何存放呢?如果把数据打 包在容器里,这显然不行,除非数据不会发生变化,否则,如何在多个副本之间保持同步呢? volume 是将宿主级的目录映射到容器中,以实现数据持久化。可以用两种方式来实现:  volume 默认模式:工作节点宿主机数据同步到容器内。  volume NFS 共享存储模式:管理节点宿主同步到工作节点宿主,工作节点宿主同步 到容器。29 生产环境中一般推荐使用 volume NFS 共享存储模式。
生产环境中一般推荐使用volume NFS共享存储模式。
登录Master节点,安装NFS服务端、配置NFS主配置文件、添加权限并启动。

[root@master ~]# yum install -y nfs-utils

添加目录让相应网段可以访问并添加读写权限。

[root@master ~]# vi /etc/exports
/root/share 10.30.59.221/24(rw,async,insecure,anonuid=1000,anongid=1000,no_root_squash)

创建共享目录,添加权限。

[root@master ~]# mkdir -p /root/share
[root@master ~]# chmod 777 /root/share

/root/share 为共享目录,生效配置。

[root@master ~]# exportfs -rv
exporting 10.30.59.221/24:/root/share

开启 RPC 服务并设置开机自启。

[root@master ~]# systemctl start rpcbind && systemctl enable rpcbind

启动NFS服务并设置开机自启

[root@master ~]# systemctl start nfs && systemctl enable nfs
Created symlink from /etc/systemd/system/multi-user.target.wants/nfs-server.service to /usr/lib/systemd/system/nfs-server.service.

查看NFS是否挂载成功

[root@master ~]# cat /var/lib/nfs/etab 
/root/share    10.30.59.221/24(rw,async,wdelay,hide,nocrossmnt,insecure,no_root_squash,no_all_squash,no_subtree_check,secure_locks,acl,no_pnfs,anonuid=1000,anongid=1000,sec=sys,rw,insecure,no_root_squash,no_all_squash)

登录Node节点,安装NFS客户端并启动服务

[root@node ~]# yum install -y nfs-utils
[root@node ~]# systemctl start rpcbind && systemctl enable rpcbind
[root@node ~]# systemctl start nfs && systemctl enable nfs
Created symlink from /etc/systemd/system/multi-user.target.wants/nfs-server.service to /usr/lib/systemd/system/nfs-server.service.

部署的服务可能分不到各个节点上,在所有节点创建 docker volume。

[root@master ~]# docker volume create --driver local --opt type=nfs --opt o=addr=10.30.59.221,rw --opt device=:/root/share foo33

—opt device=:/root/share 用于指向共享目录,也可以是共享目录下的子目录。 查看 volume。

[root@master ~]# docker volume ls
DRIVER              VOLUME NAME
local               foo33
local               portainer_data

可以查看到 docker volume 列表中有 foo33,查看 volume 详细信息。

[root@master ~]# docker volume ls
DRIVER              VOLUME NAME
local               foo33
local               portainer_data
[root@master ~]# docker volume inspect foo33
[
    {
        "CreatedAt": "2021-07-16T19:55:12+08:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/foo33/_data",
        "Name": "foo33",
        "Options": {
            "device": ":/root/share",
            "o": "addr=10.30.59.221,rw",
            "type": "nfs"
        },
        "Scope": "local"
    }
]

可以看出 NFS 的/root/share 被挂载到了/var/lib/docker/volumes/foo33/_data 目录。

创建并发布服务。

[root@master ~]# docker service create --name test-nginx-nfs --publish 80:80 --mount type=volume,source=foo33,destination=/app/share --replicas 3 nginx
vzf1mvy3fpm6epy09vx2hl07a
overall progress: 3 out of 3 tasks 
1/3: running   [==================================================>] 
2/3: running   [==================================================>] 
3/3: running   [==================================================>] 
verify: Service converged

查看服务分布的节点。

[root@master ~]# docker service ps test-nginx-nfs
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE           ERROR               PORTS
dgdn1538sf7e        test-nginx-nfs.1    nginx:latest        node                Running             Running 4 minutes ago                       
vgug75ibxtzi        test-nginx-nfs.2    nginx:latest        node                Running             Running 4 minutes ago                       
8zgx534cq5r9        test-nginx-nfs.3    nginx:latest        master              Running             Running 4 minutes ago

在 Master 节点/root/share 目录中生成一个 index.html 文件

[root@master ~]# cd  /root/share/
[root@master share]# ll
total 0
[root@master share]# touch index.html
[root@master share]# ll
total 0
-rw-r--r-- 1 root root 0 Jul 16 20:03 index.html

查看宿主机目录挂载情况

[root@master ~]# docker volume inspect foo33
[
    {
        "CreatedAt": "2021-07-16T20:21:33+08:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/foo33/_data",
        "Name": "foo33",
        "Options": {
            "device": ":/root/share",
            "o": "addr=10.30.59.221,rw",
            "type": "nfs"
        },
        "Scope": "local"
    }
]
[root@master ~]# ls /var/lib/docker/volumes/foo33/_data
index.html

查看容器目录

[root@master ~]# docker ps
CONTAINER ID        IMAGE                        COMMAND                  CREATED             STATUS              PORTS                    NAMES
9ff66dadd7f5        nginx:latest                 "/docker-entrypoint.…"   10 minutes ago      Up 10 minutes       80/tcp                   test-nginx-nfs.3.8zgx534cq5r9c5x371blfv4ah
cc7cfc2287d8        httpd:latest                 "httpd-foreground"       About an hour ago   Up About an hour    80/tcp                   web_server.2.aepbt3qaki42y1t8quwi6jakc
451dbfdee177        portainer/portainer:latest   "/portainer -H unix:…"   2 hours ago         Up 2 hours          9000/tcp                 portainer.1.vsg2f2gnqzat5hl3z21bas8lu
350997f78a09        registry:latest              "/entrypoint.sh /etc…"   24 hours ago        Up 3 hours          0.0.0.0:5000->5000/tcp   registry
[root@master ~]# docker exec -it 9ff66dadd7f5 bash
root@9ff66dadd7f5:/# ls app/share/
index.html

可以发现,NFS已经挂载成功
(5)调度节点
默认配置下 Master 也是 worker node,所以 Master 上也运行了副本。如果不希望在 Master 上运行 Service,可以执行如下命令。

[root@master ~]# docker node update --availability drain master
master

通过 docker node ls 命令查看各节点现在的状态。

[root@master ~]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
2k91s59v2msoe9qis6v48jwh1 *   master              Ready               Drain               Leader              18.09.6
1wd0b1kx2git8wqyk73w67jl3     node                Ready               Active                                  18.09.6

Drain 表示 Master 已经不负责运行 Service,之前 Master 运行的那 1 个副本会如何处理 呢?使用 docker service ps 命令来查看。

[root@master ~]# docker service ps test-nginx-nfs
ID                  NAME                   IMAGE               NODE                DESIRED STATE       CURRENT STATE                 ERROR               PORTS
dgdn1538sf7e        test-nginx-nfs.1       nginx:latest        node                Running             Running 15 minutes ago                            
vgug75ibxtzi        test-nginx-nfs.2       nginx:latest        node                Running             Running 15 minutes ago                            
zsli54am6b5c        test-nginx-nfs.3       nginx:latest        node                Running             Running about a minute ago                        
8zgx534cq5r9         \_ test-nginx-nfs.3   nginx:latest        master              Shutdown            Shutdown about a minute ago

Master 上的副本 test-nginx-nfs.3 已经被 Shut down 了,为了达到 3 个副本数的目标,在 Node 上添加了新的副本 test-nginx-nfs.3。