当前位置:   article > 正文

【Docker】Docker 快速进阶(精讲)_docker精讲

docker精讲

一、Docker Compose

1、简介

Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。借助 Compose,您可以使用 YAML 文件来配置应用程序的服务。然后,使用单个命令,从配置中创建并启动所有服务。Compose 适用于所有环境:生产、登台、开发、测试以及 CI 工作流。

使用 Compose 基本上是一个三步过程:

  1. 使用Dockerfile定义你的应用的环境。
  2. 通过docker-compose.yml 文件,将你的服务的各个部分组合在一起,以便它们可以在隔离的环境中一起运行。
  3. 运行docker compose up命令启动并运行你的整个应用程序。

一个docker-compose.yml 文件,如下:

version: "3.9"  # optional since v1.27.0
services:
  web:
    build: .
    ports:
      - "5000:5000"
    volumes:
      - .:/code
      - logvolume01:/var/log
    links:
      - redis
  redis:
    image: redis
volumes:
  logvolume01: {}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

Docker Compose的特点

  1. 多个相互隔离的环境在一个主机上
  2. 容器被创建是保存数据卷中的数据
  3. 只有重新创建容器的时候,它在可以被改变

2、安装与卸载 Docker Compose

安装

① 国内镜像下载命令
sudo curl -L https://get.daocloud.io/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose

在这里插入图片描述

② 因为docker-compose是一个二进制问津,所以我们需要给二进制文件应用可执行权限
sudo chmod +x /usr/local/bin/docker-compose

③ 测试
docker-compose --version
在这里插入图片描述

卸载

① 卸载
sudo rm /usr/local/bin/docker-compose

3、Docker Compose 初体验

下面我们来试一下,使用docker-compose来启动多个服务(镜像)。
我们的体验以官方的一个实例开始:Python+Redis 实现计数器的功能

第一步:设置

为项目创建一个目录
mkdir composetest
cd composetest
在这里插入图片描述

在当前目录下创建并编写Python应用文件app.py

import time

import redis
from flask import Flask

app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)

def get_hit_count():
    retries = 5
    while True:
        try:
            return cache.incr('hits')
        except redis.exceptions.ConnectionError as exc:
            if retries == 0:
                raise exc
            retries -= 1
            time.sleep(0.5)

@app.route('/')
def hello():
    count = get_hit_count()
    return 'Hello World! I have been seen {} times.\n'.format(count)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

在此示例中,redis是应用程序网络上的 redis 容器的主机名。我们使用 Redis 的默认端口6379。

在当前目录下创建并编写requirements.txt

flask
redis
  • 1
  • 2
第二步:创建一个 Dockerfile

编写一个用于构建 Docker 映像的 Dockerfile。该图像包含 Python 应用程序所需的所有依赖项,包括 Python 本身。

在当前目录下创建并编写Dockerfile

# syntax=docker/dockerfile:1
FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["flask", "run"]

# 从 Python 3.7 映像开始构建映像。
# 将工作目录设置为/code.
# 设置flask命令使用的环境变量。
# 安装 gcc 和其他依赖项
# 复制requirements.txt并安装 Python 依赖项。
# 将元数据添加到图像以描述容器正在侦听端口 5000
# 将.项目中的当前目录复制到.镜像中的workdir 。
# 将容器的默认命令设置为flask run.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
第四步:在 Compose 文件中定义服务

在当前目录下创建并编写一个docker-compose.yml文件

version: "3.9"
services:
  web:
    build: .
    ports:
      - "5000:5000"
  redis:
    image: "redis:alpine"

# 这个 Compose 文件定义了两个服务:web和redis
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

最后你的当前目录下应该有如下4个文件
在这里插入图片描述

第四步:通过Compose构建和启动你的app

在当前目录下。通过docker-compose up命令(使用该命令前,保证你的docker是启动的)启动并运行你的应用。或者使用docker-compose up -d后台启动。
在这里插入图片描述
在这里插入图片描述

注意:如果因为一些依赖或jar包导致项目启动失败,当我们修改之后,重新启动项目可以使用docker-compose up --build进行重新使用。--build的目的是重新构建相关的镜像,避免使用原本错误的镜像。

第五步:关闭服务

方式1:如果使用的是交互模式启动的项目,那么在项目中使用 Ctrll + C
在这里插入图片描述

方式2:如果你是要的是后台启动的项目,在项目目录下使用 docker-compose down
在这里插入图片描述

4、docker-compose.yml的配置规则

官方文档:https://docs.docker.com/compose/compose-file/

介绍

在docker-compose 中有三层的概念,如下

# 第一层:版本
version: "3.9"

# 第二层:服务(核心)
services:
  web:
    build: .
    ports:
      - "5000:5000"
  redis:
    image: "redis:alpine"
    
# 第三层:其他的一些配置(网络,数据卷...)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
第一层:版本

官方文档:https://docs.docker.com/compose/compose-file/compose-file-v3/

docker-compose文件的版本和和docker的引擎是有去联系的,其之间需要匹配好。我们的docker是向下兼容的。(说道版本对应,我得说两句,我在学习springcloud的时候,springboot的版本和springcloud的版本可把我害惨了,呜呜呜…)
在这里插入图片描述

我的docker引擎的版本是20.10.8
在这里插入图片描述

按照上图,我的docker-compose文件的版本应该是3.8以上
在这里插入图片描述

第二层:服务

compose文件是一个定义了服务、网络和数据卷的YAML(yml / yaml)文件。compose的默认路径是 ./docker-compose.yml.

官方文档:https://docs.docker.com/compose/compose-file/compose-file-v3/#service-configuration-reference

第三层:其他

Volume配置官方文档:https://docs.docker.com/compose/compose-file/compose-file-v3/#volume-configuration-reference

Network配置官方文档:https://docs.docker.com/compose/compose-file/compose-file-v3/#network-configuration-reference

Configs配置官方文档:https://docs.docker.com/compose/compose-file/compose-file-v3/#configs-configuration-reference

Secrets配置官方文档:https://docs.docker.com/compose/compose-file/compose-file-v3/#secrets-configuration-reference

变量替换官方文档:https://docs.docker.com/compose/compose-file/compose-file-v3/#variable-substitution

扩展字段官方文档:https://docs.docker.com/compose/compose-file/compose-file-v3/#extension-fields

5、springboot实战

我们在初体验的时候体验了一个Python的计数器,现在我们通过springboot实现一个Java+Redis的计数器

① 创建一个springboot项目

application.properties:

application.propertiesserver.port=8080
spring.redis.host=redis
  • 1
  • 2

redis是应用程序网络上的 redis 容器的主机名。Redis 的默认端口6379

DemoController:

@RestController
public class DemoController {

    @Autowired
    private StringRedisTemplate redistemplate;

    @RequestMapping("/tiger")
    public String demo(){
        Long view = redistemplate.opsForValue().increment("view");

        return "hello, studioustiger. view:"+view;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

② 编写 Dockerfile

FROM java:8

COPY *.jar /app.jar

CMD ["--server.port:8080"]

ENTRYPOINT ["java","-jar","app.jar"]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

③ 编写docker-compose.yml

version: '3.9'
services:
  tigerapp:
    build: .
    image: tigerapp
    depends_on:
      - redis
    ports:
      - 8080:8080
  redis:
    image: "redis:alpine"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

④ 将相关文件上传到linux中

我们需要将 docker-compose-0.0.1-SNAPSHOT.jarDockerfiledocker-compose.yml上到linux的同一个文件夹中
在这里插入图片描述
⑤ 启动项目

docker-compose.yml所在目录下使用docker-compose up命令一键启动项目
在这里插入图片描述
在这里插入图片描述

二、Docker Swarm

docker-swarm官方文档:https://docs.docker.com/engine/swarm

1、简介

Swarm 是 Docker 官方提供的一款集群管理工具,其主要作用是把若干台 Docker 主机抽象为一个整体,并且通过一个入口统一管理这些 Docker 主机上的各种 Docker 资源。

运行 Docker 的主机可以主动初始化一个 Swarm 集群或者加入一个已存在的 Swarm 集群,这样这个运行 Docker 的主机就成为一个 Swarm 集群的节点 (node) 。节点分为管理 (manager) 节点和工作 (worker) 节点。

管理节点用于 Swarm 集群的管理,docker swarm 命令基本只能在管理节点执行(节点退出集群命令 docker swarm leave 可以在工作节点执行)。一个 Swarm 集群可以有多个管理节点,但只有一个管理节点可以成为 leader,leader 通过 raft 协议实现。

工作节点是任务执行节点,管理节点将服务 (service) 下发至工作节点执行。管理节点默认也作为工作节点。你也可以通过配置让服务只运行在管理节点。下图展示了集群中管理节点与工作节点的关系。
在这里插入图片描述

节点会被配置为管理节点(Manager)或工作节点(Worker)。管理节点负责集群控制面(Control Plane),进行诸如监控集群状态、分发任务至工作节点等操作。工作节点接收来自管理节点的任务并执行。

Swarm 的配置和状态信息保存在一套位于所有管理节点上的分布式 etcd 数据库中。该数据库运行于内存中,并保持数据的最新状态。关于该数据库最棒的是,它几乎不需要任何配置,作为 Swarm 的一部分被安装,无须管理。

关于集群管理,最大的挑战在于保证其安全性。搭建 Swarm 集群时将不可避免地使用 TLS,因为它被 Swarm 紧密集成。

在安全意识日盛的今天,这样的工具值得大力推广。Swarm 使用 TLS 进行通信加密、节点认证和角色授权。自动密钥轮换(Automatic Key Rotation)更是锦上添花!其在后台默默进行,用户甚至感知不到这一功能的存在。

关于应用编排,Swarm 中的最小调度单元是服务。它是随 Swarm 引入的,在 API 中是一个新的对象元素,它基于容器封装了一些高级特性,是一个更高层次的概念。当容器被封装在一个服务中时,我们称之为一个任务或一个副本,服务中增加了诸如扩缩容、滚动升级以及简单回滚等特性。

综上所述,从概括性的视角来看 Swarm,如下图所示。
在这里插入图片描述

2、实现一个 Swarm 集群

注意:docker swarm是在docker中集成的,所以你的linux中只要安装了docker即可

第一步:创建一个swarm

我们需要在一个docker中创建一个swarm,并让其他的docker加入创建的swarm,实现swarm集群

我们先来看一下 docker swarm 怎么使用
在这里插入图片描述

使用 docker swarm init 创建(初始化)一个swarm。(我们在docker01中创建swarm)
在这里插入图片描述

第二步:将docker02以worker的角色加入swarm

我们可以在swarm的主节点(docker01)使用 docker swarm join-token worker 生成秘钥,在docker02中使用在和秘钥,加入swarm

在docker01中生成worker角色加入swarm的秘钥
在这里插入图片描述
docker02加入swarm
在这里插入图片描述
我们可以通过 docker node ls 查看swarm中的节点的信息
在这里插入图片描述

第三步:将docker03和docker04以manage的角色加入swarm

在docker01中使用docker swarm join-token manager 生成秘钥,在docker03和docker04中使用在和秘钥,加入swarm

生成秘钥(manage)
在这里插入图片描述
docker03加入swarm
在这里插入图片描述
docker04加入swarm
在这里插入图片描述

使用 docker node ls 查看集群中节点的情况
在这里插入图片描述

3、Ratf一致性协议

问题:假设一个节点挂了,其他节点是否可用?

Raft协议:保证大多数节点存活;在非集群中存活的节点数需要>1,在集群中存活的节点数需要>3

当 Docker Engine 以 swarm 模式运行时,管理器节点实现 Raft 共识算法来管理全局集群状态,以确保那些负责在集群中的管理和调度任务的所有Manager节点,都存储相同一致的状态。

在整个集群中具有相同的一致状态意味着在发生故障时,任何 Manager 节点都可以接收任务并将服务恢复到稳定状态。例如,如果集群中负责调度任务的Leader Manager意外死亡,任何其他 Manager 都可以接手调度的任务并重新平衡任务以匹配所需的状态。

Raft 最多可以允许(N-1)/2失败,并且需要(N/2)+1个Manager成员就向集群提出的价值达成一致。这意味着在运行 Raft 的 5 个 Manager 的集群中,如果 3 个节点不可用,系统将无法处理更多请求以安排额外的任务。


在上面的搭建中,我们实现了三个Manager节点,这也就意味着至少有3个[(N+1)/2] Manager节点存活,我们的swarm集群才可以使用。

现在我们关掉一个manager节点试一试。我们使用docker swarn leave --force使得docker03(manager)退出swarm集群
在这里插入图片描述
我来试一试swarm是否还可以使用(如果swarm可以使用,那么在manager节点上使用docker node ls是可以的)
在这里插入图片描述
很明显是可以使用的

现在我们将docker离开,试一下swarm是否还是可以使用
在这里插入图片描述
很明显不能使用了,因为manager的个数<2了
在这里插入图片描述
因为docker01是leader,所以我们将docker01离开后,整个swarm就崩了,我又重新搭了一个swarm集群,我们看一看当docker01(leader)宕机之后swarm的变化。我们使用systemctl stop docker模拟宕机
在这里插入图片描述
在docker03(manager)通过docker node ls查看swarm节点的状况。我们发现当原本的leader宕机之后,又出现了新的leader

当docker恢复之后(systemctl start docker),我们发现docker已经不在是leader,只是普通的manager
在这里插入图片描述

4、通过Swarm实现一个弹性服务的创建

上述,我们已经搭建好了一个docker swarm集群,那么我们就可以在集群中部署服务了。大家要注意区分服务和容器的区别(我们使用docker run启动一个容器;使用docker service启动一个服务,服务只能在集群中使用

我们在没有使用docker集群之前,大概是这样的:
在这里插入图片描述

我们在使用docker集群之前,大概是这样的:
在这里插入图片描述


接下来,我们将通过上面搭建的swarm集群,搭建一个nginx集群,并实现服务弹性。我们来看一下docker service 可以怎么使用
在这里插入图片描述
我们先来创建服务,可以使用docker service create --help 看看docker service create怎么使用。使用docker service create -p 8081:80 --name myNginx nginx命令创建一个nginx服务

[root@docker01 ~]# docker service create -p 8081:80 --name myNginx nginx
4ebot7f4xkhzdv7956sm9qbfg
overall progress: 1 out of 1 tasks
1/1: running   [==================================================>]
verify: Service converged
  • 1
  • 2
  • 3
  • 4
  • 5

通过docker service ps myNginx命令查看我们创建的服务的进程
在这里插入图片描述

我们可以看一下,我们创建的nginx在哪个节点中运行的,发现是在docker03节点上启动的
在这里插入图片描述

我们可以使用docker service update --replicas 4 myNginx创建myNginx服务的副本/扩缩容(使用docker service update --help查看其他用法)
在这里插入图片描述

我们看一下这4个nginx服务在节点上的分布情况 docker ps。我们发现是平均分布
在这里插入图片描述
我们可以发现不同的节点的访问没有问题,如下:
在这里插入图片描述


如果我们在四节点的集群中创建3个nginx的副本,那么肯定有一个节点上时没有nginx服务的,那么该节点是否可以访问nginx服务呢?

使用 docker service update --replicas 3 myNginx 命令创建三个nginx服务
在这里插入图片描述
发现在docker02所在节点上没有nginx服务
在这里插入图片描述

查看docker02节点的IP
在这里插入图片描述

通过docker02 的IP访问nginx服务。很明显,是可以的,这就是集群,这就是高可用!!
在这里插入图片描述


我什么我们四个linux上的docker可以进行集群呢?是因为这四个linux在同一个网络中

我们可以使用 docker network ls查看网络,发现有一个ingress网络(在这里就不展开讲了)
在这里插入图片描述
我们可以通过docker network inspect ingress命令,发现四个docker原来被绑定到同一个网络中了

[root@docker01 ~]# docker network inspect ingress
[
    {
		...
        "Peers": [
            {
                "Name": "15b9b9d927b5",
                "IP": "192.168.174.129"
            },
            {
                "Name": "3043986786d2",
                "IP": "192.168.174.135"
            },
            {
                "Name": "1f765c70b2e7",
                "IP": "192.168.174.134"
            },
            {
                "Name": "472700543e1c",
                "IP": "192.168.174.133"
            }
        ]
    }
]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

当然,还有很多的细节没有展现,其实其他的细节你可以结合–help慢慢的琢磨,持之以恒,学无止境

例如:我们也可以使用docker service scale myNginx=7实现动态扩缩容
在这里插入图片描述
在这里插入图片描述

三、Docker Stack

停更…

四、Docker Secret

停更…

五、Docker Config

停更…



十年饮冰,难凉热血,唯有爱情与科技不可辜负…
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/73497
推荐阅读
相关标签
  

闽ICP备14008679号