• Spring Boot实践 --windows环境下 K8s 部署 Docker


    简介

    Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。Docker 从 17.03 版本之后分为 CE(Community Edition: 社区版) 和 EE(Enterprise Edition: 企业版),用社区版就可以了。

    Docker 包括三个基本概念:

    • 镜像(Image):Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。
    • 容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
    • 仓库(Repository):仓库可看成一个代码控制中心,用来保存镜像。

    在这里插入图片描述

    Docker提供了容器化的基础设施,而Kubernetes则建立在Docker之上,提供了容器的编排和管理功能。使用Docker可以方便地创建和打包容器,而Kubernetes则可以帮助我们管理和运行这些容器,使得应用程序的部署和管理更加简单和可靠。

    安装运行Docker

    下载安装对应版本即可:
    Install Docker Desktop on Windows

    Get Started with Docker

    1,win10环境,安装Docker Desktop时如果报错:

    Docker Desktop requires Windows 10 Pro/Enterprise/Home version 19044 or above.
    
    • 1

    原因是Docker Desktop 要求计算机必须运行64位的Windows 10版本,且操作系统版本为Windows 10 专业版、企业版或教育版19044 以上版本,不支持Windows家庭版。查看操作系统版本方式:设置 - 系统 - 关于- Windows规格

    可以尝试使用更新 Windows 系统版本Windows10Upgrade9252.exe 然后再尝试安装Docker Desktop。

    2,启动Docker Desktop时如果报错:

    Docker Desktop - unexpected wsl error
    
    • 1

    在这里插入图片描述
    这是因为docker默认使用了WSL选项,在Docker Desktop的"Settings"里:

    在这里插入图片描述

    但是当前 Windows10还无法使用Linux功能 WSL(Windows Subsystem for Linux)。

    方式一:去掉WSL2的勾选,使用Hyper-V

    如果Hyper-V默认没使能,通过以下方式开启:

    控制面板 - 程序 - 启用或关闭 Windows 功能 (bios需要开启虚拟化支持)
    在这里插入图片描述

    Hyper-V 是微软开发的虚拟机,类似于 VMWare 或 VirtualBox,仅适用于 Windows 10。这是 Docker Desktop for Windows 所使用的虚拟机。但是,这个虚拟机一旦启用,QEMU、VirtualBox 或 VMWare Workstation 15 及以下版本将无法使用!

    方式二:安装 WSL

    将 WSL 2 设置为默认版本

     C:\WINDOWS\system32>wsl --set-default-version 2
    
    • 1

    查看wsl版本情况:

    在这里插入图片描述

    显示子系统没有已安装的分发,并给出了两个解决方法。如方法二访问:https://aka.ms/wslstore,采用 旧版 WSL 的手动安装步骤 安装 Linux 分发版Ubuntu。

    配置换源

    选择Docker Engine,在编辑框中输入源,如:

    {
      "registry-mirrors":[
          "https://docker.mirrors.ustc.edu.cn",
          "https://registry.docker-cn.com",
          "http://hub-mirror.c.163.com",
          "https://mirror.ccs.tencentyun.com"
      ],
      "insecure-registries":[],
      "debug":true,
      "experimental":false,
      "data-root":"F:\\docker"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    默认情况下, Docker环境下的其它相关镜像文件及容器文件,存储在:C:\ProgramData\Docker目录下,可以通过Windows Docker Destop中的Docker Enginer的配置文件进行更改,具体是JSON文件中增加如下一行:"data-root":"F:\\docker"
    在这里插入图片描述

    docker 基础使用

    测试:启动成功后可以看到左下角的running状态:

    在这里插入图片描述

    打开cmd命令框,
    输入“docker -v”“docker info”可以看到对应信息。
    输入“docker run hello-world”,这行命令会让docker从官方仓库中拉取hello-world的镜像到本地,并且自动将其实例化成容器。出现下图所示的提示:

    在这里插入图片描述

    我们再去查看Docker Desktop的主页会出现对应记录。直接点击容器名,我们可以进入容器的交互界面,其中能看到容器的log、参数等信息:

    在这里插入图片描述

    获取当前所有镜像(docker images)

    docker image ls
    # 或者
    docker images
    
    • 1
    • 2
    • 3

    在这里插入图片描述
    上面图的结果字段含义如下:

    标签含义
    REPOSITORY镜像所在的仓库名称
    TAG镜像标签
    IMAGEID镜像ID
    CREATED镜像的创建日期(不是获取该镜像的日期)
    SIZE镜像大小

    拉取镜像(docker pull)

    除了使用官方的镜像外,我们还可以在仓库中申请一个自己的账号,保存自己制作的镜像,或者拉取使用他人的镜像。

    # 官方镜像
    docker image pull 镜像名称 
    # 或简写为 
    docker pull 镜像名称
    # 比如
    docker pull ubuntu
    docker pull ubuntu:16.04
    
    # 个人镜像
    docker pull 仓库名称/镜像名称
    docker pull gyd/django
    
    # 第三方仓库拉取
    docker pull 第三方仓库地址/仓库名称/镜像名称
    docker pull hub.c.163.com/library/mysql:latest
    (默认仓库名为library,所有从官方获取镜像相当于`sudo docker image pull library/镜像名称`
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    删除镜像(docker rmi)

    docker image rm 镜像名或镜像ID 或 docker rmi 镜像名或镜像ID
    docker image rm hello-world
    docker rmi 9e64176cd8a2
    
    • 1
    • 2
    • 3

    删除镜像的前提是没有使用这个镜像的容器,如果有需要先删除容器(报错:Error response from daemon: conflict: unable to delete 镜像ID (must be forced) - image is being used by stopped container 容器ID则代表有容器使用了此镜像。),可以尝试先执行docker rm 容器ID删除容器,如果还报错,可以看我下方删除容器的具体方法。 几条删除命令的区别:

    - docker rm: 删除一个或多个 容器 
    - docker rmi: 删除一个或多个 镜像 
    - docker prune: 用来删除不再使用的 docker 对象 
    
    • 1
    • 2
    • 3

    加载镜像(docker run)

    上面我们说过,镜像只是一个只读类型的文件,而我们的环境不可能只是一个这样的文件,所以我们需要把这个镜像加载成我们的环境,也就是让他变成容器

    docker run [可选参数] 镜像名 [向启动容器中传入的命令]
    
    • 1
    常用可选参数作用
    -i表示以《交互模式》运行容器。
    -d会创建一个守护式容器在后台运行(这样创建容器后不会自动登录容器)。
    -t表示容器启动后会进入其命令行。加入这两个参数后,容器创建就能登录进去。即分配一个伪终端。
    –name为创建的容器命名。(默认会随机给名字,不支持中文字符!!!)
    -v表示目录映射关系,即宿主机目录:容器中目录。注意:最好做目录映射,在宿主机上做修改,然后共享到容器上。
    -p表示端口映射,即宿主机端口:容器中端口。 比如:-p 8080:80 就是将容器中的80端口,映射到主机中的8080端口
    – network=host表示将主机的网络环境映射到容器中,使容器的网络与主机相同。每个 Docker 容器都有自己的网络连接空间连接到虚拟 LAN。使用此命令则会让容器和主机共享一个网络空间。

    可以启动一个系统(这里我使用linux的一个发行版作为介绍):

    docker run -i -d -t --name=my-test-kali kalilinux/kali-rolling
    或可以简写为
    docker run -idt --name=my-test-kali kalilinux/kali-rolling
    
    • 1
    • 2
    • 3

    如果加载的是一个我们没有的镜像,docker会自动从官方仓库中进行拉取:
    在这里插入图片描述

    或者我们可以启动一个网站

    docker run -dp 8080:80 --name docker-test docker/getting-started 
    
    • 1

    在这里插入图片描述

    成功启动后,可以在浏览器中输入“http://localhost:8080/” 即可看到getting-started页面。

    上面我们成功将镜像变成了容器,但上述的命令中我们都加入了-d,让容器在后台运行了。下面我们就来讲如何和正在运行的容器进行交互。

    查看容器(docker ps)

    # 查看当前所有正在运行的容器
    docker ps
    # 查看当前所有的容器
    docker ps -a
    # 使用过滤器(除了name外,常用的还可以指定id:id= 、所有停止的容器:status=exited,正在运行的容器:status=running 等)
    docker ps -f name=指定的名字
    # 显示2个上次创建的容器(2可以改变)
    docker ps -n 2
    # 显示最新创建的容器(包括所有状态)
    docker ps -l
    # 仅显示ip
    docker ps -q
     # 显示容器大小
    docker ps -s
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述

    启动和关闭容器(docker start\stop\kill)

    # 停止容器
    docker container stop 容器名或容器id
    # 或可简写为
    docker stop 容器名或容器id
    
    # 强制关闭容器
    docker container kill 容器名或容器id
    # 或可简写为
    docker kill 容器名或容器id
    
    # 启动容器
    docker container start 容器名或容器id
    # 或可简写为
    docker start 容器名或容器id
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    如果我们成功启动或者关闭一个容器的话,会返回容器名或者容器id

    操作后台容器(docker exec -it 、 attach)

    之前我们下过一个kali并且放在了后台运行,并且使用docker ps -a查看其中的STATUS属性是Up的,确保我们要进入的容器是开启状态。

    开启容器后,如果需要在容器内执行命令,可以将后台切换到前台,也可能使用docker命令将我们需要执行的命令传入。 操作方法有很多种,这里我们介绍一些比较常用的方法:

    # 如果我只需要执行简单的一两条命令可以使用docker exec
    # 执行单条命令 (-i: 启动并且保留交互式命令行; -t:作用是分配一个虚拟的终端; docker run )
    docker exec -it 容器名或容器id 执行的命令
    # 比如
    docker exec -it my-test-kali whoami
    # 用这种方法,我们还可以启动命令行,根据Linux的特性,系统程序会在/bin中,linux中常用的Shell有多个,其中大部分用的Linux默认的为bash
    # 所以我们启动命令可以自行如下命令(除了/bin/bash外,linux一般还会带/bin/sh、/bin/rbash、/bin/dash等,具体区别可以自行百度)
    docker exec -it 容器名或容器id /bin/bash
    # 比如
    docker exec -it my-test-kali /bin/bash
    # 除了exec外还有attach可以使用,但它有个弊端,多终端启动attach后,都会会同步显示。如果有一个窗口阻塞了,那么其他窗口也无法再进行操作。
    docker attach 容器名或容器id
    # 比如
    docker attach my-test-kali
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    删除容器(docker rm)

    如我们需要删除一个容器,首先需要确保这个容器已经停止了,因为正在运行的容器是无法直接删除。 我们可以运行一下docker ps -a,如果发现没有停止,可以使用docker stop停止(STATUS下已Exited开头则是停止的)

    # 使用rm删除容器
    docker rm 容器名或容器id
    # 列如
    docker rm docker-test
    
    • 1
    • 2
    • 3
    • 4

    保存镜像(docker commit\save\load)

    镜像可以看作为是一种备份,如果我们后期环境出现了问题,可以还原到早期镜像。
    镜像便于传播,可以让自己的其他设备或他人的重复利用变得更加简单容易。

    # 将容器制作成镜像
    docker commit 容器名 镜像名
    # 镜像打包备份(打包备份的文件会自动存放在当前命令行的路径下,如果想让保存的文件可以打开,可以加.tar后缀)
    docker save -o 保存的文件名 镜像名
    # 镜像解压
    docker load -i 文件路径/备份文件
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    我们将打包备份的镜像可以通过网络发送到其他设备上,使用docker镜像解压即可直接使用你的环境。

    另外,Docker重启后镜像消失,也可以使用Docker的镜像导出和导入功能,将我们需要的镜像保存到本地,并在需要的时候重新导入:

    docker save -o my_images.tar image1 image2 image3
    docker load -i my_images.tar
    
    • 1
    • 2

    docker 实践

    示例-部署安装mysql程序

    a. 拉取最新的镜像

     docker image pull mysql
    
    • 1

    b. 创建mysql容器实例并启动

    容器名是mysql,自定义。第一次执行,需要先创建容器并启动(容器名是mysql):

    docker run --name mysql -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=1234 mysql 
    
    • 1

    后续 直接执行 docker start 容器名即可:

     docker start mysql
    
    • 1

    c. 设置并使用mysql

    进入mysql 交互环境,使用创建容器时设置的账户密码登录mysql环境

    docker exec -it mysql mysql -u root -p
    
    • 1

    接下来可以愉快的执行mysql相关命令啦! 比如查看数据库 show databases、创建数据库 create databses; 创建表 create table等。
    本地运行的springboot应用也能正常使用容器里的mysql了。

    Spingboot集成docker(docker build、run)

    在传统的应用程序部署中,我们往往需要手动安装和配置各种应用程序所需的组件和依赖项。这个过程通常是非常繁琐的,因为我们需要确保我们部署的代码在各个环境中都能正常运行。而且,当我们需要在多个环境中部署同一个应用程序时,这个过程可能会变得更加复杂。因此,使用Docker来部署Spring Boot应用程序可以带来以下好处:

    • 环境一致性: 使用Docker容器可以确保我们在不同的环境中运行相同版本的应用程序,不管是在开发、测试还是生产环境,都可以提供相同的运行环境。
    • 部署更加简单: 使用Docker容器可以大大简化应用程序的部署流程。我们只需要把应用程序打包成一个Docker镜像,然后将这个镜像推送到Docker仓库中,就可以在任何支持Docker的环境中轻松地部署应用程序。
    • 资源隔离: 每个Docker容器都是一个独立的环境,它们之间是隔离的。这意味着我们可以在同一台主机上运行多个容器,每个容器都有自己的资源,例如CPU和内存,这可以提高系统的资源利用率。

    生成Spring Boot应用镜像和容器

    下面使用Docker来部署Spring Boot应用程序的步骤:

    这里我们准备好前面的springboot项目 用户管理系统 项目里的jar包,定时任务会每过10s打印一次日志:

    E:\test>java -jar demospringboot-0.0.1-SNAPSHOT.jar
    
    2023-11-01 20:24:21.059  INFO 11848 --- [  sched-exe-2-1] c.example.demospringboot.ScheduledTasks  : AnalysisLogTask start:20:24:21
    2023-11-01 20:24:31.065  INFO 11848 --- [  sched-exe-2-1] c.example.demospringboot.ScheduledTasks  : AnalysisLogTask end:20:24:31
    2023-11-01 20:24:32.076  INFO 11848 --- [  sched-exe-2-1] c.example.demospringboot.ScheduledTasks  : AnalysisLogTask start:20:24:32
    2023-11-01 20:24:42.079  INFO 11848 --- [  sched-exe-2-1] c.example.demospringboot.ScheduledTasks  : AnalysisLogTask end:20:24:42
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    1,准备Docker环境

    在使用Docker之前,启动redis和mysql依赖的容器:

    # redis
    docker run --name reids -d -p 6379:6379 redis 
    # mysql
    docker run --name mysql -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=1234 mysql 
    
    • 1
    • 2
    • 3
    • 4

    Docker在创建容器时有四种网络模式:bridge/host/container/none,bridge为默认不需要用–net去指定,其他三种模式需要在创建容器时使用–net去指定。

    • –net=bridge,这种模式会为每个容器分配一个独立的Network Namespace,
      同一个宿主机上的所有容器会在同一个网段下,相互之间是可以通信的
    • -net=host,容器将不会虚拟出IP/端口,而是使用宿主机的IP和端口。但是Host 模式只支持 Linux 系统,Windows 和 macOS 此参数无效。因此容器中的localhost是指向容器本身,所以要访问容器外的,需要明确指出宿主机的IP地址。官网说明:https://docs.docker.com/network/host/

    因此这里我们采用默认的bridge模式,springboot应用通过ip访问redis和mysql。
    查看容器ip:

    # docker ps                                                                 
    CONTAINER ID   IMAGE     COMMAND                   CREATED         STATUS         PORTS                               NAMES
    14f52f108fdc   mysql     "docker-entrypoint.s…"   6 seconds ago   Up 5 seconds   0.0.0.0:3306->3306/tcp, 33060/tcp   mysql
    f3570e0aed2b   redis     "docker-entrypoint.s…"   7 hours ago     Up 7 hours     0.0.0.0:6379->6379/tcp              redis
    # docker inspect --format='{{.NetworkSettings.IPAddress}}' mysql            
    172.17.0.3
    # docker inspect --format='{{.NetworkSettings.IPAddress}}' redis
    172.17.0.2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    并修改springboot配置文件applications.properties用到的ip,打包jar包:

    # mysql 
    spring.datasource.url=jdbc:mysql://172.17.0.3:3306/mydatabase?createDatabaseIfNotExist=true
    spring.datasource.username=root
    spring.datasource.password=1234
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    # mysql5: spring.datasource.driver-class-name=com.mysql.jdbc.Driver
    spring.datasource.initialize=true
    spring.datasource.schema=classpath:schema.sql
    
    # redis
    spring.redis.host=172.17.0.2
    spring.redis.port=6379
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2,编写Dockerfile

    在Docker环境准备好之后,接下来我们需要编写一个Dockerfile文件。Dockerfile文件是一个包含Docker容器构建步骤的脚本文件。构建Docker容器时,我们可以根据Dockerfile文件中的步骤来创建和打包Docker镜像。以下是一个简单的Dockerfile文件示例:

    FROM openjdk:8-jdk-alpine
    COPY target/demospringboot-0.0.1-SNAPSHOT.jar F:\docker
    WORKDIR F:\docker
    EXPOSE 8080
    ENTRYPOINT ["java", "-jar", "demospringboot-0.0.1-SNAPSHOT.jar"]
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这个Dockerfile文件中,我们使用了一个已经存在的openjdk:8-jdk-alpine镜像作为基础镜像,并将我们的Spring Boot应用程序打成jar包后复制到镜像中,并指定工作目录和开放的端口。最后,使用ENTRYPOINT指令指定了容器启动命令。

    如果没有镜像,可以先去镜像仓库拉取镜像 DockerHub

    docker pull openjdk:8-jdk-alpine
    
    • 1

    在这里插入图片描述

    3,构建Docker镜像

    在编写完Dockerfile文件后,我们需要使用docker build命令来构建Docker镜像,该命令具有以下基本语法:

    # docker build -f my-app-dockfile -t my-springboot-img:v1 .
    
    # docker images
    REPOSITORY                                                TAG                                                                          IMAGE ID       CREATED         SIZE
    my-springboot-img                                         v1                                                                           a21af825fd01   5 seconds ago   153MB
    redis                                                     latest                                                                       720b987633ae   3 weeks ago     158MB
    mysql                                                     latest                                                                       5d2fb452c483   4 weeks ago     622MB
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    其中-t参数用于指定新镜像的名称和版本,"."表示Dockerfile文件所在的当前目录。

    4,运行Spring Boot应用程序容器

    构建Docker镜像后,我们可以通过docker run命令来运行容器,该命令具有以下基本语法:

    # 其中--name参数用于指定容器的名称,-d为后台运行,-p为主机到容器的端口映射,最后指定要运行的镜像名称和标记。
    # docker run --name my-springboot -d -p 8080:8080 my-springboot-img:v1
    
    # docker ps                                                             
    CONTAINER ID   IMAGE                  COMMAND                   CREATED          STATUS          PORTS                               NAMES
    80d0cfcd7e60   my-springboot-img:v1   "java -jar demosprin…"   29 seconds ago   Up 28 seconds   0.0.0.0:8080->8080/tcp              my-springboot
    14f52f108fdc   mysql                  "docker-entrypoint.s…"   9 minutes ago    Up 9 minutes    0.0.0.0:3306->3306/tcp, 33060/tcp   mysql
    f3570e0aed2b   redis                  "docker-entrypoint.s…"   7 hours ago      Up 7 hours      0.0.0.0:6379->6379/tcp              redis
    
    # docker inspect --format='{{.NetworkSettings.IPAddress}}' my-springboot
    172.17.0.4
    
    # 查看日志
    docker logs my-springboot
    docker logs -f my-springboot  // 实时查看
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    注:mac 系统docker 使用桥接网络ip 宿主机无法访问容器。因为mac docker 实现的桥接网络是通过了一个linux 虚拟机实现,并不是直接在mac宿主机上创建虚拟网卡,导致无法ping通。解决方案参考:https://cloud.tencent.com/developer/article/2322367

    docker 查看容器网络配置:

    # docker inspect my-springboot | tail -n 20    
                "Networks": {
                    "bridge": {
                        "IPAMConfig": null,
                        "Links": null,
                        "Aliases": null,
                        "NetworkID": "39180cce7b9d653bbf0838bc95e3467cd9b749f32890d7afe7e8b064d7dbe4fb",
                        "EndpointID": "7ad7ebc523ab57a18d601ff94f37488b1c225cd8edd83806ae585c84c497b693",
                        "Gateway": "172.17.0.1",
                        "IPAddress": "172.17.0.4",
                        "IPPrefixLen": 16,
                        "IPv6Gateway": "",
                        "GlobalIPv6Address": "",
                        "GlobalIPv6PrefixLen": 0,
                        "MacAddress": "02:42:ac:11:00:04",
                        "DriverOpts": null
                    }
                }
            }
        }
    ]
    
    # ping 172.17.0.4
    PING 172.17.0.4 (172.17.0.4): 56 data bytes
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    5,部署Docker镜像

    最后,我们可以将Docker镜像部署到任何支持Docker的环境中。例如,我们可以使用Docker Swarm或者Kubernetes等集群管理工具来管理Docker容器。

    从Spring Boot容器中连接到另一个容器中的MySQL

    上面我们的springboot应用采用了ip访问mysql容器,但是由于容器ip可能会变,比较好的访问方法是使用Docker的网络功能来实现:

    (1)创建一个自定义的Docker网络:运行以下命令创建一个自定义的Docker网络,以便容器可以相互通信。

    docker network create mynetwork 
    
    • 1

    (2)启动MySQL容器:在创建MySQL容器时,将其连接到自定义的Docker网络。运行以下命令启动MySQL容器:

    docker run --name mysql-container --network=mynetwork  -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=1234 mysql 
    
    • 1

    (3)在Spring Boot配置中使用容器名称:在Spring Boot的配置文件中,将localhostip替换为MySQL容器的名称(在本例中为mysql-container)。修改配置如下:

    spring.datasource.url=jdbc:mysql://mysql-container:3306/mydatabase?createDatabaseIfNotExist=true ```
    
    • 1

    基于jar包生成镜像:

    # docker build -f my-app-dockfile -t my-springboot-img:v1 .
    
    • 1

    (4)启动Spring Boot容器:在启动Spring Boot容器时,将其连接到相同的自定义Docker网络。运行以下命令启动Spring Boot容器:

    # docker run --name my-springboot --network=mynetwork -d -p 8080:8080 my-springboot-img:v1
    
    • 1

    这样,Spring Boot容器就可以通过Docker网络连接到MySQL容器中的MySQL数据库了。

    安装运行Kubernetes

    Kubernetes 配置方式:

    • 右键点击Docker Desktop系统托盘图标,选择"Settings"。
    • 在"Kubernetes"选项卡中,启用Kubernetes,然后点击"Apply & Restart"按钮以应用更改。
    • Docker将自动为你配置Kubernetes,并在运行时创建一个Kubernetes集群。

    国内的用户如果一直停留在Starting状态,可能是镜像源无法下载,需要提前把Kubernetes需要的Images拉取下来。

    在这里插入图片描述

    打开PowerShell,注:不要使用PowerShell ISE。交互式终端在PowerShell ISE中不起作用(但它们在PowerShell中起作用)。见docker / for-win / issues / 223

    并下载k8s-for-docker-desktop,这是阿里提供了一个项目,只要checkout到你需要k8s的版本分支上,然后执行一个脚本就ok了。当前k8s-for-docker-desktop的 master 分支已经在支持到 Docker for Mac/Windows 4.24.1 (包含 Docker CE 24.0.2 和 Kubernetes 1.27.2)

    版本配套详见:
    https://github.com/AliyunContainerService/k8s-for-docker-desktop.git
    macOS:
    git clone git@github.com:maguowei/k8s-docker-desktop-for-mac.git

    Docker Desktop 历史版本下载:https://docs.docker.com/desktop/release-notes/

    运行下面的命令拉取Kubernetes需要的Images:

    Set-ExecutionPolicy -ExecutionPolicy bypass  // PowerShell脚本权限
    git clone https://github.com/AliyunContainerService/k8s-for-docker-desktop.git
    cd k8s-for-docker-desktop
    .\load_images.ps1
    
    • 1
    • 2
    • 3
    • 4

    执行完后通过docker images可以看到镜像拉取成功了:

    在这里插入图片描述
    不过windows上 k8s-for-docker-desktop拉取的镜像并不完整(mac没问题),还要增加如下几个镜像:

    docker pull docker/desktop-kubernetes:kubernetes-v1.25.9-cni-v1.1.1-critools-v1.25.0-cri-dockerd-v0.2.6-1-debian
    docker pull docker/desktop-storage-provisioner:v2.0
    docker pull docker/desktop-vpnkit-controller:v2.0
    
    • 1
    • 2
    • 3

    然后再回到Docker Desktop卡住的界面,执行一下“Reset Kubernetes Cluster”,左下角running成功。

    验证执行:kubectl cluster-infokubectl get nodes命令

    ➜  kubectl cluster-info
    Kubernetes control plane is running at https://127.0.0.1:6443
    CoreDNS is running at https://127.0.0.1:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
    
    To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
    
    ➜  kubectl get nodes   
    NAME             STATUS   ROLES           AGE    VERSION
    docker-desktop   Ready    control-plane   2d4h   v1.27.2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    Kubernetes实践

    最简部署

    Pod是k8s中最小的可部署单元,它可以包含一个或多个容器。

    命令运行:

    #运行一个镜像版本为6.2.5 的redis程序
    #  kubectl run redis --image=redis:6.2.5
    
    #  kubectl get pods -o wide             
    NAME    READY   STATUS              RESTARTS   AGE   IP       NODE             NOMINATED NODE   READINESS GATES
    redis   0/1     ContainerCreating   0          16s   <none>   docker-desktop   <none>           <none>
    
    #  kubectl delete pod redis  // 或 --all --force
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    YAML文件运行:

    # vim pod.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: redis
    spec:
      # 定义容器,可以多个
      containers:
        - name: redis # 容器名字
          image: redis:6.2.5 # 镜像
          ports:
             - containerPort: 6379
        - name: mysql
          image: mysql:latest
          ports:
             - containerPort: 3306
          env:
             - name: MYSQL_ROOT_PASSWORD
               value: "1234"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    # 启动pod
    # kubectl apply -f pod.yaml
    
    # 关闭pod
    # kubectl delete -f pod.yaml
    pod/redis-mysql created
    
    # 查看pod
    # kubectl get pods -o wide 
    NAME          READY   STATUS              RESTARTS   AGE   IP       NODE             NOMINATED NODE   READINESS GATES
    redis-mysql   0/2     ContainerCreating   0          5s    <none>   docker-desktop   <none>           <none>
    
    # 查看所有信息
    # kubectl get all                                                                 
    NAME              READY   STATUS              RESTARTS   AGE
    pod/redis-mysql   0/2     ContainerCreating   0          3m48s
    
    NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
    service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   2d6h
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    status定义说明:
    在这里插入图片描述

    # 查看pod详细信息
    # kubectl describe pod    
    Name:             redis-mysql
    Namespace:        default
    Priority:         0
    Service Account:  default
    Node:             docker-desktop/192.168.65.3
    Start Time:       Fri, 17 Nov 2023 23:35:40 +0800
    Labels:           <none>
    Annotations:      <none>
    Status:           Pending
    IP:               
    IPs:              <none>
    Containers:
      redis:
        Container ID:   
        Image:          redis:6.2.5
        Image ID:       
        Port:           6379/TCP
        Host Port:      0/TCP
        State:          Waiting
          Reason:       ContainerCreating
        Ready:          False
        Restart Count:  0
        Environment:    <none>
        Mounts:
          /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-nrqf6 (ro)
      mysql:
        Container ID:   
        Image:          mysql:latest
        Image ID:       
        Port:           3306/TCP
        Host Port:      0/TCP
        State:          Waiting
          Reason:       ContainerCreating
        Ready:          False
        Restart Count:  0
        Environment:
          MYSQL_ROOT_PASSWORD:  1234
        Mounts:
          /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-nrqf6 (ro)
    Conditions:
      Type              Status
      Initialized       True 
      Ready             False 
      ContainersReady   False 
      PodScheduled      True 
    Volumes:
      kube-api-access-nrqf6:
        Type:                    Projected (a volume that contains injected data from multiple sources)
        TokenExpirationSeconds:  3607
        ConfigMapName:           kube-root-ca.crt
        ConfigMapOptional:       <nil>
        DownwardAPI:             true
    QoS Class:                   BestEffort
    Node-Selectors:              <none>
    Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                                 node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
    Events:
      Type    Reason     Age   From               Message
      ----    ------     ----  ----               -------
      Normal  Scheduled  5s    default-scheduler  Successfully assigned default/redis-mysql to docker-desktop
      Normal  Pulling    5s    kubelet            Pulling image "redis:6.2.5"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    YAML文件说明

    apiVersion: v1 # 【必须】版本号
    kind: Pod # 【必选】Pod
    metadata: # 【必选-Object】元数据
      name: String # 【必选】 Pod的名称
      namespace: String # 【必选】 Pod所属的命名空间
      labels: # 【List】 自定义标签列表
       - name: String
      annotations: # 【List】 自定义注解列表
       - name: String
    spec: # 【必选-ObjectPod中容器的详细定义
      containers: # 【必选-ListPod中容器的详细定义
      - name: String # 【必选】 容器的名称
        image: String # 【必选】 容器的镜像名称
        imagePullPolicy: [Always | Never | IfNotPresent] # 【String】 镜像拉取策略
        command: [String] # 【List】 容器的启动命令列表,如果不指定,则使用镜像打包时使用的启动命令
        args: [String] # 【List】 容器的启动命令参数列表
        workingDir: String # 容器的工作目录
        volumeMounts: # 【List】 挂载到容器内部的存储卷配置
        - name: String # 引用Pod定义的共享存储卷的名称,需使用volumes[]部分定义的共享存储卷名称
          mountPath: Sting # 存储卷在容器内mount的绝对路径,应少于512个字符
          readOnly: Boolean # 是否为只读模式,默认为读写模式
        ports: # 【List】 容器需要暴露的端口号列表
        - name: String  # 端口的名称
          containerPort: Int # 容器需要监听的端口号
          hostPort: Int # 容器所在主机需要监听的端口号,默认与containerPort相同。设置hostPort时,同一台宿主机将无法启动该容器的第二份副本
          protocol: String # 端口协议,支持TCPUDP,默认值为TCP
        env: # 【List】 容器运行前需设置的环境变量列表
        - name: String # 环境变量的名称
          value: String # 环境变量的值
        resources: # 【Object】 资源限制和资源请求的设置
          limits: # 【Object】 资源限制的设置
            cpu: String # CPU限制,单位为core数,将用于docker run --cpu-shares参数
            memory: String # 内存限制,单位可以为MBGB等,将用于docker run --memory参数
          requests: # 【Object】 资源限制的设置
            cpu: String # cpu请求,单位为core数,容器启动的初始可用数量
            memory: String # 内存请求,单位可以为MBGB等,容器启动的初始可用数量
        # 【Object】 对Pod内各容器健康检查的设置,当探测无响应几次之后,系统将自动重启该容器。
        # 可以设置的方法包括:exec、httpGet和tcpSocket。对一个容器只需要设置一种健康检查的方法
        livenessProbe:
          exec: # 【Object】 对Pod内各容器健康检查的设置,exec方式
            command: [String] # exec方式需要指定的命令或者脚本
          httpGet: # 【Object】 对Pod内各容器健康检查的设置,HTTGet方式。需要指定path、port
            path: String
            port: Number
            host: String
            scheme: String
            httpHeaders:
            - name: String
              value: String
          tcpSocket: # 【Object】 对Pod内各容器健康检查的设置,tcpSocket方式
            port: Number
          initialDelaySeconds: Number # 容器启动完成后首次探测的时间,单位为s
          timeoutSeconds: Number  # 对容器健康检查的探测等待响应的超时时间设置,单位为s,默认值为1s。
          periodSeconds: Number # 对容器健康检查的定期探测时间设置,单位为s,默认10s探测一次
          successThreshold: 0
          failureThreshold: 0
        securityContext:
          privileged: Boolean
      # Pod的重启策略 一旦终止运行,都将重启 | 终止后kubelet将报告给master,不会重启 
      # 只有Pod以非零退出码终止时,kubelet才会重启该容器。如果容器正常终止(退出码为0),则不会重启。
      restartPolicy: [Always | Never | OnFailure]
      nodeSelector: object # 设置NodeLabel,以key:value格式指定,Pod将被调度到具有这些LabelNode上
      imagePullSecrets: # 【Object】 pull镜像时使用的Secret名称,以name:secretkey格式指定
      - name: String
      # 是否使用主机网络模式,默认值为false。设置为true表示容器使用宿主机网络,不再使用docker网桥,该Pod将无法在同一台宿主机上启动第二个副本
      hostNetwork: Boolean
      volumes: # 【List】 在该Pod上定义的共享存储卷列表
      - name: String # 共享存储卷的名称,volume的类型有很多emptyDir,hostPath,secret,nfs,glusterfs,cephfs,configMap
        emptyDir: {} # 【Object】 类型为emptyDir的存储卷,表示与Pod同生命周期的一个临时目录,其值为一个空对象:emptyDir: {}
        hostPath: # 【Object】 类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录
          path: String # Pod所在主机的目录,将被用于容器中mount的目录
        secret: # 【Object】类型为secret的存储卷,表示挂载集群预定义的secret对象到容器内部
          secretName: String
          items:
          - key: String
            path: String
        configMap: # 【Object】 类型为configMap的存储卷,表示挂载集群预定义的configMap对象到容器内部
          name: String
          items:
          - key: String
            path: String
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81

    k8s的yaml文件中kind类型详解

    在Kubernetes(k8s)的YAML语法中,kind是一种重要的关键字,它用于指定Kubernetes资源的类型。根据Kubernetes官方文档,以下是kind可能的取值:

    Deployment:用于定义应用程序的声明式更新。
    StatefulSet:用于有状态应用程序的声明式更新和管理。
    DaemonSet:用于在集群中运行一个pod的声明式更新和管理。
    Job:用于在集群上运行一次性任务的声明式更新和管理。
    CronJob:用于在集群上运行定期作业的声明式更新和管理。
    Service:用于定义一组pod的逻辑集合,以及访问这些pod的方式。
    Pod:一个Kubernetes中最基本的资源类型,它用于定义一个或多个容器的共同运行环境。
    ReplicaSet:用于确保在集群中运行指定数量的pod的声明式更新和管理。
    ConfigMap:用于存储非敏感数据(如配置文件)的声明式更新和管理。
    Secret:用于存储敏感数据(如密码和密钥)的声明式更新和管理。
    ServiceAccount:用于定义一个pod的身份验证信息,以及与Kubernetes API Server进行交互的权限。
    Ingress:用于定义从外部访问Kubernetes集群中服务的方式。
    PersistentVolume:用于定义持久化存储卷,并使它们在Kubernetes集群中可用。
    StorageClass:用于定义不同类型的存储,例如云存储、本地存储等,并为这些存储类型指定默认的参数和策略。
    Namespace:用于在Kubernetes集群中创建逻辑分区,从而将资源隔离开来,以提高安全性和可维护性。
    ServiceMonitor:用于自动发现和监控在Kubernetes集群中运行的服务。
    HorizontalPodAutoscaler:用于自动调整Kubernetes集群中的pod副本数量,以根据当前负载需求实现自动扩展或收缩。
    NetworkPolicy:用于定义网络访问策略,以控制pod之间的网络流量。
    CustomResourceDefinition:用于定义自定义资源,以扩展Kubernetes APICRD操作。
    PodDisruptionBudget:用于定义维护期间可以安全中断的pod的最小数量,以确保Kubernetes集群的高可用性。
    Role:用于定义对Kubernetes资源的操作权限,例如读、写、更新、删除等。
    ClusterRole:与Role类似,但是可以在整个Kubernetes集群中使用。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    这些kind类型扩展了Kubernetes API的功能,使得Kubernetes更加灵活和强大,可以满足不同场景下的需求。

    参考:
    https://blog.csdn.net/KingCruel/article/details/113775272
    https://blog.csdn.net/bamboo_2001/article/details/129612150
    https://zhuanlan.zhihu.com/p/619273476?utm_id=0
    https://zhuanlan.zhihu.com/p/653147039
    https://blog.csdn.net/cloudflash/article/details/128796673
    https://blog.csdn.net/qq_16253859/article/details/130811097
    https://www.cnblogs.com/linyouyi/p/10691060.html
    https://zhuanlan.zhihu.com/p/654662196

  • 相关阅读:
    mybatisplus和java8一些常用方法总结
    CSS中三栏布局的实现
    Leetcode 74、搜索二维矩阵
    java计算机毕业设计网上花店源码+系统+数据库+lw文档+mybatis+运行部署
    【毕业设计】基于php+mysql+apache的网络数据包分析工具设计与实现(毕业论文+程序源码)——网络数据包分析工具
    JVM基础
    简单的kafka&redis学习之redis
    复旦微FMQL20SM全国产ARM+FPGA核心板,替代xilinx ZYNQ7020系列
    使用json-bigint库处理后端返回数值型数据精度丢失问题
    Linux (redhat)封装虚拟机镜像
  • 原文地址:https://blog.csdn.net/qq_15437629/article/details/134169257