掘金 后端 ( ) • 2024-03-22 00:10

温馨提示:所有文章中所提及的Docker相关的案例的安装包和工具,都可以在我的网盘中直接下载并跟着实操:

链接:https://pan.baidu.com/s/1pgboR8O5DjZoZK9f1NvK9g

提取码:30in

13. Docker容器编排

编排功能,是复杂系统是否具有灵活可操作性的关键。特别在Docker应用场景中,编排意味着用户可以灵活地对各种容器资源实现定义和管理。例如:在基于微服务架构的应用系统一般都包含若干个微服务,每个微服务一般都会集群部署多个实例,如果每个微服务都要手动启动与停止,那么效率非常低、工作量也非常大。或是有一些微服务和应用之间有部署的先后关系,当前一个有依赖性的服务还没有完成部署时,另一个有依赖性的服务先完成了部署就会导致部署失败。那么使用 Docker Compose可以轻松、高效地管理和编排多个容器。

Docker Compose 作为Docker官方编排工具,其重要性不言而喻,它可以让用户通过编写一个简单的模板文件(yaml格式),然后使用一个命令即可创建并启动配置文件中所配置的所有服务,实现快速地创建和管理基于Docker容器的应用集群。

13.1 Docker-Compose安装

  1. 下载Compose二进制安装包(可以使用我们下载好的):

    下载地址:https://github.com/docker/compose/releases,我们下载Linux版本

    image-20230209094917383.png

  2. 上传这些二进制文件到执行路径到/usr/local/bin/目录下,并添加执行权限即可

    #进入/usr/local/bin目录
    cd /usr/local/bin
    ​
    #修改文件名字
    mv docker-compose-linux-x86_64 docker-compose
    ​
    #添加执行权
    chmod +x docker-compose
    
  3. 测试安装结果

    #打印docker-compose版本号
    docker-compose --version
    

    image-20230209110804601.png

13.2 Docker-Compose模板文件

模板文件是使用Compose的核心,涉及的指令也比较多,但大部分的指令与docker命令创建或启动容器时所填写的参数类似。默认的模板文件名称为docker-compose.yml,格式为YAML格式,目前最新的版本为v3

版本v1的Compose文件结构十分简单,每个顶级元素为服务名,次级元素为服务容器的配置信息,例如:

tomcat:
    image: my_tomcat:9
    ports:
        - "8080:8080"
    volumes:
        - "/mydata/tomcat"

版本v2和版本v3扩展了Compose的语法,同时尽量保持跟旧版本的兼容,除了可以声明网络和存储外,最大的不同一个是添加了版本信息,另一个是需要将所有的服务放到services元素下面,例如我们将上面的例子改为版本v3:

version:"3"
services:
    tomcat:
        image: my_tocamt:9
        ports:
            - "8080:8080"
        volumes:
            - "/mydata/tomcat"

注意:每个服务的编排都必须通过image指令指定镜像 或 build指令通过Dockerfile构建镜像,如果使用build指令,在Dockerfile中设置的一系列指令,例如CMD,EXPOSE都会自动被执行,无需再次设置

Compose模板文件常用指令列表参考如下表格内容:(这里只列出一些我认为很常用的)

指令 功能 image 指定镜像名或镜像id,如果镜像在本地不存在,会尝试去拉取这个镜像 ports 暴露容器的端口,可指定多个。 volumes 数据卷或数据目录的挂载设置,可指定多个 build 指定Dockerfile所在路径,会自动构建这个镜像,并使用这个镜像 container_name 指定容器名称,默认将会使用"项目名称服务名称序号"的格式,如果我们自己指定了容器名,该服务将无法进行集群扩展,因为Docker不允许多个容器实例名重复 command 覆盖容器启动后默认执行的命令 depends_on 指定多个服务之间的依赖关系,启动时,会先启动被依赖服务 dns 自定义DNS服务器,可以指定多个 dns_serach 配置DNS搜索域,可以指定多个 dockerfile 指定额外的编译镜像的Dockerfile文件,该指令不能跟image同时使用 entrypoint 覆盖容器中默认的入口命令,也会取消镜像中指定的入口命令和默认启动命令 pid 跟宿主机共享进程命名空间,打开该选项容器之间,以及容器额宿主机之间可以通过进程ID来互相访问和操作 expose 指定容器暴露的端口 extends 基于其他模板文件进行扩展,可以有多个yaml文件,他们之间可以有继承关系 restart 指定重启策略,可以为no(不重启),always(总是),on-failure(失败时),unless-stopped(停止时) ulimits 指定容器的限制值,例如,指定最大进程数 network_mode 设置网络模式,bridger、host、none、containner networks 指定加入的网络名 environment 设置环境变量

13.3 Docker-Compose命令

Docker-Compose的命令与docker命令极为相似, 用法上没有太大区别,其基本格式是docker-compose 命令 参数,下面列出一些常用命令:

查看帮助命令:

docker-compose --help

效验和查看Compose文件的配置信息

docker-compose config 

创建并启动容器

docker-compose up -d --scale 服务名=数字
d表示后台运行,scale是表示对应的服务同时启动几个容器

停止容器,但不删除

docker-compose stop

启动容器

docker-compose start

停止并删除容器

docker-compose down

13.4 Docker-Compose部署

我们以之前的SpirngBoot项目部署例子来进行改造实验,目前我们需要在同一个宿主机中实现的一个MySQL数据库和两个SpirngBoot程序的实例部署:

  1. 创建用于存储yml文件的目录

    #进入到/mydata目录
    cd /mydata
    
    #创建compose目录
    mkdir compose
    
  2. 编写docker-compose.yml文件

    #在/mydata/compose目录下编写
    vim docker-compose.yml
    
    version: "3"
    services:
        mysql:
            container_name: my_mysql
            image: mysql
            privileged: true
            restart: always
            volumes:
                - "/mydata/mysql/data:/var/lib/mysql"
                - "/mydata/mysql/conf:/etc/mysql/conf.d"
                - "/mydata/mysql/logs:/var/log/mysql"
            ports:
                - "3306:3306"
            expose:
                - "3306"
            environment: 
                - MYSQL_ROOT_PASSWORD=123456
            networks:
                - my_network
        springboot:
            image: springboot_jxc
            ports:
                - "80-81:80"
            depends_on:
                - mysql
            restart: always
            networks:
                - my_network
    networks:
        my_network:               
    

    以上配置文件注释版讲解:

    #指定yaml版本v3
    version: "3"
    #服务配置
    services:
        #第一个服务mysql
        mysql:
            #容器名,如果指定了,就不能部署多个容器
            container_name: my_mysql
            #镜像名
            image: mysql
            #为了防止出现Centos7安全Selinux禁止了一些安全权限
            privileged: true
            #自动重启容器
            restart: always
            #数据挂载
            volumes:
                - "/mydata/mysql/data:/var/lib/mysql"
                - "/mydata/mysql/conf:/etc/mysql/conf.d"
                - "/mydata/mysql/logs:/var/log/mysql"
            #映射端口
            ports:
                - "3306:3306"
            #暴露端口
            expose:
                - "3306"
            #环境配置
            environment: 
                - MYSQL_ROOT_PASSWORD=123456
            #加入的自定义网络
            networks:
                - my_network
        #第二个服务springboot
        springboot:
            #镜像名,我们之前自己通过Dockerfile制作的JXC项目的镜像
            image: springboot_jxc
            #映射端口,"80-81:80"这种写法会在启动多个实例的时候,自动为我们分配端口在80-81这个区间的容器映射
            ports:
                - "80-81:80"
            #依赖某个服务
            depends_on:
                - mysql
            #自动重启
            restart: always
            #加入的自定义网络
            networks:
                - my_network
    #自定义网络配置
    networks:
        #自定义网络名
        my_network:
    
  3. 启动服务

    #在/mydata/compose目录下执行
    docker-compose up -d --scale springboot=2
    ​
    -d:后台启动容器
    --scale:启动多个实例
    
  4. 进行访问测试

    在Windows浏览器中分别访问8081两个端口号的实例,访问如下地址,访问后如出现如下登录页面,则部署成功,登录账号:admin,登录密码:admin123

    http://192.168.177.128:80
    http://192.168.177.128:81
    

    image-20221221152141321.png

    image-20221221152149257.png

  5. 关闭服务,并删除容器

    #在/mydata/compose目录下执行
    docker-compose down
    

14. Docker容器管理

目前,已经有若干开源项目试图实现强大和便捷的Docker管理工具,包括Portainer、Panamax、Seagull等。本例,我们以Portainer为例为大家讲解如何安装使用Docker的容器管理工具。

Portainer是一个Docker官方推荐的轻量级的docker管理工具,它具有可视化ui界面,只需简单的TCP连接就能实现对Docker容器的全面管理和监控。官方网站为:https://portainer.io,该项目最早于2013年12月发起,主要基于HTML/JS语言实现。

14.1 Portainer安装

  1. 下载Portainer镜像

    #我们可以在Docker Hub中找到MySQL镜像
    https://hub.docker.com/r/portainer/portainer
    ​
    #拉取portainer镜像,默认拉取的版本是latest的
    docker pull portainer/portainer-ce
    
  2. 创建数据卷

    docker volume create portainer_data
    
  3. 启动容器

    docker run --name portainer -p 9000:9000 \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -v portainer_data:/data \
    -d portainer/portainer-ce
    ​
    #以上命令解析
    --name:容器的名称
    ​
    -p:端口映射
    ​
    -v:目录挂载
    -v /var/run/docker.sock:/var/run/docker.sock
    将宿主机的/var/run/docker.sock目录挂载到容器中的/var/run/docker.sock目录中(该目录是docker的套接字目录,主要就是发送指令给docker的守护进程的)
    -v portainer_data:/data
    将宿主机的portainer_data数据卷挂载到容器中的/data目录(这是portainer容器默认的数据目录)
    ​
    -d:后台启动
    
  4. 创建管理员账号

    容器启动完毕之后,我们可以在Windows浏览器中输入以下地址访问管理平台

    http://192.168.177.128:9000
    

    image-20230215103329369.png

    我们需要管理员账号的创建,如果5分钟不创建该账号,Portainner会出于安全考虑而自动关闭容器,常见完毕之后就会进入下面的页面,那么整个Portainer就安装完毕了

    image-20230215103507527.png

14.2 Portainer本地连接

Portainer安装完毕之后,我们就可以开始进行使用了,Portainer支持很多种管理和监控方式,这里我们以LocalRemote两种方式为例。Local指的是管理当前安装Portainer宿主机的Docker环境,而Remote指的是管理其他宿主机的Docker环境。

  1. 访问本地Docker

    选择Local ->点击Connect即可进行连接。

    image-20230215105514159.png

    连接后就会进入如下列表界面,该列表会显示出所有正处于Portainner管理的机器信息

    image-20230215105637693.png

  2. 管理本地Docker

    在列表中,点击local本地机器,就可以进入当前机器的管理页面,该页面可对当前选定机器的栈,容器,镜像,数据卷,网络进行管理

    image-20230215110132152.png

    image-20230215110258982.png

14.3 Portainer远程连接

Portainer连接其他机器需要使用tcp协议,端口号默认为2375。我们以192.168.177.129机器node2为例来进行演示

  1. 在node2机器中修改docker.service文件,开放2375端口

    #打开node2的docker.service文件
    vim /usr/lib/systemd/system/docker.service
    ​
    #找到ExecStart字段修改如下
    ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock
    ​
    #重启daemon
    systemctl daemon-reload
    ​
    #重启docker服务
    systemctl restart docker
    
  2. 添加远程机器管理

    回到Portainer页面,在左侧导航栏选择Endpoint,在打开的页面中选择Add endpoint选项

    image-20230215142040893.png

    在弹出页面中选择Docker,并填写机器名remote和机器地址192.168.177.129:2375,之后点击下方Add endpoint按钮进行添加

    image-20230215142317958.png

  3. 查看添加的远程机器

    添加完毕后,点击左侧导航栏选择Home,就可以看到如下页面,出现remote说明node2机器的Docker也被Portainner进行管理了

    image-20230215142528468.png

    点击remote机器就可以查看node2机器中Docker的栈,容器,镜像,数据卷,网络情况了,至此我们就完成了对远程Docker机器的连接

    image-20230215142804955.png

14.4 Portainner镜像管理

我们以本地node1上的Docker为例,演示Portainner对镜像的操作

  1. 进入镜像管理页面

    选择左侧导航栏的Home按钮,进入以下主机列表页面,然后选择local本地机器

    image-20230215160353080.png

    之后检查左侧导航栏Home下的机器是否正确切换到LOCAL字样,我们可以选择左侧导航栏的Images或是点击当前列表页中的Images图标进入镜像管理页面

    image-20230215160524103.png

    image-20230215160706761.png

  2. 单个镜像删除

    我们在镜像列表页选择需要删除的惊险,点击Remove即可进行删除,例如这里我们删除hello-world:latest,如下图所示

    image-20230216160435519.png

  3. 多个镜像删除

    如果我们需要删除的镜像包含多个tags标签,那么直接点解Remove删除按钮是不被允许的,例如我们这里的Tomcat镜像,有3个Tags,那么我们需要点击该镜像,进入到如下页面进行逐一删除

    image-20230216160616993.png

    image-20230216160648712.png

  4. 从DockerHub拉取镜像

    要拉取镜像,我需要在该页面的上方选择Registry仓库,填写要拉取的镜像,然后点击Pull the image拉取镜像

    image-20230216160921083.png

  5. 从私有仓库拉取镜像

    这里我们以阿里云为例,从私有仓库拉取镜像。找到左侧导航栏,选择Registrles,然后点击Add registry添加注册仓库

    image-20230216161703338.png

    登录自己的阿里云镜像仓库,地址https://cr.console.aliyun.com/cn-hangzhou/instances,找到自己的镜像仓库,查看自己仓库的信息

    image-20230216162642046.png

    回到Portainner页面,填写如下仓库信息,然后添加该仓库

    image-20230216163051663.png

    image-20230216163125786.png

    添加完自己的镜像仓库后,点击左侧导航栏选择images,在该页面的上方选择Registry仓库,填写要拉取的镜像,然后点击Pull the image拉取镜像

    image-20230216163534260.png

  6. 镜像的导出

    在镜像页面,选择需要导出的镜像,点击Export按钮,例如这里我们导出hello-world:latest,导出后浏览器会自动进行下载

    image-20230216164002998.png

  7. 镜像的导入

    我们把之前导出的镜像进行导入,再导入之前,先将hello-world:latest镜像手动删除掉。然后点击Import按钮找到之前导出的镜像进行导入即可

    image-20230216164225725.png

    image-20230216164305067.png

  8. 使用Dockerfile构建镜像

    在镜像页面,选择Build a new image来构建镜像,再弹出的新页面中,编写构建镜像的镜像名和Dockerfile文件

    image-20230221173603527.png

    在使用Portainner进行Dockerfile构建镜像时,Portainner官方文档专门有说明,Dockerfile里的ADD COPY指令不允许使用相对路径,而应该采用URL远程资源地址进行资源的下载。这里我们制作一个包含JDK17的centos7镜像,填下内容如下

    FROM centos:7
    MAINTAINER gucaini
    ADD https://download.oracle.com/java/17/archive/jdk-17.0.6_linux-x64_bin.tar.gz /usr/local/java
    ENV JAVA_HOME=/usr/local/java/jdk-17.0.6
    ENV PATH=$JAVA_HOME/bin:$PATH
    CMD ["java","-version"]
    

    image-20230221173702254.png

    填写完毕之后点击下方Build the image,进行构建,构建结果,可以通过切换到Output页面来查看

    image-20230221174032735.png

    image-20230221174417141.png

14.5 Portainner容器管理

我们以本地node1上的Docker为例,演示Portainner对容器的操作

  1. 进入容器管理页

    选择左侧导航栏的Containers进入容器管理页

    image-20230222093513422.png

    进入容器管理页后,会出现容器的操作功能按钮以及当前宿主机中的Docker容器列表,其中容器的操作功能按钮各个功能含义如下:

    按钮键 功能含义 Start 启动一个停止中的容器 Stop 停止一个正在运行的容器 Kill 与Stop的作用相似,区别在于Stop是优雅关闭容器,而Kill是强制关闭 Restart 重启一个容器 Pause 暂停一个容器中的所有进程 Resume 恢复一个容器中的所有进程 Remove 删除一个容器 Add container 添加一个新的容器

    Docker容器列表中每一个属性的作用及含义如下:

    列表属性 功能含义 Name 容器名 State 容器的运行状态,Running是正在运行,Stop是停止 Quick actions 可以查看容器的日志、容器的详情、容器的运行情况、进入容器命令行 Stack 堆栈名称,这里指的是使用类似Docker-Compose容器编排来创建容器时的堆栈名称 Image 镜像名 Created 容器创建的时间 Published Ports 端口映射列表 Ownership 容器的所有权
  2. 创建一个容器

    这里以启动一个MySQL容器为例,我们在容器列表页点击Add container,首先填写容器名my_mysql,选择镜像仓库服务器DockerHub,填写镜像名mysql:latest,如下:

    image-20230222111014835.png

    接下来,我们添加端口映射,选择publish a new network port,然后填写宿主机和容器的端口映射配置3306:3306,如下图:

    image-20230222111754196.png

    在下方容器设置中,找到Volumes标签页配置数据挂载,点击map additional volume添加一组新的数据挂载配置项,其中Volume配置的是数据卷挂载,Bind配置的是目录挂载,这里使用Bind目录挂载,分别填下如下挂载路径

    /mydata/mysql/data:/var/lib/mysql
    /mydata/mysql/conf:/etc/mysql/conf.d
    /mydata/mysql/logs:/var/log/mysql
    

    image-20230222165424763.png

    在下方容器设置中,找到Env标签页配置环境变量,点击add environment variable添加一组新的环境变量配置项,其中name配置的是环境变量的名字,value配置的是环境变量的值,填下如下内容:

    MYSQL_ROOT_PASSWORD=123456
    

    image-20230222165809087.png

    接着找到Restart policy标签页配置重启策略,点击Always,设置为总是自动重启,如下图:

    image-20230222170013667.png

    再接着找到Runtime & Resource标签页配置运行时资源,打开Privileged mode特权模式,如下图:

    image-20230222170418927.png

    最后点击页面中的Deploy the container按钮进行容器的创建

    image-20230222170521012.png

    容器创建成功后,会自动跳转到容器列表页进行展示,如下图:

    image-20230222170640398.png

  3. 使用Compose容器编排来创建容器

    在Portainner中,可以非常方便的使用容器堆栈的方式来创建容器,它相当于Docker-Compose容器编排。这里仍然SpringBoot程序部署为例,在左侧导航栏中找到Stacks按钮进入堆栈列表,填写堆栈名称,以及编写docker-compose.yml文件,如下图:

    version: "3"
    services:
      mysql:
        container_name: my_mysql
        image: mysql
        privileged: true
        restart: always
        volumes:
          - "/mydata/mysql/data:/var/lib/mysql"
          - "/mydata/mysql/conf:/etc/mysql/conf.d"
          - "/mydata/mysql/logs:/var/log/mysql"
        ports:
          - "3306:3306"
        expose:
          - "3306"
        environment:
          - MYSQL_ROOT_PASSWORD=123456
        networks:
          - my_network
      springboot:
        image: springboot_jxc
        deploy:
          replicas: 2
        ports:
          - "80-81:80"
        depends_on:
          - mysql
        restart: always
        networks:
          - my_network
    networks:
      my_network:
    

    image-20230223170503730.png

    image-20230224103659051.png

    编写完毕之后,点击Deploy the stack按钮进行容器的创建,如下图:

    image-20230224103805578.png

    部署完毕之后,我们可以通过列表查看详情,至此完成了Compose的部署:

    image-20230224103852754.png

    进行访问测试:

    在Windows浏览器中分别访问8081两个端口号的实例,访问如下地址,访问后如出现如下登录页面,则部署成功,登录账号:admin,登录密码:admin123

    http://192.168.177.128:80
    http://192.168.177.128:81
    

    image-20221221152141321.png