Docker小记

Docker概览

运维视角

Docker安装:

  1. 先删除以前安装的docker:
yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
  1. 添加yum相关工具:
yum install -y yum-utils
  1. 添加阿里yum库:
yum-config-manager \
    --add-repo \
    http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
  1. 安装:
yum install docker-ce docker-ce-cli containerd.io
  1. 启动:systemctl start docker
  2. 设置开机启动:systemcetl enable docker
  3. 添加国内镜像库服务,修改配置文件(没有的话新建)/etc/docker/daemon.json,然后重启docker:
{
    "registry-mirrors": ["https://xxxxx.mirror.aliyuncs.com"]
}

在安装docker时,会涉及两个主要组件:docker客户端和docker daemon(docker引擎或docker服务端)。默认情况下,客户端与daemon通过本地套接字通信(/var/run/docker.sock),或者网络通信,docker daemon默认会监听2375或2376端口(TLS)。由于docker命令需要root权限,所以可以将用户添加到安装docker时自动创建的docker组里:sudo usermod -aG docker [username]

镜像

可以将docker镜像粗略理解为一个包含os文件系统和应用的对象。
查看镜像:docker image ls
拉取镜像:docker pull ubuntu:latest
启动容器:docker run -it ubuntu:latest /bin/bash-it表示开启容器的交互模式,将当前Shell连接到容器终端。/bin/bash表示用户想在docker里运行bash进程,实际上就是后文要讲的runc组件启动的程序,也是容器里当前唯一的进程(大部分容器只会运行一个进程)。容器随其中运行的应用关闭而终止,在这里就是bash退出后容器就停止了。容器相关命令还有:docker container start|stop|rm [container name|container ID]
ctrl-PQ组合键可以在退出容器的同时还保持容器的运行,再执行docker container exec -it [container ID] /bin/bash会让容器再运行一个bash并连接上,此时再用exit退出容器里的bash并不会停止容器,因为容器里还有一个bash。
查看运行中的容器:docker container ls
查看所有容器,包括已停止的:docker container ls -a
连接到运行中的容器:docker container exec -it mycontainer /bin/bash

开发视角

从开发者的视角来看,运行的容器就是应用进程,换句话说就是容器化的进程,一个属于特殊命名空间的应用进程。

构建镜像

将应用容器化,应用文件目录如下:


应用文件.PNG

可以看出在项目文件目录里有一个Dockerfile的文件,内容是:

FROM alpine
LABEL maintainer="nigelpoulton@hotmail.com"
RUN apk add --update nodejs nodejs-npm
COPY . /src
WORKDIR /src
RUN npm install
EXPOSE 8080
ENTRYPOINT ["node", "./app.js"]

跳转到项目目录里,然后根据Dockerfile构建名为test:latest的镜像:docker image build -t test:latest .
启动容器:docker container run -d --name web1 --publish 8080:8080 test:latest

Docker引擎

Docker引擎采用的是模块化设计,其组件是可以替换的。


Docker引擎架构.PNG

daemon的功能主要有镜像管理、镜像构建、与Docker client的交互、身份验证、安全特性、卷、核心网络以及编排。
runc是一个命令行工具,它只有一个作用:创建容器。
shim是一个实现容器与daemon解耦的工具,containerd每启动一个容器都会fork一个runc,不过一旦容器启动完毕,runc就会退出,一旦runc退出,对应的shim进程就会成为容器的父进程,其主要职责是保持STDIN和STDOUT流是开启状态,避免daemon重启时导致容器关闭,以及将容器的退出状态返回给daemon。
containerd是一个单独的守护进程,它的主要任务是容器的生命周期的管理——start|stop|pause|rm...
containerd还可完成一些诸如push和pull镜像的操作,但这些操作都是模块化可选的。
上面的daemon、containerd、shim、runc在Linux系统中均是以二进制文件形式存在,在宿主机通过ps命令均可以查看到对应的进程。


容器的启动过程.PNG
容器启动流程图.PNG

Docker镜像

镜像其实就是多个只读层文件的叠加。而容器则是在此基础上增加了一个读写层,并且在容器运行时,会映射出一个完整的叠加后的文件目录在对应容器的merged目录下。因为容器的运行依赖它下面的只读层,所以删除镜像前必须先删除以此镜像为基础的容器(哪怕是已经停止的容器),否则无法删除该镜像。删除镜像命令:docker image rm [image ID]|[image tag],删除全部镜像:docker image rm $(docker image ls -q) -f。镜像文件通常位于/var/lib/docker/overlay2/
镜像通常都比较小,镜像里并不包含内核——容器都是共用宿主机的内核。所以说容器仅包含必要的操作系统(通常指的是操作系统文件和文件系统对象)
拉取镜像:docker image pull ubuntu:latest
镜像仓库服务:

镜像仓库服务.PNG

docker客户端连接的镜像仓库服务是可配置的,默认值Docker Hub。在Docker Hub里还分官方仓库和第三方仓库。


从Docker Hub拉取官方镜像.PNG
从Docker Hub拉取非官方镜像.PNG
拉取其它镜像仓库服务里的镜像.PNG

一个镜像可以拥有多个标签。 docker image ls --filter dangling=false 可用于过滤没有标签的镜像(如果新镜像的标签和旧镜像的标签冲突,则会移除旧镜像的标签)。docker image prune可用于移除全部的悬虚(没有标签)镜像,如果再带上-a则还会移除所有没有被任何容器使用的镜像。

Docker支持的镜像过滤.PNG

docker search [NAME]用于搜索镜像。NAME字段可以是仓库名、你的Docker ID或者非官方仓库的组织名称。docker search [NAME] --filter "is-official=true"可以只返回官方仓库。默认情况下docker search只返回25行结果,可以通过--limit来指定返回行数,最多100行。
查看镜像分层:docker image inspect ubuntu:latest
所有的Docker镜像都始于一个基础镜像,当增加内容时,就会在当前镜像的基础上新增一层镜像。

新增文件增加镜像层.PNG

更新文件增加镜像层.PNG
镜像层合并.PNG

容器运行时,镜像层会合并在对应容器的merged目录下,容器停止后,merged目录会消失,但新增或修改的内容会存在diff目录下。
不同镜像还会共享可读镜像层。
拉取指定摘要的镜像:

docker image pull nginx@sha256:aeade65e99e5d5e7ce162833636f692354c227ff438556e5f3ed0335b7cc2f1b

显示镜像的摘要:docker image ls --digests nginx

镜像和镜像层.PNG

多架构镜像.PNG

Docker容器

Docker容器重启策略:
除非运行中的容器被明确要求停止(如docker container stop),否则一直尝试重启:docker container run --name neverdie -it --restart always ubuntu /bin/bash。不过always策略会使停止的容器在daemon重启时被启动,而unless-stoped策略正好相反。on-failure策略会在容器退出但返回不是0的情况下重启,daemon重启时,这种策略下的停止容器也会重启。
删除所有容器:docker container rm $(docker container ls -aq) -f
docker container inspect [container name|container ID]可以显示容器的配置细节和运行时信息。

应用容器化

应用容器化步骤.PNG

接下来详细说明下应用容器化的流程,项目的目录结构如下,这是一个简单的node.js应用:


项目目录.PNG

对于Docker来说,项目目录通常称为构建上下文,而Dockfile文件一般放在项目的根目录下。

项目目录里有个Dockfile文件,里面的内容如下:

FROM alpine
LABEL maintainer="nigelpoulton@hotmail.com"
RUN apk add --update nodejs nodejs-npm
COPY . /src
WORKDIR /src
RUN npm install
EXPOSE 8080
ENTRYPOINT ["node", "./app.js"]

Dockerfile文件主要有这样几个主要任务:配置应用运行所需的环境、将应用代码拷入镜像中、配置应用启动方式,最后指导Docker将这些信息进行容器化,也就是生成一个完整镜像。接下来逐行分析Dockfile文件里的每行命令:

  • FROM alpine:表示以alpine作为基础镜像,后续命令若有新增或修改内容则会新增镜像在基础镜像之上。
  • LABEL maintainer="nigelpoulton@hotmail.com":为镜像添加一个键值对元数据(镜像本身是一个配置对象),不会增加新的镜像层。
  • RUN apk add --update nodejs nodejs-npm:运行alpine系统里的包管理器来安装nodejs和npm,并在基础镜像层之上新建一个镜像层来存储这些程序。实际上在这里会先将基础镜像层运行起来,然后在运行的容器里使用apk来安装nodejs和npm,最后commit生成一个新镜像层并删除临时容器。
  • COPY . /src:生成一个新镜像,将当前目录下的构建上下文拷贝到alpine系统里的/src目录下。
  • WORKDIR /src:将alpine里的/src目录作为Dockfile文件里后续还未执行的命令的工作目录,这不会新增镜像层。
  • RUN npm install:在当前工作目录运行npm install命令,并新增镜像层。
  • EXPOSE 8080:仅表示要暴露的端口,无其它作用,作为元数据存在镜像配置里,不会新增镜像层。
  • ENTRYPOINT ["node", "./app.js"]:指定容器启动时默认启动的程序,同样作为元数据,不会新增镜像层。

最后的镜像层组成如下:


镜像层组成.PNG

最后进行应用容器化(生成镜像):docker image build -t web:latest .

推送镜像到镜像仓库服务

在推送镜像前,Docker需要3个关于镜像的信息,分别是镜像仓库服务、镜像仓库、镜像标签:


目的仓库.PNG

镜像仓库服务和镜像标签有默认值,可以不用指定。但由于我们没有官方仓库的访问权限,所以往往我们需要推送到以自己Docker ID命名的二级命名空间下,所以在推送前要给镜像添加一个新仓库名:docker image tag web:latest mydockerid/web:latest。然后再推送:docker image push mydockerid/web:latest
docker image history命令可以用来查看构建该镜像执行了哪些命令。

多阶段构建

多阶段构建.PNG

多阶段构建,简单来讲就是在一个Dockfile文件里有多个构建阶段,每个阶段都会构建自己的镜像,然后在构建最后一个阶段时,会直接从前面已构建好的镜像里拷贝所需文件,从而避免在最后的应用镜像里有过多不必要的文件,如包依赖等。


多阶段构建生成的镜像.PNG

利用构建缓存:


利用构建缓存.PNG

合并镜像:
docker image build --squash
合并镜像层不好的一点是它里面的镜像层不能再分享,并且在push或pull时操作的镜像体积更大。但如果镜像层太多,合并还是一个不错的选择。

合并镜像.PNG

Docker Compose

安装Docker Compose:

  1. 下载二进制文件:
curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
  1. 添加可执行权限:
chmod +x /usr/local/bin/docker-compose

Docker Compose可以用来管理和部署一个多服务(容器)应用。Docker Compose使用YAML文件来定义多服务应用,也可以使用JSON。Docker Compose默认使用文件名docker-compose.yml。
下面是一个简单的Compose文件示例,它定义了一个包含两个服务(web-fe和redis)的小型Flask应用。这是一个能够对访问者进行计数并将其保存到Redis的简单的Web应用:

#必须以此开头,它指定了该Compose文件的版本格式
version: "3.5"
#若干服务
services:
    #定义名叫web-fe的服务
    web-fe:
        #指定构建镜像的上下文路径,在这里就是指引Docker基于当前目录下的上下文和Dockfile来构建一个镜像
        build: .
        #指定容器运行时要运行的程序,其实也可以不在这里指定
        command: python app.py
        #指定端口映射,target是容器内端口,published是主机端口
        ports:
            - target: 5000
              published: 5000
        #指定连接的网络
        networks:
            - counter-net
        #将counter-vol卷挂载到容器内的/code目录下
        volumes:
            - type: volume
              source: counter-vol
              target: /code
    #定义名叫redis的服务
    redis:
        #让Docker基于镜像redis:alpine启动一个容器
        image: "redis:alpine"
        #让redis容器连接到counter-net网络
        networks:
            counter-net:
#指引Docker创建新的网络,默认情况下会创建bridge网络。也可以常见其它网络:
#                           networks:
#                               other-net:
#                                   driver: overlay
#                                   attachable: true
networks:
    counte-net:
#指引Docker创建新的卷
volumes:
    counter-vol:

然后跳转到Compose服务的项目目录下,在这个例子中就是web-fe项目目录下,假设目录名为counter-app,开始部署:docker-compose up -d这个命令会先创建网络和卷,然后构建所需镜像,并启动容器。-d表示后台运行compose。还有这个命令会默认在当前目录查找docker-compose.yml文件,你也可以用-f命令指定文件。
需要一提的是,在docker compose为services里的每个服务部署容器时,还会使用对应的key作为容器名字的一部分,例如:

docker compose容器命名.PNG

实际上,Docker Compose会将项目名(counter-app)作为compose文件里所有资源名的前缀。


docker compose资源命名.PNG

Docker Compose管理应用

docker-compose down命令会先关闭应用和相关容器并删除容器,然后删除网络。但docker-compose up过程中拉取和构建的镜像不会删除,卷也不会删除。
docker-compose ps可以查看应用相关服务的状态。
docker-compose top

docker-compose top.PNG

docker-compose stop会停止应用,但不会删除资源。对于已停止的应用,可以用docker-compose rm来删除容器和网络,也不会删除镜像和卷。
docker-compose restart用于重启,如果用户在停止应用后对compose文件进行了修改,那么重启不会使这些修改生效,只能重新部署。
docker volume inspect [volume name] | grep Mount可用于查看卷在Docker主机的什么位置,改变这里的内容会实时反应在运行中的容器里。

Docker Swarm

Docker Swarm主要包含两个方面:一个是企业级Docker安全集群,Swarm可以将一个或多个Docker节点(docker daemon)组织起来,使得用户能够以集群方式管理它们,用户可以自如地添加或删除节点;另一个是微服务应用的编排,Swarm提供了一套丰富的API用来部署和管理微服务应用,通过将应用定义在声明式配置文件中,就可以使用原生的Docker命令完成部署,还支持滚动升级、回滚以及扩容操作。
从集群的交读来说,一个Swarm由一个或多个Docker节点组成,节点会被配置为管理节点和工作节点。Swarm的配置和状态信息保存在etcd里,它作为Swarm的一部分被安装。同时,在集群里Swarm使用TLS进行通信加密、节点认证和角色授权以及自动密钥轮换。
对于应用编排,Swarm中的最小调度单位是服务,是一个基于容器的更高层次的概念,当容器被封装在一个服务中时,我们称之为一个任务或一个副本,一个服务也具有扩缩容、滚动升级以及简单回滚等特性。


Swarm概括.PNG

Swarm集群示例:
Swarm集群里的节点情况如下:

Swarm集群.PNG

每个节点都需要安装Docker,并且能够与Swarm的其它节点通信。不包含在任何Swarm中的Docker节点称为运行于单引擎模式,而一旦被加入Swarm集群,则称为Swarm模式。在安装Docker时,需要在路由器和防火墙中开放如下端口:


Docker节点开放端口.PNG

满足以上前提后,就可以着手开始搭建Swarm集群了:
在单引擎模式下的Docker主机上运行docker swarm init会将其切换到Swarm模式,并创建一个新的Swarm,将自身设置为Swarm的第一个管理节点。其它节点则可以作为管理节点或工作节点加入进来,这一操作也会将新加入的节点切换为Swarm模式。

  1. 登录到mgr1并初始化一个新的Swarm。
docker swarm init --advertise-addr 10.0.0.1:2377 --listen-addr 10.0.0.1:2377

--advertise-addr指定其它节点用来连接到当前节点的IP和端口,如果你的机器只有一个 IP 地址,可以省略,docker 会自动选择正确的 IP。当节点上有多个IP时,可以用于指定使用哪个IP。此外,还可以指定一个节点上没有的IP,比如一个负载均衡的IP。
--listen-addr指定用于承载Swarm流量的IP和端口。其设置通常与--advertise-addr相匹配,但是当节点上有多个IP的时候,可用于指定具体某个IP。并且,如果--advertise-addr设置了一个远程IP地址(如负载均衡的IP地址),该属性也是需要设置的。


Swarm常用端口.PNG
  1. 查看Swarm当前节点。


    Swarm第一个节点.PNG
  2. 在mgr1上执行docker swarm join-token命令来获取添加新的工作节点和管理节点到Swarm的命令和Token。

    加入Swarm.PNG

  3. 登录wrk1,并使用包含工作节点接入Token的docker swarm join命令将其接入Swarm。

    加入一个工作节点.PNG

  4. 在wrk2和wrk3上重复上一步骤来将这两个节点作为工作节点加入Swarm。

  5. 在mgr2作为管理节点接入Swarm。


    管理节点接入.PNG
  6. 在mgr3重复上一个操作。

  7. 在任意一个管理节点上执行docker node ls命令列出Swarm节点。

    查看Swarm节点.PNG

管理节点HA:

管理节点HA.PNG

内置的Swarm安全机制:
Swarm集群内置有繁多的安全机制,并提供了开箱即用的合理默认配置——如CA设置、接入Token、公用TLS、加密集群存储、加密网络、加密节点ID等。
锁定Swarm:

锁定Swarm.PNG

重启节点加入Swarm.PNG

Swarm服务

例如我们要部署有5个实例的某web应用,先登录到主管理节点,然后使用命令docker service create

创建Swarm服务.PNG

上图可以看出,其参数与docker container run有很多相同的。使用该命令后,主管理节点会在Swarm集群中实例化5个副本——请注意管理节点也会作为工作节点运行。相关各工作节点或管理节点会拉取镜像,然后启动相应容器。
docker service ls用于查看Swarm中所有运行中的服务。docker service ps [service name|service ID]用于查看服务副本列表及各副本的状态。
docker service inspect --pretty [service name|service ID]用于查看更详细的信息。
副本模式和全局模式:
副本模式会部署期望数量的服务副本,并尽可能均匀地将各个副本分布在整个集群中。而全局模式下每个节点上仅运行一个副本。默认是副本模式,可以通过给docker service create命令传--mode global参数来部署一个全局服务。
服务的扩缩容:
docker service scale用于对服务进行扩缩容。

扩缩容.PNG

删除服务:
docker service rm [service name|service ID]

滚动升级:
登录主管理节点,执行docker network create -d overlay uber-net,该命令会创建一个名为uber-net的覆盖网络。再执行docker service create --name uber-svc --network uber-net -p 80:80 --replicas 12 nigelpoulton/tu-demo:v1该命令会创建一个新的服务,使用v1镜像,并将其接入uber-net网络。
对与Swarm的网络,默认是入站模式,该模式下即使节点上没有服务的副本也会开放对应端口;此外还有主机模式,仅在运行有容器副本的节点上开放端口。下面的命令是以主机模式创建服务:docker service create --name uber-svc --network uber-net --publish published=80,target=80,mode=host --replicas 12 nigelpoulton/tu-demo:v1。在入站模式下,即使某个节点上并没有运行服务的副本,依然可以进行访问——所有节点都配置有映射,因此会将请求转发给运行有服务副本的节点
docker service update --image nigelpoulton/tu-demo:v2 --update-parallelism 2 --update-delay 20s uber-svc该命令会对uber-svc进行升级,每次更新两个副本,并且间隔20s,使用新镜像v2。
查看日志:
docker service logs [service name|service ID]

Docker网络

Docker的网络的部分都是由Libnetwork实现,它是一个独立于docker daemon的库,是CNM设计规范的实现。


CNM设计.PNG

单机桥接网络:
docker network create -d bridge会调用Libnetwork内置的网桥驱动去创建一个虚拟网桥(Docker有个默认网桥,映射在主机上的docker0),当Docker运行一个容器时,会调用Libnetwork去创建一对veth虚拟网卡,然后将这对虚拟网卡的一个放在容器里(也就是对应的网络命名空间),一个放在虚拟网桥上。以上这些是我的分析,可能不正确。
Linux上默认的Bridge网络是不支持通过Docker DNS服务进行域名解析的,而自定义桥接网络可以。

macvlan:

macvlan.PNG

查看daemon日志:

查看daemon日志.PNG

修改daemon日志级别.PNG

查看容器日志:

容器日志.PNG

服务发现:

docker DNS.PNG

Ingress网络:

Swarm发布模式.PNG

Docker网络命令总结:

Docker网络命令.PNG

Docker覆盖网络

创建一个覆盖网络十分容易:

  1. 创建一个Swarm集群;
  2. 登录主管理节点,然后创建一个overlay网络,此时其它节点是看不到这个网络的,并且网络的控制层已是加密,带上-o encrypted还可以对数据层加密;
  3. 创建一个服务,此时所有节点都会自动连接到这个overlay网络,并可以通过容器名或ip地址相互ping通。

Docker卷

Docker卷.PNG

docker container run --mount source=[volume name],target=/vol [image name]创建一个容器,并挂在一个卷(没有的话自动新建)到容器里的/vol目录下。Swarm模式下创建服务时也可以带上--mount

Docker卷命令.PNG

捕获.PNG

Docker Stack

用Docker Stack来部署总体来说比较容易,简单来说就是用Compose(也称Stack文件)文件定义应用,然后通过docker stack deploy命令完成部署管理。
下面以一个简单的应用举例说明:


Docker Stack应用.PNG

最重要的就是项目里的Stack文件,这里先简单写下这个文件:

version: "3.2"
services:
    reverse_proxy:
        image: dockersamples/atseasampleshopapp_reverse_proxy
        ports:
            - "80:80"
            - "443:443"
        secrets:
            - source: revprox_cert
              target: revprox_cert
            - source: revprox_key
              target: revprox_key
        networks:
            - front-tier
    database:
        image: dockersamples/atsea_db
        environment:
            POSTGRES_USER: gordonuser
            POSTGRES_DB_PASSWORD_FILE: /run/secrets/postgres_password
            POSTGRES_DB: atsea
        networks:
            - back-tier
        secrets:
            - postgres_password
        deploy:
            placement:
                constraints:
                    - 'node.role == worker'
    appserver:
        image: dockersample/atsea_app
        networks:
            - fron-tier
            - back-tier
            - payment
        deploy:
            replicas: 2
            update_config:
                parallelism: 2
                failure_action: rollback
            placement:
                constraints:
                - 'node.role == worker'
            restart_policy:
                condition: on-failure
                delay: 5s
                max_attempts: 3
                window: 120s
            secrets:
                - postgres_password
    visualizer:
        image: dockersample/visualizer:stable
        ports:
            - "8001:8080"
        stop_grace_period: 1m30s
        volumes:
            - "var/run/docker.sock:/var/run/docker/sock"
        deploy:
            update_config:
                failure_action: rollback
            placement:
                constraints:
                    - 'node.role == manager'
    payment_gateway:
        image: dockersamples/atseasampleshopapp_payment_gateway
        secrets:
            - source: staging_token
              target: payment_token
         networks:
             - payment
         deploy:
             update_config:
                 failure_action: rollback
             placement:
                 constraints:
                     - 'node.role == worker'
                     - 'node.labels.pcidss == yes'
networks:
    front-tier:
    back-tier:
    payment:
        driver: overlay
        driver_opts:
            encrypted: 'yes'
secrets:
    postgres_password:
        external: true
    staging_token:
        external: true
    revprox_key:
        external: true
    revprox_cert:
        external: true

可以看出上面的Stack文件有4个顶级key,接下来详细分析每个顶级key:
networks
可以看出上面定义了3个网络,默认情况下,这些网络都会采用overlay驱动。payment网络较为特殊,它增加了数据层加密的功能,也可以在docker network create命令中指定-o encrypted参数来实现数据层加密。
secrets
注意到4个密钥都被定义为external,这意味着在Stack部署之前,这些密钥必须存在。
services
image关键字是服务里唯一必选项,Docker Stack和Docker Compose的一个区别是Stack不支持构建,这意味着在部署Stack之前,所有镜像必须是提前构建好的。仓库服务名是可选的,默认会从Docker Hub拉取。
默认情况下,所有端口映射都采用Ingress模式,这意味着Swarm集群中每个节点的对应端口都会映射并且是可访问的,即使是那些没有运行副本的节点。另一种方式是Host模式,端口只映射到运行副本的Starm节点,但是Host模式需要使用完整的配置:

ports:
    - target: 80
      published: 80
      mode: host

secrets关键字表面这个服务用来两个密钥,这两个密钥必须在顶级关键字secrets下定义了,并且必须在系统上已经存在。部署后,密钥以普通文件的形式被挂载到服务副本当中,文件的名称就是Stack文件中定义的target属性的值,其在Linux下的路径为/run/secrets,例如/run/secrets/revprox_cert和/run/secrets/revprox_key。还可以通过docker service create --sercret [secret name]暴露某个secret给某个服务。
networks关键字确保服务的所有副本都会连接到front-tier网络,网络相关定义必须位于顶级关键字networks之下,如果定义的网络不存在,Docker会以Overlay网络方式新建一个网络。
deploy关键字保证了当前服务只会运行在Swarm集群的worker节点之上。Swarm还支持以下约束:

部署约束.PNG

在appserver里,replicas关键字设置期望服务的副本数量为2,默认值为1。update_config定义了Docker在服务滚动升级的时候具体如何操作,在这个例子里,Docker每次会更新两个副本。failure_action规定了升级失败后自动回滚,failure_action的默认操作是pause,会在服务升级失败后阻止其它副本的升级,还支持continue操作。
restart-policy定义了Swarm针对容器异常退出的重启策略。在这个例子中,如果某个副本以非0返回值退出(conditon: onfailure),会立即重启当前副本,重启最多重试3次,每次都会等待至多120s来检测是否启动成功,每次重启的间隔是5s。
当docker要停止某个容器时,会给容器内部PID为1的进程发送SIGTERM信号,容器内PID为1的进程会有10s的时间来执行一些清理操作,如果进程没有处理该信号,那么10s后就会被SIGKILL信号强制结束。而stop_grace_period关键字可以修改这个10s时间。volumes关键字用于挂载提前创建的卷或者主机目录到某个服务副本当中,在本例中,会挂载Docker主机的/var/run/docker.sock目录到每个服务副本的/var/run/docker.sock路径,这意味着在服务副本中任何对/var/run/docker.sock的读写操作都会指向Docker主机的对应目录中。
/var/run/docker/docker.sock恰巧是Docker提供的IPC套接字,Docker daemon通过该套接字对其它进程暴露其API,这意味着给予了容器查询和管理daemon的能力。
在payment_gateway服务里多了个node.label约束,这是一个标签约束,可以通过docker node update命令来自定义标签,并添加到Swarm集群的指定节点,node.label配置只适用于Swarm集群中的节点,不能用于单独的容器。

部署Stack应用

在进行部署之前,有几个前置处理需要完成:

  • Swarm模式:应用将采用Docker Stack部署,而Stack依赖Swarm模式。
  • 标签:某个Swarm worker节点需要自定义标签
  • 密钥:应用所需的密钥需要在部署前创建完成


    示例环境.PNG

上图中给wrk-1节点添加标签可以在管理节点上执行一下命令:
docker node update --label-add key=value wrk-1
应用定义了4个密钥,这些都要在部署前创建好。在管理节点上运行下面的命令:
openssl req -newkey rsa:4096 -nodes -sha256 -keyout domain.key -x509 -days 365 -out domain.crt这个命令会创建一个证书和对应的私钥。
下面分别创建revprox_cert、revprox_key、postgree_password、stage_token:

docker secret create revprox_cert domain.crt
docker secret create revprox_key domain.key
docker secret create postgres_password domain.key
echo staging | docker secret create staging_token -

开始部署:
docker stack deploy -c docker-stack.yml seastack

Docker Stack部署.PNG

如果想查看具体某个服务的详细信息,可以使用docker service logs命令,需要将服务名称/ID或者副本ID作为参数传入。如果传入服务名称或ID,可以看到所有服务副本的日志信息,如果传入的是副本ID,只会看到对应副本的日志信息。

docker stack管理应用

虽然可以通过docker service scale命令来扩充某个服务的副本数,但这不是推荐的方式,最好是将Stack文件作为配置的唯一声明,然后重新执行docker stack deploy -c docker-stack.yml seastack即可,重新部署Stack并不会影响那些没有改动的服务。

Docker Stack命令.PNG

Docker安全

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容

  • 深入浅出Docker学习笔记 Docker引擎 Docker引擎:用来运行和管理容器的核心文件模块化(基于开放容器...
    yuq329阅读 769评论 0 4
  • docker概念 镜像与容器 docker镜像是一个统一文件系统,由一系列只读层堆叠而成。容器则是在只读层堆顶加上...
    羽色云烟阅读 649评论 0 0
  • 从Docker 1.11开始,Docker容器运行已经不是简单的通过Docker daemon来启动,而是集成了c...
    泛轻舟gen阅读 26,494评论 4 11
  • containerd是什么 containerd是容器技术标准化之后的产物,为了能够兼容OCI标准,将容器运行时及...
    裘马轻狂大帅阅读 3,195评论 0 3
  • 特别说明: 本人平时混迹于 B 站,不咋回复这里的评论,有问题可以到 B 站视频评论区留言找我视频地址: http...
    撸帝阅读 850评论 1 3