Loading...

# Docker 容器的使用

# Docker 客户端

输入 docker 命令可以查看到 Docker 客户端的所有命令。

docker

docker命令

可以通过 docker command --help 更深入的查看 Docker 命令使用方法。

docker attach --help

doker指定命令详情

# 容器的使用

# 获取镜像

如果本地没有 ubuntu 镜像,可以使用 docker pull 命令来载入 ubuntu 镜像

docker pull ubuntu

# 启动容器

下面命令使用 ubuntu 镜像启动一个容器,参数以命令行模式进入该容器

参数说明

  • -i 交互式操作
  • -t 终端
  • ubuntu ubuntu 镜像
  • /bin/bash 放在镜像后的命令,这里我们希望有个交互式 Shell,因此用的是 /bin/bash。
docker run -it ubuntu /bin/bash

docker容器启动命令

如果要退出终端,输入 exit

停止终端

# 查看所有容器

docker ps -a

查看所有容器

# 启用已停止容器

docker start 81bb4132e433

# 后台运行

在大部分情况下,我们是更希望 docker 的服务是在后台运行的,可以通过 **-d** 指定容器的运行模式。

docker run -itd --name ubuntu_name ubuntu /bin/bash

后台运行容器

** 注:** 加了 -d 参数默认不会进入容器,想要进入容器需要使用指令 docker exec(下面会介绍到)。

# 停止一个容器

docker stop <容器ID>

停止的容器当然也可以通过 docker restart 重启

docker restart <容器ID>

停止和重启容器

停止所有容器

docker stop $(docker ps -aq)

# 进入容器

在使用 -d 参数时,容器启动后会进入后台。此时想要进入容器,可以通过以下指令进入

  • docker attach
  • docker exec:推荐大家使用 docker exec 命令,因为此命令会退出容器终端,但不会导致容器的停止。

attach 命令

docker attach <容器ID>

进入容器1

exec 命令

docker exec -it <容器ID> /bin/bash

进入容器2

注意: 如果从这个容器退出,容器不会停止,这就是为什么推荐大家使用 docker exec 的原因。

# 导出和导入容器

导出容器

如果要导出本地某个容器,可以使用 docker export 命令。

docker export <容器ID> > ubuntu.tar

容器导出

导入容器快照

可以使用 docker import 从容器快照文件中再导入为镜像。

cat ubuntu.tar | docker import - ubuntu_demo:v1

将快照文件 ubuntu.tar 导入镜像 ubuntu_demo 中

容器导入

也可以通过指定 URL 或者某个目录来导入

docker import <导入URL> <镜像名称>

# 删除容器

docker rm -f <容器ID>

清除所有处于终止状态的容器。

docker container prune

# 运行 WEB 应用

# 拉取容器

使用 docker 构建一个 web 应用程序。

在 docker 容器中运行一个 Python Flask 应用来运行一个 web 应用。

docker pull training/webapp #载入镜像
docker run -d -P tratining/webapp python app.py

参数说明

  • -d 让容器在后台运行。
  • -P 将容器内部使用的网络端口随机映射到我们使用的主机上

# 查看 WEB 应用容器

使用 docker ps 查看正在运行的容器,能够发现现在多了端口信息。

运行web项目

Docker 开放了 5000 端口(默认 Python Flask 端口)映射到主机端口 49153 上。

这时我们可以通过浏览器访问 WEB 应用

访问地址:服务器 IP 地址:49153

如果访问不了,说明服务器可能没有开通此端口号,需要去控制台打开此端口。

也可以通过 **-p** 参数设置不一样的端口号

docker run -d -p 5000:5000 training/webapp python app.py

运行web项目(端口号)

容器内部的 5000 端口映射到我们本地主机的 5000 端口上。

# 网络端口的快捷方式

通过 docker ps 命令可以查看到容器的端口映射,docker 还提供了另一个快捷方式 docker port,使用 docker port 可以查看指定 (ID 或者名字)容器的某个确定端口映射到宿主机的端口号。

docker port <容器ID 或 容器名称>

# 查看 WEB 应用程序日志

docker logs [ID 或者名字] 可以查看容器内部的标准输出。

docker logs -f <容器ID 或 容器名称>

-f:docker logs 像使用 tail -f 一样来输出容器内部的标准输出。

# 查看 WEB 应用程序容器的进程

docker top <容器ID 或 容器名称>

# 检查 WEB 应用程序

使用 docker inspect 来查看 Docker 的底层信息。它会返回一个 JSON 文件记录着 Docker 容器的配置和状态信息。

docker insepct <容器ID 或 容器名称>

# 停止 WEB 应用容器

docker stop <容器ID 或 容器名称>

# 重启 WEB 应用容器

docker start <容器ID 或 容器名称>

docker ps -l 查询最后一次创建的容器

# 移除 WEB 应用容器

docker rm <容器ID 或 容器名称>

# Docker 镜像使用

# 列出镜像列表

使用 docker images 来列出本地主机上的镜像

查看所有镜像

同一仓库源可以有多个 TAG,代表这个仓库源的不同个版本,如 ubuntu 仓库源里,有 15.10、14.04 等多个不同的版本,我们使用 REPOSITORY:TAG 来定义不同的镜像。

所以,我们如果要使用版本为 15.10 的 ubuntu 系统镜像来运行容器时,命令如下

docker run -it ubuntu:15.10 /bin/bash

各个选项说明:

  • REPOSITORY 表示镜像的仓库源
  • TAG 镜像的标签
  • IMAGE ID 镜像 ID
  • CREATED 镜像创建时间
  • SIZE 镜像大小

如果不指定一个镜像的版本标签,将默认使用 ubuntu:latest 镜像。

# 获取一个新的镜像

当我们在本地主机上使用一个不存在的镜像时 Docker 就会自动下载这个镜像。如果我们想预先下载这个镜像,我们可以使用 docker pull 命令来下载它。

下载完成后,我们可以直接使用这个镜像来运行容器。

docker pull ubuntu:13.10

# 查找镜像

可以从 Docker Hub 网站来搜索镜像,Docker Hub 网址为: https://hub.docker.com/

也可以使用 docker search 命令来搜索镜像。

docker search java

搜索镜像

各个选项说明

  • NAME 镜像仓库源的名称
  • DESCRIPTION 镜像的描述
  • OFFICIAL 是否 docker 官方发布
  • stars 类似 Github 里面的 star,表示点赞、喜欢的意思。
  • AUTOMATED 自动构建。

# 拖取镜像

使用命令 docker pull 来下载镜像。

docker pull <镜像>

# 删除镜像

docker rmi <镜像>

删除所有镜像

docker rmi -f $(docker images -qa)

# 创建镜像

当我们从 docker 镜像仓库中下载的镜像不能满足我们的需求时,我们可以通过以下两种方式对镜像进行更改。

  • 从已经创建的容器中更新镜像,并且提交这个镜像
  • 使用 Dockerfile 指令来创建一个新的镜像

# 更新镜像

更新镜像之前,我们需要使用镜像来创建一个容器。

docker run -it ubuntu /bin/bash

在运行的容器内使用 apt-get update 命令进行更新。

在完成操作之后,输入 exit 命令来退出这个容器。

此时 ID 为 0a768a9bea64 的容器,是按我们的需求更改的容器。我们可以通过命令 docker commit 来提交容器副本。

docker commit -m="has update" -a="root" 0a768a9bea64 ubuntu_demo:v2

各个参数说明:

  • -m 提交的描述信息
  • -a 指定镜像作者
  • e218edb10161 容器 ID
  • runoob/ubuntu:v2 指定要创建的目标镜像名

更新镜像

# 构建镜像

我们使用命令 docker build, 从零开始来创建一个新的镜像。为此,我们需要创建一个 Dockerfile 文件,其中包含一组指令来告诉 Docker 如何构建我们的镜像。

列如:构建 JAVA 环境镜像

vim Dockerfile

编写 Dockerfile 文件

# 基础镜像用 centos
FROM centos:6.7
# 作者
MAINTAINER qiyin
# 添加最新版 jdk19.tar.gz 到容器中,并解压到 /usr/local/ 路径下
ADD jdk-19_linux-x64_bin.tar.gz /usr/local/
# 添加环境变量
ENV JAVA_HOME /usr/local/jdk-19.0.1
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV PATH $PATH:$JAVA_HOME/bin
# 暴露端口号
EXPOSE 8888

使用当前文件构建镜像

docker build -t java:v1 .

-t:指定要创建的目标镜像名,java 为创建的镜像名,v1 为镜像标签

.:Dockerfile 文件所在目录,可以指定 Dockerfile 的绝对路径

使用当前构建的镜像来创建容器

docker run -it java:v1

验证环境变量是否正确,如果出现 java 版本则说明配置成功。

java -version

构建镜像

# 设置镜像标签

我们可以使用 docker tag 命令,为镜像添加一个新的标签。

docker tag <镜像ID> <新的镜像名>:<新的镜像标签>

镜像添加新标签

# Docker 容器连接

前面我们实现了通过网络端口来访问运行在 docker 容器内的服务。

容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过 -P-p 参数来指定端口映射。

下面我们来实现通过端口连接到一个 docker 容器。

# 网络端口映射

创建一个 python 应用容器

docker run -d -P training/webapp python app.py

也可以使用 -p 标识来指定容器端口绑定到主机端口

docker run -d -p 5000:5000 training/webapp python app.py

两种方式的区别是:

  • -P : 是容器内部端口随机映射到主机的端口。
  • -p : 是容器内部端口绑定到指定的主机端口。

端口映射

另外,也可以指定容器绑定的网络地址,比如绑定 127.0.0.1。

docker run -d -p 127.0.0.1:5001:5000 training/webapp python app.py

以上默认都是绑定 tcp 端口,如果要绑定 udp 端口,可以在端口后面加上 /udp

docker run -d -p 127.0.0.1:5001:5000/udp training/webapp python app.py

端口映射2

docker port 命令可以让我们快捷地查看端口的绑定情况。

查看绑定端口号

# Docker 容器互联

端口映射并不是唯一把 docker 连接到另一个容器的方法。

docker 有一个连接系统允许将多个容器连接在一起,共享连接信息。

docker 连接会创建一个父子关系,其中父容器可以看到子容器的信息。

# 新建网络

docker network create -d bridge test-net

参数说明

  • -d:参数指定 Docker 网络类型,有 bridge、overlay。

新建网络

# 连接容器

运行一个容器并连接到新建的 test-net 网络

docker run -itd --name test1 --network test-net ubuntu /bin/bash

打开新的终端,再运行一个容器并加入到 test-net 网络

docker run -itd --name test2 --network test-net ubuntu /bin/bash

下面通过 ping 来证明 test1 容器和 test2 容器建立了互联关系。

如果 test1、test2 容器内中无 ping 命令,则在容器内安装 ping 命令。

安装步骤

  1. 新打开一个容器
docker run -it ubuntu
  1. 运行以下命令
apt-get update
apt install iputils-ping
  1. 退出容器
  2. 提交容器到镜像
docker commit -a "作者名" -m "提交信息" <容器ID> <镜像>

安装ping命令再用新的镜像重新运行以上两个容器(test1、test2)

连接test2

连接test1

# 配置 DNS

在宿主机的 /etc/docker/daemon.json 文件中增加以下内容来设置全部容器的 DNS。

{
    "dns": [
        "114.114.114.114",
        "8.8.8.8"
    ]
}

设置后,启动容器的 DNS 会自动配置为 114.114.114.114 和 8.8.8.8。

配置完,需要重启 docker 才能生效。

systemctl restart docker

查看容器的 DNS 是否生效可以使用以下命令,它会输出容器的 DNS 信息

docker run -it --rm ubuntu cat etc/resolv.conf

配置DNS

手动指定容器的配置

如果只想在指定的容器设置 DNS,则可以使用以下命令

docker run -it --rm -h host_ubuntu --dns=114.114.114.114 --dns-search=test.com ubuntu

参数说明

  • --rm:容器退出时自动清理容器内部的文件系统。
  • -h HOSTNAME 或者 --hostname=HOSTNAME: 设定容器的主机名,它会被写到容器内的 /etc/hostname 和 /etc/hosts。
  • --dns=IP_ADDRESS: 添加 DNS 服务器到容器的 /etc/resolv.conf 中,让容器用这个服务器来解析所有不在 /etc/hosts 中的主机名。
  • --dns-search=DOMAIN: 设定容器的搜索域,当设定搜索域为 .example.com 时,在搜索一个名为 host 的主机时,DNS 不仅搜索 host,还会搜索 host.example.com

配置自定义DNS

# Docker 仓库管理

仓库(Repository)是集中存放镜像的地方。

# Docker Hub

目前 Docker 官方维护了一个公共仓库 Docker Hub

大部分需求都可以通过在 Docker Hub 中直接下载镜像来实现。

# 注册

https://hub.docker.com 免费注册一个 Docker 账号。

# 登录和退出

登录需要输入用户名和密码,登录成功后,我们就可以从 docker hub 上拉取自己账号下的全部镜像。

docker login
docker logout

# 推送镜像

通过 docker search 命令来查找官方仓库中的镜像,并利用 docker pull 命令来将它下载到本地。

使用 docker pull 将官方 ubuntu 镜像下载到本地

通过 docker push 命令将自己的镜像推送到 Docker Hub。

以下命令中的 username 请替换为你的 Docker 账号用户名

# 搜索 ubuntu 镜像
docker search ubuntu
# 拉取 ubuntu 镜像
docker pull ubuntu
# 为 ubuntu 镜像添加新的标签
docker tag ubuntu username/ubuntu:v1
# 将新标签的镜像推送至 Docker Hub
docker push username/ubuntu:v1
# 搜索自己推上去的镜像
docker seach username/ubuntu

# Docker DockerFile

Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。

# 定制镜像

# 使用 Dockerfile 定制镜像

1、定制一个 nginx 镜像(构建好的镜像内会有一个 /usr/share/nginx/html/index.html 文件)

在一个空目录下,新建一个名为 Dockerfile 文件,并在文件内添加以下内容

FROM nginx
RUN echo '这是一个本地构建的nginx镜像' > /usr/share/nginx/html/index.html

2、FROM 和 RUN 指令的作用

FROM:定制的镜像都是基于 FROM 的镜像,这里的 nginx 就是定制需要的基础镜像。后续的操作都是基于 nginx。

RUN:用于执行后面跟着的命令行命令。有以下俩种格式

  • shell 格式

    RUN <命令行命令>
    # < 命令行命令 > 等同于,在终端操作的 shell 命令。
  • exec 格式

    RUN ["可执行文件", "参数1", "参数2"]
    # 例如:
    # RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline

注意:Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。

RUN yum -y install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN tar -xvf redis.tar.gz

以上执行会创建 3 层镜像。

FROM centos
RUN yum -y install wget \
    && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
    && tar -xvf redis.tar.gz

&& 符号连接命令,这样执行后,只会创建 1 层镜像。

# 开始构建镜像

在 Dockerfile 文件的存放目录下,执行构建动作。

docker build -t nginx:v3 .

构建nginx

以上显示,说明已经构建成功。

# 上下文路径

上一节中,有提到指令最后一个 . 是上下文路径。

上下文路径,是指 docker 在构建镜像,有时候想要使用到本机的文件(比如复制),docker build 命令得知这个路径后,会将路径下的所有内容打包。

解析:由于 docker 的运行模式是 C/S。我们本机是 C,docker 引擎是 S。实际的构建过程是在 docker 引擎下完成的,所以这个时候无法用到我们本机的文件。这就需要把我们本机的指定目录下的文件一起打包提供给 docker 引擎使用。

如果未说明最后一个参数,那么默认上下文路径就是 Dockerfile 所在的位置。

注意:上下文路径下不要放无用的文件,因为会一起打包发送给 docker 引擎,如果文件过多会造成过程缓慢。

# 指令详解

# COPY

复制指令,从上下文目录中复制文件或者目录到容器里指定路径。

COPY [--chown=<user>:<group>] <源路径1>...  <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",...  "<目标路径>"]

[--chown=<user>:<group>]:可选参数,用户改变复制到容器内文件的拥有者和属组。

<源路径>:源文件或者源目录,这里可以是通配符表达式,其通配符规则要满足 Go 的 filepath.Match 规则。例如:

COPY hom* /mydir/
COPY hom?.txt /mydir/

<目标路径>:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。

# ADD

ADD 指令和 COPY 的使用格类似(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:

  • ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 < 目标路径 >。
  • ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。

# CMD

类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:

  • CMD 在 docker run 时运行。
  • RUN 是在 docker build。

作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。

注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。

格式:

CMD <shell 命令> 
CMD ["<可执行文件或命令>","<param1>","<param2>",...] 
CMD ["<param1>","<param2>",...]  # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数

推荐使用第二种格式,执行过程比较明确。第一种格式实际上在运行的过程中也会自动转换成第二种格式运行,并且默认可执行文件是 sh。

# ENTRYPOINT

类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。

但是,如果运行 docker run 时使用了 --entrypoint 选项,将覆盖 ENTRYPOINT 指令指定的程序。

优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。

注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。

ENTRYPOINT ["<executeable>","<param1>","<param2>",...]

可以搭配 CMD 命令使用:一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参,以下示例会提到。

示例:

假设已通过 Dockerfile 构建了 nginx:test 镜像:

FROM nginx
ENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参

1、不传参运行

docker run  nginx:test

容器内会默认运行以下命令,启动主进程。

nginx -c /etc/nginx/nginx.conf

2、传参运行

docker run  nginx:test -c /etc/nginx/new.conf

容器内会默认运行以下命令,启动主进程 (/etc/nginx/new.conf: 假设容器内已有此文件)

nginx -c /etc/nginx/new.conf

# ENV

设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。

ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...

以下示例设置 NODE_VERSION = 7.2.0 , 在后续的指令中可以通过 $NODE_VERSION 引用:

ENV NODE_VERSION 7.2.0
RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
  && curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc"

# ARG

构建参数,与 ENV 作用一致。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。

构建命令 docker build 中可以用 --build-arg <参数名>=< 值 > 来覆盖。

ARG <参数名>[=<默认值>]

# VOLUME

定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。

作用:

  • 避免重要的数据,因容器重启而丢失,这是非常致命的。
  • 避免容器不断变大。
VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>

在启动容器 docker run 的时候,我们可以通过 -v 参数修改挂载点。

# EXPOSE

仅仅只是声明端口。

作用:

  • 帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。
  • 在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。
EXPOSE <端口1> [<端口2>...]

# WORKDIR

指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会帮你建立目录。

docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。

WORKDIR <工作目录路径>

# USER

用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)。

USER <用户名>[:<用户组>]

# HEALTHCHECK

用于指定某个程序或者指令来监控 docker 容器服务的运行状态。

HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令
HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令
HEALTHCHECK [选项] CMD <命令> : 这边 CMD 后面跟随的命令使用,可以参考 CMD 的用法。

# ONBUILD

用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这时执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。

ONBUILD <其它指令>

# LABEL

LABEL 指令用来给镜像添加一些元数据(metadata),以键值对的形式,语法格式如下:

LABEL <key>=<value> <key>=<value> <key>=<value> ...

比如我们可以添加镜像的作者:

LABEL org.opencontainers.image.authors="root"

# 指令简洁版

  • FROM 构建镜像基于哪个镜像

  • MAINTAINER 镜像维护者姓名或邮箱地址

  • RUN 构建镜像时运行的指令

  • CMD 运行容器时执行的 shell 环境

  • VOLUME 指定容器挂载点到宿主机自动生成的目录或其他容器

  • USER 为 RUN、CMD、和 ENTRYPOINT 执行命令指定运行用户

  • WORKDIR 为 RUN、CMD、ENTRYPOINT、COPY 和 ADD 设置工作目录,就是切换目录

  • HEALTHCHECH 健康检查

  • ARG 构建时指定的一些参数

  • EXPOSE 声明容器的服务端口(仅仅是声明)

  • ENV 设置容器环境变量

  • ADD 拷贝文件或目录到容器中,如果是 URL 或压缩包便会自动下载或自动解压

  • COPY 拷贝文件或目录到容器中,跟 ADD 类似,但不具备自动下载或解压的功能

  • ENTRYPOINT 运行容器时执行的 shell 命令

# Docker Compose

# Compose 简介

Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。

Compose 使用的三个步骤

  • 使用 Dockerfile 定义应用程序的环境。
  • 使用 docker-compose.yml 定义构成应用程序的服务,这样它们可以在隔离环境中一起运行。
  • 最后,执行 docker-compose up 命令来启动并运行整个应用程序。

# Compose 安装

Linux 上我们可以从 Github 上下载它的二进制包来使用,最新发行的版本地址:https://github.com/docker/compose/releases。

运行以下命令以下载 Docker Compose 的当前稳定版本

curl -L "https://github.com/docker/compose/releases/download/v2.2.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

将可执行权限应用于二进制文件

chmod +x /usr/local/bin/docker-compose

创建软链

ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

测试是否安装成功

docker-compose version

# 使用(Springboot+Redis+MySQL)

# 准备

创建一个 SpringBoot 目录

mkdir springboot
cd springboot

# 构建 Springboot.jar 包

1. 引入 maven 依赖

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.6.6</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>2.6.6</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.48</version>
        </dependency>
    </dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>2.0.3.RELEASE</version>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

2. 配置文件(application.yml)

server:
  port: 8888
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://mysqlserver:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: 123456
  mybatis:
    configration:
      map-underscore-to-camel-case: true
  redis:
    host: redis
    port: 6379

3. 编写代码

controller

package com.example.demo.controller;
import com.example.demo.entity.DemoEntity;
import com.example.demo.mapper.DemoMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class DemoController {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private DemoMapper demoMapper;
    @GetMapping("get")
    public String get(){
        stringRedisTemplate.opsForValue().set("demo", "SpringBoot + Redis + MySQL");
        return stringRedisTemplate.opsForValue().get("demo");
    }
    @GetMapping("queryAll")
    public List<DemoEntity> queryAll(){
        return demoMapper.queryAll();
    }
}

entity

package com.example.demo.entity;
import java.io.Serializable;
public class DemoEntity implements Serializable {
    private String id;
    private String name;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

mapper

package com.example.demo.mapper;
import com.example.demo.entity.DemoEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface DemoMapper {
    @Select("select * from demo")
    List<DemoEntity> queryAll();
}

4. 使用 package 进行打包

5. 将打包好的文件上传至 springboot 目录下

# 创建 Dockerfile 文件

在 springboot 目录中,创建一个名为 Dockerfile_web 的文件,内容如下

# 从 openjdk:8 映像开始构建镜像。
FROM openjdk:8
# 将当前目录下以.jar 名称结尾的文件复制到镜像中的工作目录,并改名为 app.jar。
COPY *.jar /app.jar
# 
CMD ["--server.port=8888"]
# 暴露 8888 端口号
EXPOSE 8888
# 运行 java 项目的命令
ENTRYPOINT ["java", "-jar", "app.jar"]

在 springboot 目录中,创建一个名为 Dockerfile_mysql 的文件,内容如下

FROM mysql:5.7.17

# 创建 docker-compose.yml

在 springboot 目录中创建一个名为 docker-compose.yml 的文件,然后粘贴以下内容

# 版本号
version: "1.0"
services:
  # mysql 服务
  mysqlserver:
    # 服务名称
    container_name: mysqlserver
    # 镜像
    image: mysql:5.7.17
    build:
      context: .
      dockerfile: Dockerfile_mysql
    # 端口
    ports:
      - "3306:3306"
    # 执行多条命令
    command: [
      'mysqld',
      '--innodb-buffer-pool-size=20M',
      '--character-set-server=utf8',
      '--collation-server=utf8_general_ci',
      '--default-time-zone=+8:00',
      '--lower-case-table-names=1'
    ]
    environment:
      # 数据库
      MYSQL_DATABASE: demo
      # 登录名
      MYSQL_ROOT_USER: root
      # 密码
      MYSQL_ROOT_PASSWORD: 123456
  # web 服务
  webserver:
    container_name: webserver
    build:
      context: .
      dockerfile: Dockerfile_web
    image: webserver
    # 依赖 redis 和 mysql
    depends_on:
      - redis
      - mysqlserver
    ports:
      - "8888:8888"
  # redis 服务
  redis:
    container_name: redis
    image: "library/redis:alpine"

该 Compose 文件定义了三个服务:web 、mysql 和 redis。

  • web:该 web 服务使用从 Dockerfile 当前目录中构建的镜像。然后,它将容器和主机绑定到暴露的端口 8888。
  • mysql:该 mysql 服务使用 Docker Hub 的公共 mysql 映像
  • redis:该 redis 服务使用 Docker Hub 的公共 Redis 映像。

# 使用 Compose 命令构建和运行您的应用

在 springboot 目录中,执行以下命令来启动应用程序:

docker-compose up

如果你想在后台执行该服务可以加上 -d 参数

docker-compose up -d

停止

docker-compose down

问题:如果出现 Error response from daemon: Failed to Setup IP tables: Unable to enable SKIP DNAT rule: ...... 则说明可能是在 docker 服务启动之后,再执行关闭系统防火墙的操作,那后续执行启动 docker 容器(docker-compose up -d)或者创建 docker 网络(docker create network),就会出现这样的报错。

解决方案:重启 docker 服务

systemctl restart docker

# 访问

访问地址

http://IP:8888/get

页面出现 SpringBoot + Redis + MySQL 则成功。

http://Ip:8888/queryAll

页面返回对应的查询数据则成功。(注:构建好 mysql 时需把对应的数据表建上)

# yml 配置指令参考

# version

指定本 yml 依从的 compose 哪个版本制定的。

# build

指定为构建镜像上下文路径:

例如 webapp 服务,指定为从上下文路径 ./dir/Dockerfile 所构建的镜像:

version: "3.7"
services:
  webapp:
    build: ./dir

或者,作为具有在上下文指定的路径的对象,以及可选的 Dockerfile 和 args:

version: "3.7"
services:
  webapp:
    build:
      context: ./dir
      dockerfile: Dockerfile-alternate
      args:
        buildno: 1
      labels:
        - "com.example.description=Accounting webapp"
        - "com.example.department=Finance"
        - "com.example.label-with-empty-value"
      target: prod
  • context:上下文路径。
  • dockerfile:指定构建镜像的 Dockerfile 文件名。
  • args:添加构建参数,这是只能在构建过程中访问的环境变量。
  • labels:设置构建镜像的标签。
  • target:多层构建,可以指定构建哪一层。

# cap_add,cap_drop

添加或删除容器拥有的宿主机的内核功能。

cap_add:
  - ALL # 开启全部权限
cap_drop:
  - SYS_PTRACE # 关闭 ptrace 权限

# cgroup_parent

为容器指定父 cgroup 组,意味着将继承该组的资源限制。

cgroup_parent: m-executor-abcd

# command

覆盖容器启动的默认命令。

command: ["bundle", "exec", "thin", "-p", "3000"]

# container_name

指定自定义容器名称,而不是生成的默认名称。

container_name: my-web-container

# depends_on

设置依赖关系。

  • docker-compose up :以依赖性顺序启动服务。在以下示例中,先启动 db 和 redis ,才会启动 web。
  • docker-compose up SERVICE :自动包含 SERVICE 的依赖项。在以下示例中,docker-compose up web 还将创建并启动 db 和 redis。
  • docker-compose stop :按依赖关系顺序停止服务。在以下示例中,web 在 db 和 redis 之前停止。
version: "3.7"
services:
  web:
    build: .
    depends_on:
      - db
      - redis
  redis:
    image: redis
  db:
    image: postgres

注意:web 服务不会等待 redis db 完全启动 之后才启动。

# deploy

指定与服务的部署和运行有关的配置。只在 swarm 模式下才会有用。

version: "3.7"
services:
  redis:
    image: redis:alpine
    deploy:
      mode:replicated
      replicas: 6
      endpoint_mode: dnsrr
      labels: 
        description: "This redis service label"
      resources:
        limits:
          cpus: '0.50'
          memory: 50M
        reservations:
          cpus: '0.25'
          memory: 20M
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
        window: 120s

可以选参数:

endpoint_mode:访问集群服务的方式。

endpoint_mode: vip 
# Docker 集群服务一个对外的虚拟 ip。所有的请求都会通过这个虚拟 ip 到达集群服务内部的机器。
endpoint_mode: dnsrr
# DNS 轮询(DNSRR)。所有的请求会自动轮询获取到集群 ip 列表中的一个 ip 地址。

labels:在服务上设置标签。可以用容器上的 labels(跟 deploy 同级的配置) 覆盖 deploy 下的 labels。

mode:指定服务提供的模式。

  • replicated:复制服务,复制指定服务到集群的机器上。
  • global:全局服务,服务将部署至集群的每个节点。

replicas:mode 为 replicated 时,需要使用此参数配置具体运行的节点数量。

resources:配置服务器资源使用的限制,例如上例子,配置 redis 集群运行需要的 cpu 的百分比 和 内存的占用。避免占用资源过高出现异常。

restart_policy:配置如何在退出容器时重新启动容器。

  • condition:可选 none,on-failure 或者 any(默认值:any)。
  • delay:设置多久之后重启(默认值:0)。
  • max_attempts:尝试重新启动容器的次数,超出次数,则不再尝试(默认值:一直重试)。
  • window:设置容器重启超时时间(默认值:0)。

rollback_config:配置在更新失败的情况下应如何回滚服务。

  • parallelism:一次要回滚的容器数。如果设置为 0,则所有容器将同时回滚。
  • delay:每个容器组回滚之间等待的时间(默认为 0s)。
  • failure_action:如果回滚失败,该怎么办。其中一个 continue 或者 pause(默认 pause)。
  • monitor:每个容器更新后,持续观察是否失败了的时间 (ns|us|ms|s|m|h)(默认为 0s)。
  • max_failure_ratio:在回滚期间可以容忍的故障率(默认为 0)。
  • order:回滚期间的操作顺序。其中一个 stop-first(串行回滚),或者 start-first(并行回滚)(默认 stop-first )。

update_config:配置应如何更新服务,对于配置滚动更新很有用。

  • parallelism:一次更新的容器数。
  • delay:在更新一组容器之间等待的时间。
  • failure_action:如果更新失败,该怎么办。其中一个 continue,rollback 或者 pause (默认:pause)。
  • monitor:每个容器更新后,持续观察是否失败了的时间 (ns|us|ms|s|m|h)(默认为 0s)。
  • max_failure_ratio:在更新过程中可以容忍的故障率。
  • order:回滚期间的操作顺序。其中一个 stop-first(串行回滚),或者 start-first(并行回滚)(默认 stop-first)。

:仅支持 V3.4 及更高版本。

# devices

指定设备映射列表。

devices:
  - "/dev/ttyUSB0:/dev/ttyUSB0"

# dns

自定义 DNS 服务器,可以是单个值或列表的多个值。

dns: 8.8.8.8
dns:
  - 8.8.8.8
  - 9.9.9.9

自定义 DNS 搜索域。可以是单个值或列表。

dns_search: example.com
dns_search:
  - dc1.example.com
  - dc2.example.com

# entrypoint

覆盖容器默认的 entrypoint。

entrypoint: /code/entrypoint.sh

也可以是以下格式:

entrypoint:
    - php
    - -d
    - zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20100525/xdebug.so
    - -d
    - memory_limit=-1
    - vendor/bin/phpunit

# env_file

从文件添加环境变量。可以是单个值或列表的多个值。

env_file: .env

也可以是列表格式:

env_file:
  - ./common.env
  - ./apps/web.env
  - /opt/secrets.env

# environment

添加环境变量。您可以使用数组或字典、任何布尔值,布尔值需要用引号引起来,以确保 YML 解析器不会将其转换为 True 或 False。

environment:
  RACK_ENV: development
  SHOW: 'true'

# expose

暴露端口,但不映射到宿主机,只被连接的服务访问。

仅可以指定内部端口为参数:

expose:
 - "3000"
 - "8000"

# extra_hosts

添加主机名映射。类似 docker client --add-host。

extra_hosts:
 - "somehost:162.242.195.82"
 - "otherhost:50.31.209.229"

以上会在此服务的内部容器中 /etc/hosts 创建一个具有 ip 地址和主机名的映射关系:

162.242.195.82  somehost
50.31.209.229   otherhost

# healthcheck

用于检测 docker 服务是否健康运行。

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost"] # 设置检测程序
  interval: 1m30s # 设置检测间隔
  timeout: 10s # 设置检测超时时间
  retries: 3 # 设置重试次数
  start_period: 40s # 启动后,多少秒开始启动检测程序

# image

指定容器运行的镜像。以下格式都可以:

image: redis
image: ubuntu:14.04
image: tutum/influxdb
image: example-registry.com:4000/postgresql
image: a4bc65fd # 镜像 id

# logging

服务的日志记录配置。

driver:指定服务容器的日志记录驱动程序,默认值为 json-file。有以下三个选项

driver: "json-file"
driver: "syslog"
driver: "none"

仅在 json-file 驱动程序下,可以使用以下参数,限制日志得数量和大小。

logging:
  driver: json-file
  options:
    max-size: "200k" # 单个文件大小为 200k
    max-file: "10" # 最多 10 个文件

当达到文件限制上限,会自动删除旧得文件。

syslog 驱动程序下,可以使用 syslog-address 指定日志接收地址。

logging:
  driver: syslog
  options:
    syslog-address: "tcp://192.168.0.42:123"

# network_mode

设置网络模式。

network_mode: "bridge"
network_mode: "host"
network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"

networks

配置容器连接的网络,引用顶级 networks 下的条目 。

services:
  some-service:
    networks:
      some-network:
        aliases:
         - alias1
      other-network:
        aliases:
         - alias2
networks:
  some-network:
    # Use a custom driver
    driver: custom-driver-1
  other-network:
    # Use a custom driver which takes special options
    driver: custom-driver-2

aliases :同一网络上的其他容器可以使用服务名称或此别名来连接到对应容器的服务。

# restart

  • no:是默认的重启策略,在任何情况下都不会重启容器。
  • always:容器总是重新启动。
  • on-failure:在容器非正常退出时(退出状态非 0),才会重启容器。
  • unless-stopped:在容器退出时总是重启容器,但是不考虑在 Docker 守护进程启动时就已经停止了的容器
restart: "no"
restart: always
restart: on-failure
restart: unless-stopped

注:swarm 集群模式,请改用 restart_policy。

# secrets

存储敏感数据,例如密码:

version: "3.1"
services:
mysql:
  image: mysql
  environment:
    MYSQL_ROOT_PASSWORD_FILE: /run/secrets/my_secret
  secrets:
    - my_secret
secrets:
  my_secret:
    file: ./my_secret.txt

# security_opt

修改容器默认的 schema 标签。

security-opt:
  - label:user:USER   # 设置容器的用户标签
  - label:role:ROLE   # 设置容器的角色标签
  - label:type:TYPE   # 设置容器的安全策略标签
  - label:level:LEVEL  # 设置容器的安全等级标签

# stop_grace_period

指定在容器无法处理 SIGTERM (或者任何 stop_signal 的信号),等待多久后发送 SIGKILL 信号关闭容器。

stop_grace_period: 1s # 等待 1 秒
stop_grace_period: 1m30s # 等待 1 分 30 秒

默认的等待时间是 10 秒。

# stop_signal

设置停止容器的替代信号。默认情况下使用 SIGTERM 。

以下示例,使用 SIGUSR1 替代信号 SIGTERM 来停止容器。

stop_signal: SIGUSR1

# sysctls

设置容器中的内核参数,可以使用数组或字典格式。

sysctls:
  net.core.somaxconn: 1024
  net.ipv4.tcp_syncookies: 0
sysctls:
  - net.core.somaxconn=1024
  - net.ipv4.tcp_syncookies=0

# tmpfs

在容器内安装一个临时文件系统。可以是单个值或列表的多个值。

tmpfs: /run
tmpfs:
  - /run
  - /tmp

# ulimits

覆盖容器默认的 ulimit。

ulimits:
  nproc: 65535
  nofile:
    soft: 20000
    hard: 40000

# volumes

将主机的数据卷或着文件挂载到容器里。

version: "3.7"
services:
  db:
    image: postgres:latest
    volumes:
      - "/localhost/postgres.sock:/var/run/postgres/postgres.sock"
      - "/localhost/data:/var/lib/postgresql/data"

# Docker Machine

# 安装

# Linux 安装命令

base=https://github.com/docker/machine/releases/download/v0.16.0 &&
  curl -L $base/docker-machine-$(uname -s)-$(uname -m) >/tmp/docker-machine &&
  sudo mv /tmp/docker-machine /usr/local/bin/docker-machine &&
  chmod +x /usr/local/bin/docker-machine

# macOS 安装命令

base=https://github.com/docker/machine/releases/download/v0.16.0 &&
 curl -L $base/docker-machine-$(uname -s)-$(uname -m) >/usr/local/bin/docker-machine &&
 chmod +x /usr/local/bin/docker-machine

# Windows 安装命令

如果你是 Windows 平台,可以使用 Git BASH,并输入以下命令:

base=https://github.com/docker/machine/releases/download/v0.16.0 &&
 mkdir -p "$HOME/bin" &&
 curl -L $base/docker-machine-Windows-x86_64.exe > "$HOME/bin/docker-machine.exe" &&
 chmod +x "$HOME/bin/docker-machine.exe"

问题:如果出现 curl: (35) Encountered end of file,说明是服务器的 443 端口未打开,解决方案如下

# 开启防火墙
systemctl start firewalld
# 添加 443 端口访问
firewall-cmd --zone=public -add-port=443/tcp --premanent
# 重新加载让配置生效
firewall-cmd --reload
# 查看开启情况,返回 yes 说明已开启。
firewall-cmd --zone=public --query-port=443/tcp

查看是否安装成功

docker-machine version

# 使用

# 列出可用的机器

可以看到目前只有这里默认的 default 虚拟机。

docker-machine ls

# 创建机器

docker-machine create --driver virtualbox <机器名>
  • --driver:指定用来创建机器的驱动类型,这里是 virtualbox。

问题:如果出现 Error with pre-create check: “VBoxManage not found. Make sure VirtualBox is installed and VBoxManage is in the path”

解决:在 /etc/yum.repos.d/ 目录下新建 virtualbox.repo 并写入如下内容

vim /etc/yum.repos.d/virtualbox.repo
[virtualbox]
name=Oracle Linux / RHEL / CentOS-$releasever / $basearch - VirtualBox
baseurl=http://download.virtualbox.org/virtualbox/rpm/el/$releasever/$basearch
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://www.virtualbox.org/download/oracle_vbox.asc

更新 yum 缓存

yum clean all
yum makecache

搜索 virtualbox 并安装对应版本

yum search virtualbox
yum install virtualbox-7.0

搜索virtualbox

问题:如果出现 Error with pre-create check: "This computer doesn't have VT-X/AMD-v enabled. Enabling it in the BIOS is mandatory"

解决:添加 --virtualbox-no-vtx-check 参数可以禁止 vtx 检查

问题:下载过慢

解决--virtualbox-boot2docker-url 可以指定本地镜像

最终命令如下

docker-machine create --driver virtualbox --virtualbox-no-vtx-check --virtualbox-boot2docker-url=/home/machine/boot2docker.iso test

# 查看机器的 ip

docker-machine ip <机器名>

# 停止机器

docker-machine stop <机器名>

# 启动机器

docker-machine start <机器名>

# 进入机器

docker-machine ssh <机器名>

# 命令参数说明

  • docker-machine active:查看当前激活状态的 Docker 主机。
  • config:查看当前激活状态 Docker 主机的连接信息。
  • create:创建 Docker 主机
  • env:显示连接到某个主机需要的环境变量
  • inspect: 以 json 格式输出指定 Docker 的详细信息
  • ip: 获取指定 Docker 主机的地址
  • kill: 直接杀死指定的 Docker 主机
  • ls: 列出所有的管理主机
  • provision: 重新配置指定主机
  • regenerate-certs: 为某个主机重新生成 TLS 信息
  • restart: 重启指定的主机
  • rm: 删除某台 Docker 主机,对应的虚拟机也会被删除
  • ssh: 通过 SSH 连接到主机上,执行命令
  • scp: 在 Docker 主机之间以及 Docker 主机和本地主机之间通过 scp 远程复制数据
  • mount: 使用 SSHFS 从计算机装载或卸载目录
  • start: 启动一个指定的 Docker 主机,如果对象是个虚拟机,该虚拟机将被启动
  • status: 获取指定 Docker 主机的状态 (包括:Running、Paused、Saved、Stopped、Stopping、Starting、Error) 等
  • stop: 停止一个指定的 Docker 主机
  • upgrade: 将一个指定主机的 Docker 版本更新为最新
  • url: 获取指定 Docker 主机的监听 URL
  • version: 显示 Docker Machine 的版本或者主机 Docker 版本
  • help: 显示帮助信息

# Swarm 集群管理

Docker Swarm 是 Docker 的集群管理工具。它将 Docker 主机池转变为单个虚拟 Docker 主机。 Docker Swarm 提供了标准的 Docker API,所有任何已经与 Docker 守护程序通信的工具都可以使用 Swarm 轻松地扩展到多个主机。

# 使用

# 创建 swarm 集群管理节点(manager)

创建 docker 机器

docker-machine create -d virtualbox swarm-manager

初始化 swarm 集群,进行初始化的这台机器,就是集群的管理节点。

docker-machine ssh swarm-manager
docker swarm init --advertise-addr IP #这里的 IP 为创建机器时分配的 ip。

以下输出,证明已经初始化成功。需要把以下这行复制出来,在增加工作节点时会用到

docker swarm join --token xxx IP:端口号

# 创建 swarm 集群工作节点(worker)

这里直接创建好俩台机器,swarm-worker1 和 swarm-worker2 。

docker-machine create -d virtualbox swarm-worker1
docker-machine create -d virtualbox swarm-worker2

分别进入两个机器里,指定添加至上一步中创建的集群,这里会用到上一步复制的内容。

docker-machine ssh swarm-worker1
docker swarm join --token xxx IP:端口号

# 查看集群信息

进入管理节点,执行:docker info 可以查看当前集群的信息。

docker info

# 部署服务到集群中

注意:跟集群管理有关的任何操作,都是在管理节点上操作的。

以下例子,在一个工作节点上创建一个名为 helloworld 的服务,这里是随机指派给一个工作节点:

docker service create --replicas 1 --name helloworld alpine ping docker.com

# 查看服务部署情况

查看 helloworld 服务运行在哪个节点上,可以看到目前是在 swarm-worker1 节点

docker service ps helloworld

查看 helloworld 部署的具体信息

docker service inspect --pretty helloworld

# 扩展集群服务

我们将上述的 helloworld 服务扩展到俩个节点。

docker service scale helloworld=2

# 删除服务

docker service rm helloworld

# 滚动升级服务

以下实例,我们将介绍 redis 版本如何滚动升级至更高版本。

创建一个 3.0.6 版本的 redis。

docker service create --replicas 1 --name redis --update-delay 10s redis:3.0.6

滚动升级 redis 。

docker service update --image redis:3.0.7 redis

# 停止某个节点接收新的任务

查看所有的节点

docker node ls

可以看到目前所有的节点都是 Active, 可以接收新的任务分配。

停止节点 swarm-worker1

docker node update --availability drain swam-worker1

注意:swarm-worker1 状态变为 Drain。不会影响到集群的服务,只是 swarm-worker1 节点不再接收新的任务,集群的负载能力有所下降。

可以通过以下命令重新激活节点

docker node update --availability active swarm-worker1

文章来源:https://www.runoob.com/docker/docker-tutorial.html

更新于

请我喝[茶]~( ̄▽ ̄)~*

七音 微信支付

微信支付

七音 支付宝

支付宝