docker入门到精通一文搞定

文章目录


前言

从docker安装到docker容器、docker镜像、docker网络、docker-compose、dockers-swarm、docker-stack等


整理自:bilibili 狂神说

一、Docker概述

1.Docker为什么会出现?

传统应用
缺点1:
一款产品:开发-上线 两套环境! 应用环境,应用配置很麻烦
开发 – 运维。问题,我电脑上可以运行!版本的更新,导致服务不可用了!对于运维人员来说,考验就比较大。
现在情况:开发即运维

缺点2:
环境配置十分麻烦,每一个机器都要部署环境(redis集群、Es集群、Hadoop集群…),费时又费力
发布一个项目:jar+ 环境(redis + mysql + jdk + es等),项目不能带上环境进行打包,配置很麻烦,jar可以跨平台,环境是不能跨平台。如window跨到linux

缺点3:
传统:开发做好jar,剩下运维来做
现在:开发打包部署上线,一套流程做完!
java – apk – 发布(应用商店) — 张三使用apk – 安装即可用!
java – jar (环境) – 打包带上环境 (镜像) – (docker仓库 :商店) – 下载我们发布的镜像 – 直接运行使用

docker的出现:
Dokcer给以上的问题,提出了解决方案。
Docker思想:来源于多集装箱,每个箱子互相隔离
jre – 多个应用(端口错误、配置错误) – 原来环境都是交叉的(用的同一套环境)

2.Docker相比VM技术

vm : linux centos 原生镜像(小型电脑) ,隔离,需要开启多个虚拟机;启动几分钟
缺点:1.资源占用十分多 2.冗余步骤多 3.启动很慢

docker : 隔离,镜像(最核心的环境(4M大小) + jdk + mysql)十分轻巧,运行镜像就可以。启动,秒级别

3.Docker 能做什么?

3.1 比较Docker和虚拟机技术的不同:

  • 传统虚拟机,虚拟出一套硬件,运行一个完整的操作系统,然后在这个系统上安装和运行文件
  • 容器内的应用直接运行在宿主机内核,容器没有自己的内核,也不会虚拟出自己的硬件,轻便
  • 每个容器之间是相互隔离,容器内都有一个属于自己的文件系统,互不影响

3.2 DevOps (开发、运维):4个特点

1、更快速的交付和部署

传统:一堆帮助文档、安装程序
Docker:打包镜像发布测试、一键运行

2、更便捷的升级和扩容

使用了Docker之后,我们部署应用就和搭积木一样 轻松
项目打包为一个镜像,进行扩展。如A服务器出问题了,在B服务器一键运行镜像即可

3、更简单的系统运维

在容器化之后,我们的开发,测试环境都是高度一致的。不出出现本地可以用,线上环境不能用

4、更高效的计算与资源利用(最好的地方)

Docker是内核级别的虚拟化,可以在一个物理机上运行很多个容器实例。服务器性能可以被压榨到极致。

二、Docker安装

1.dokcer架构图:

在这里插入图片描述

2.Docker基本组成:3个大要素

2.1 镜像(image)

docker镜像就好比一个模板,通过这个模板来创建容器对象
如tomcat镜像 ==>run ==> tomcat01容器(容器提供服务,最终服务运行就是在容器中);

2.2容器(container)

Docker利用容器技术,独立运行一个或一组应用,通过镜像来创建的。
启动、停止、删除等基本命令
目前就是可以把一个容器理解为一个建议的linux系统

2.3仓库(repositry)

仓库存放镜像的地方

公有仓库:

DockerHub (默认国外的)
阿里云、华为…(配置镜像加速!)

私有仓库:搭建自己的私有仓库

3.安装 /卸载

# 准备工作
yum -y install gcc
yum -y install gcc-c++

# 1、卸载旧的docker文件
yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
                  
# 2、需要的安装包
yum install -y yum-utils

# 3、设置中央仓库
# 这里是国外的,非常慢
yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

# 这里是国内的,比较快 - 阿⾥云
 yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# 4、安装docker相关的内容,最新的:
#更新yum软件包索引
yum makecache fast

# 5、docker-ce 社区版本(一般使用),docker-ee 企业版
yum install -y docker-ce docker-ce-cli containerd.io

# 6、启动docker
systemctl start docker # 第一步:启动docker服务端
docker version	# 第二步:启动docker服务端后,查看docker版本。不然只能看到docker-client的版本

# 7、运行hello-world
docker run hello-world

# 8、查看下载的hello-world镜像:(每个服务打包成镜像进行发布)
docker images

#了解:卸载docker
yum remove docker-ce docker-ce-cli containerd.io # 卸载安装的docker软件
rm -rf /var/lib/docker #删除docker在系统的数据文件,docker默认的工作路径

# 9、开机启动
sudo systemctl enable docker

4.阿里云镜像加速

1.登录阿里云,找到【容器镜像服务】
2.找到镜像加速地址(每个人地址不一样):
在这里插入图片描述
3.在系统中配置docker加速器,如上图代码

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://dk3u1mig.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

5.docker run的执行流程:

在这里插入图片描述

6.docker底层原理

docker到底是怎么工作的?
docker是一个client-server结构的系统,docker的守护进程运行在宿主机上。通过socket与客户端访问!
docker server接受client指令,就会执行容器命令
在这里插入图片描述

7.docker为什么比VM快?

1.docker有比VM更少的抽象层。
2.docker利用的是宿主机的内核,VM需要GuestOS。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UaYQB6tR-1668762515097)(C:\Users\msi\AppData\Roaming\Typora\typora-user-images\image-20220621150946306.png)]
所以:新建一个容器的时候,docker不需要像虚拟机一样重新加载一个操作系统内核,避免引导。虚拟机是加载的Guest OS,分钟级别的启动。而docker是利用宿主机的操作系统,省略了这个复杂过程,是秒级别启动!

3.docker与vm对比
在这里插入图片描述

三、Docker常用命令(非常多)

1.帮助命令

docker version # 显示docker版本信息
docker info #显示docker的系统信息,包括镜像和容器
docker 命令 --help # 帮助命令;如docker images --help

帮助文档地址:docker官方帮助文档
在这里插入图片描述

2.镜像命令

2.1 docker images

查看所有本地主机上的镜像

docker images # 列出所有镜像
# 可选项
-a, --all 	# 列出所有镜像
-q, --quiet # 只显示镜像的id

2.2 docker search

搜索远程镜像

docker search mysql
# 可选项
-f 过滤 # --filter=STARS=3000
例子:docker search mysql --filter=STARS=3000
docker search mysql -f=STARS=3000

2.3 docker pull

远程拉取镜像到本地

docker pull mysql
或
docker pull mysql[:tag] # tag版本,一般都会加上版本 (通过分层下载,联合文件系统)

# 两个命令等价
docker pull mysql = docker pull mysql:5.7

2.4 docker rmi

删除镜像

docker rmi -f 镜像名/镜像ID	# -f 强制,多个删除用空格区分
docker rmi -f $(docker images -qa)	# 删除所有本地镜像

3.容器命令

说明:有了镜像才能创建容器,以下载一个centos镜像来测试学习

docker pull centos

3.1docker run

新建容器并启动

docker run [可选参数] image 

#参数说明
--name="name"  	容器名字,用来区分容器
-d				后台方式运行
-it				使用交互方式运行,进入容器查看内容
-p				指定容器的端口 -p 8080:8080
	-p ip:主机端口:容器端口 # ip是主机ip吗?
	-p 主机端口:容器端口(常用)
	-p 容器端口
	容器端口
-P 				随机指定端口

# 测试:启动并进入容器
[root@localhost ~]# docker run -it centos /bin/bash
[root@1e973315dad7 /]# 	# 启动已经进入了容器,是一个最初版的centos
[root@1e973315dad7 /]# exit; # 停止并退出容器

3.2docker ps

查看所有在运行的容器

docker ps		# 正在运行的
docker ps -a 	# 曾经运行的+正在运行的容器
docker ps -n=? 	# 最近创建的容器,显示数量-n。
docker ps -q 	# 只显示容器的id
#eg: docker ps -a -n=2 # 显示最近的两个容器

进入容器后退出容器

exit 		# 停止并退出容器
ctrl+P+Q	# 容器不停止且退出

3.3docker rm

删除容器

docker rm 容器id	# 移除单个,如果要强制删除需要加参数:-f
docker rm -f $(docker ps -qa)	  # 删除所有容器
docker ps -a -q | xargs docker rm # 删除所有的容器

3.4 容器启动、重启、关闭

docker start 容器ID	#启动容器
docker restart 容器ID #重启容器
docker stop 容器ID 	#关闭容器
docker kill 容器ID	#强制关闭容器

4.其他常用命令

4.1后台启动命令

docker run

# 命令 docker run -d 镜像名
docker run -d centos
	#存在问题:docker ps时发现centos停止了
	#常见的坑:docker容器后台运行,必须要有一个前台进程,如果docker发现没有cli,那么后台应用就会自动停止
	#启动nginx,容器启动后,发现自己没有提供服务,就会立即停止。

4.2日志命令

docker logs

docker logs -f -t --tail n 容器ID # n日志条数,t 时间戳;f 规范显示format

# 自己写一段shell脚本
"while true;do echo biebiebie;sleep 1;done"
docker run -d centos /bin/sh -c "while true;do echo biebie;sleep 1;done"

4.3查看容器中进程信息

docker top 容器ID

4.3查看容器内部元数据

docker inspect 容器ID

4.4 进入正在运行的容器

# 方式一:docker exec
docker exec -it 容器ID /bin/bash # /bin/bash:通过哪个命令行进入容器,还有/bin/sh

# 方式二:docker attach 
docker attach 容器ID
正在运行的代码.....

#docker exec	#开启新的终端进入正在运行的容器,可以操作命令(常用)
#docker attach  #进入容器正在执行的终端,不会启动新的终端

4.5 从容器内拷贝文件到主机上

docker cp 容器ID:容器内路径 目的主机路径

4.6 从主机拷贝文件到容器

挂在的方式

5.docker各模块命令交互图

在这里插入图片描述

6.docker安装nginx(练习)

#1.启动docker服务,并搜索镜像;建议先看hub.docker.com上进行搜索
docker search nginx
#2.远程下载镜像
docker pull nginx:[版本号]
#3.启动nginx
docker run -d  --name nginx01 -p 3344:80 nginx
#4.测试是否启动成功:成功
curl localhost:3344
	
	#安装curl包
	#1.下载
	wget --no-check-certificate https://curl.haxx.se/download/curl-7.80.0.tar.gz
	#2.解压
	tar zxvf curl-7.80.0.tar.gz
	#3.执行配置文件
	cd curl-7.80.0
	./configure
	#4.make编译
	make


# 进入容器查看容器ip:cat /etc/hosts
# 外部查看:docker inspect 容器ID/名称

7.docker端口暴露的概念:

在这里插入图片描述
思考:我们每次改动nginx配置文件,都需要进入容器内部,很麻烦,可以通过容器外部修改直接映射到内部文件吗? -v(数据卷技术)

8.docker安装tomcat

# 官网使用
docker run -it --rm tomcat:9.0 # --rm:容器运行停止后即删除,一般用于测试

# 下载启动
docker  pull tomcat

# 启动运行
docker run -d -p 3355:8080 --name tomcat01 tomcat:[TAG]

#测试,启动成功

#进入容器
docker exec -it tomcat01 /bin/bash
# 发现问题:1.linux命令少了很多 2.在tomcat的webapps里面没内容
# 原因:阿里云的镜像的原因:阿里云镜像默认是最小镜像,所有不必要的内容都会剔除

9.docker部署 es + kibana

9.1es安装

# es 暴露的端口很多
# es 十分耗内存
# es 的数据一般需要存放到安全目录! 即挂载

# 1.下载镜像与启动:
docker run -d --name elasticsearch  -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
#其中:--net somenetwork是docker的网络配置

# 2.启动完之后,linux卡死了
docker stats # 查看docker CPU的状态

# 3.测试es是否启动成功
docker ps

# 4. 赶紧关闭,增加内存的限制。修改es的配置文件 
-e 环境修改
docker run -d --name elasticsearch02  -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2

docker ps # 查看docker进程
在这里插入图片描述

9.2安装kibana连接es

思考:网络如何联通?
在这里插入图片描述

10.可视化-管理镜像的工具

10.1 portainer (不是最佳)

什么是portainer?
dokcer图像化界面管理工具。提供一个后台面板供我们操作

# 1.拉取镜像安装并启动
docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer

# 2.测试是否启动成功
在宿主机上执行:curl localhost:8088

# 3.通过浏览器访问:如下图
宿主机ip:8088  -> 192.168.229.131:8088

在这里插入图片描述

# 4.一般连接选择本地,如下图

在这里插入图片描述

# 5.进入之后的面板

在这里插入图片描述

10.2 Rancher (CI/CD再用)

四、Docker镜像(核心)

学完镜像才算入门docker

镜像是什么?

镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件。
它包含运行某个软件所需要的所有内容:包括代码、运行时、库、环境变量和配置文件。
所有的应用,直接打包成docker镜像,就可以直接跑运行了。方面扩展和部署

如何得到镜像:

- 从远程仓库下载
- 朋友拷贝
- 自己制作一个镜像,Dockerfile

1.Docker镜像加载原理

UnionFS(联合文件系统) :

UnionFS(联合文件系统):UnionFS文件系统是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同事可以将不同的目录挂在到同一个虚拟文件系统下。UnionFS是docker镜像的基础,镜像可以通过分层来进行继承,基于基础镜像(没有父镜像)可以制作各种具体的应用镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录
联合文件系统类似于git的版本提交

Docker镜像加载原理

docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统就是UnionFS
bootfs(boot file system)引导文件系统。主要包含了bootloader和kernel,bootloader主要引导加载kernel,Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与典型的Linux/Unix系统是一样的,包含boot加载器和啮合。当boot加载器完成之后整个内核就在内存中了,此时内存的使用权有bootfs转交给内核,此时系统也会写在bootfs。
rootfs(root file system)根文件系统,在bootfs智商。包含的就是典型Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。footfs就是各种不同的操作系统发行版,比如ubuntu,Centos等

在这里插入图片描述

思考:平常我们安装虚拟机centos都是好几个G,为什么Docker这里才200M?
在这里插入图片描述

对于一个精简的OS,rootfs可以很小,只需要包含最基本的命令,工具和程序库就可以了。因为底层直接用Host和kernel,自己只需要听过rootfs就可以了。由此可见对于不同的linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以公用bootfs。

2.镜像分层理解

分层的镜像

在下载镜像时,观察下载时输出的日志,可以看到是一层一层的在下载!如图:
在这里插入图片描述

思考:为什么docker镜像要采用这种分层的结构呢?
答:最大的好处就是资源共享了! 比如有多个降序都从相同的base镜像构建而来,那么宿主机啊只需要在磁盘上保留一份base镜像,同事内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像是每一次都可以被共享的。

思考:为什么docker的继承只需要加载一次基础镜像而java中基础需要每次加载基类?
答:java中的继承是有状态的,需要记录每个基类的数据。docker继承是无状态的,所以只加载存储一次即可

查看镜像分层的方式可以通过docker image inspect命令
理解:所有的dokcer镜像都起始于一个基础镜像,当进行修改或增加内容时,就会在当前镜像层之上,创建新的镜像层。

例子:假如基于Ubuntu Linux 16.04创建一个新的镜像,这就新镜像的第一层;如果在该进行中添加Python包,就会在基础镜像层之上创建第二个镜像层;如继续添加一个安全补丁,那么就会创建第三个镜像层。

如下图:
在这里插入图片描述
在添加额外的镜像层的同时,镜像始终保持当前所有镜像的并集组合。如下如每层镜像3个文件,打包镜像时会有6个文件,分别来自于不同的镜像层。

如下图:
在这里插入图片描述
下图中展示了稍微复制的三层镜像,在外部看来整个镜像只有6个文件,这是因为文件7是文件5的更新版
在这里插入图片描述

这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件,这样就是的文件的更新版本作为一个镜像层添加到镜像中。
Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。
Linux上可用的存储引擎有AUFS、Overlay2、Device Mapper、Btrfs以及ZFS。顾名思义,每种存储引擎都是基Linux中对应的文件系统或者快设备技术,并且每种存储引擎都有自己的特点。
Docker在Windows上仅支持windowsFilter这一种存储引擎,并且该引擎基于NTFS文件系统之上实现了分层和CoW[1]。

下图展示了与文件系统相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图
在这里插入图片描述

特点
Docker现有pull的镜像都是只读的,当容器启动时,一个新的可写层被加载到docker现有镜像层的顶部,这一层就是容器层,容器之下的都是镜像层。
我们对容器的所有操作都是正在新建一个自己的镜像层,容器commit提交就成为一个新的镜像。

3.commit:容器提交为新的镜像

命令:docker commit 
解释:提交一个容器成为新的镜像副本

# 命令和git命令类似
docker commit -m="提交描述信息" -a="作者" 容器ID 目标镜像名:[TAG]

以tomcat为例子提交新镜像

# 1、启动一个默认的tomcat
# 2、发现这个默认的tomcat是没有webapps应用,是因为镜像纯净的原因。官方的镜像默认webapps文件夹下是没有文件的
# 3、自己拷贝进去了基本文件
# 4、讲文明操作过的容器通过commit提交为一个镜像(提交的镜像会保存在docker本地,与git也类似),我们以后就使用这个新提交的镜像即可
[root@localhost ~]# docker commit -a="bie" -m="add webapps app" 70b6e29900d3 tomcat02:1.1
# 5、如下图

在这里插入图片描述
学习方式说明:理解概念,但是一定要实践,最后理论和实践相结合一次搞定这个知识。

五、容器数据卷(核心)如何挂载

docker精髓:容器数据卷、DockerFile、Docker网络原理三项

什么是容器数据卷

数据?如果数据都在容器中,那么我们删除容器,数据就会丢失! 需求:数据可用持久化
mysql安装在docker容器中,容器删除 = 删库跑路! 需求:mysql数据可以存储在本地

容器之间可以有一个数据共享的技术! 卷技术,容器挂载(容器内的目录,挂载到宿主机)
总结:容器的持久化和同步操作!容器间也是可以数据共享的!

使用数据卷:
1.volumns挂载
2.mounts挂载

docker run -it -v 主机目录:容器目录

# 1.执行命令进行挂载
docker run -it -v /home/ceshi:/home centos /bin/bash

# 2.测试,在容器home目录下创建test.txt
结果:宿主机目录下 /home/cesh 有test.txt文件

# 3.docker inspect 容器id/容器名

在这里插入图片描述

1.安装mysql

思考:mysql的持久化问题?data目录挂载

会占用两倍存储空间

# 1.远程下载mysql镜像
docker pull mysql:5.7

# 2.启动mysql
docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7

# 注意:conf.d文件为空,正常,需要人为配置

# 3.测试:启动成功后用sqlyog或navicat连接
telnet 192.168.229.131 3310 # 允许登录

2.具名挂载和匿名挂载

# 1.匿名挂载
-v 容器内路径!
-P 随机映射端口 -p指定映射端口

docker run -d -P --name nginx01 -v /etc/nginx nginx

#查看所有挂载映射
docker volume ls 
如下显示:
DRIVER    VOLUME NAME
local     8a5ae8e2f309a8619fdfb873ce561883498cc1a04572899f0e174548137f45fb	#匿名挂载,是真实存在的目录
local     9ba4a4c682727d7584f9143788d66491d9bb267c23b659e002b8b9987379c487  #匿名挂载,是真实存在的目录


# 2.具名挂载
docker run -d -P -v juming-nginx:/etc/nginx --name nginx02 nginx
docker volumn ls
如下显示:
DRIVER    VOLUME NAME
local     8a5ae8e2f309a8619fdfb873ce561883498cc1a04572899f0e174548137f45fb
local     9ba4a4c682727d7584f9143788d66491d9bb267c23b659e002b8b9987379c487
local     juming-nginx	# 具名挂载

下图中:inspect时,Name就是挂载名
在这里插入图片描述

几种挂载语法

# 3.几种挂载-v的写法:
匿名写法:
-v /宿主机路径:容器内路径 	# 带/绝对路径,没有名字,例子:-v /home/nginx:/etc/nginx
-v 容器内路径 		# 例子:-v /etc/nginx

具名写法:
-v 卷名:容器内路径 	# 例子:-v juming-nginx:/etc/nginx 

# 4.总结
所有docker容器内的卷,没有指定目录的情况下都是在"/var/lib/docker/volumes/xxxxx(卷名)/_data"

docker工作目录:"/var/lib/docke"

在这里插入图片描述

# 5.拓展
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx # ro:只读,只能宿主机改变内容,容器内无法改变此目录及数据
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx # rw:可读写,默认情况

3.初始dockerfile:脚本生成镜像

Dockerfile就是用来构建docker镜像的文件!实际上就是命令脚本,通过脚本生成镜像
之前有commit构建docker镜像

# 1.编写dokcerfile文件,脚本如下:
FROM centos #基于centos镜像

VOLUME ["volume1","volume2"] # 这里的写法就是匿名挂载,只写了容器内的目录

CMD echo "---------------end----------------"

CMD /bin/bash

# 2.运行脚本
docker build -f /home/docker-test-volume/dockerfile1 -t kuangshen-centos:1.0 .
#-f 脚本路径; -t 打包版本 ;.标示存放位置

# 3.查看镜像是否构建成功
docker images;

# 4.启动自己构建的镜像
docker run -it kuangshen-centos /bin/bash

发现挂载目录如下图:
在这里插入图片描述

4.数据卷容器(是一个容器):多个dokcer容器共享一份数据(备份机制)

被挂载的容器:就是数据卷容器
在这里插入图片描述
启动3个容器进行测试:

#启动数据卷容器:
docker run -it --name docker01 kuangshen-centos:1.1

#启动第2个容器:
docker run -it --name dokcer02 --volumes-from docker01 kuangshen-centos:1.1

#启动第3个容器:
docker run -it --name dokcer03 --volumes-from docker01 kuangshen-centos:1.1

#启动第4个容器:挂载docker02上
docker run -it --name dokcer04 --volumes-from docker02 kuangshen-centos:1.1

命令:--volumes-from 类似于java的继承

#测试,删除docker01之后,其他容器中的挂载目录还是有数据
#总结:只要有一个容器还在运行,那么数据就不会丢失

使用docker进行mysql数据同步:

docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7

docker run -d -p 3311:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumns-from mysql01 mysql:5.7

(测试时:数据挂载成功了。通过ssh链接时,哪台先开启,就可以连接上哪台。调换先后顺序后,发现创建的数据库test成功,没过3分钟,后启动的mysql自动挂了,很奇怪的现象)

小结:
容器之间配置的信息传递,数据卷容器的生命周期一直持续到没有容器使用为止。
但一旦持久化到宿主机,这个时候宿主机的数据是不会删除的。

六、DockerFile

1.DockerFile介绍

dockerfile是用来构建docker镜像的文件,是一个命令参数的脚本!
构建步骤:
1、编写一个docker文件
2、docker build构建成为新的镜像
3、docker run运行镜像
4、docker push发布镜像(DockerHub,阿里云镜像仓库)
追问:有本地镜像仓库?

2.Dockfile的构建过程

DockerFile的基础知识

1.每个保留关键字(指令)都必须是大写字母
2.执行顺序从上到下
3.#标示注释
4.每一更的指令都会创建提交一个新的镜像层,并提交
在这里插入图片描述
dockerfile是面向开发的,我们以后要发布项目,做镜像就需要编写dockerfile文件,这个文件十分简单。
docker镜像已经成为开发交付的一个趋势,逐步取代jar,war包

步骤:开发,部署,运维,缺一不可
Dockerfile:构建文件,定义了一切的步骤,原代码
DockerImages:通过dockerfile构建生成的镜像,最终发布和运行的产品
Docker容器:容器就是镜像运行起来提供服务器

3.Dockfile的指令

以前都是我们使用别人的,现在我们知道这些指令后,自己练习写一个镜像

FROM		#基础镜像,一切从这里开始构建
MAINTAINER 	#镜像作者,姓名+日期
RUN			#镜像构建的时候需要运行的命令
ADD			#添加文件,如步骤:tomcat镜像,添加tomcat的压缩包
WORKDIR		#镜像的工作目录
VOLUMES		#挂载的目录
EXPOSE		#暴露端口
CMD			#指定这个容器启动时需要运行的命令,只有最后一个会生效。有覆盖动作
ENTRYPOINT 	#指定这个容器启动时需要运行的命令,是追加,无覆盖动作
ONBUILD		#当构建一个被继承Dockfile这个时候就会运行ONBUILD命令
COPY		#类似ADD,将我们文件拷贝到镜像中
ENV			#构建的时候设置环境变量

在这里插入图片描述

4.实战一:构建自己的centos

DockerHub中99%的镜像都是从这个基础镜像构建而来的(FROM scratch)
在这里插入图片描述

在原有的centos上,添加vim包和ipconfig包

# 1.编写自己的dockerfile文件
FROM centos # FROM cenos1
MAINTAINER biejiahao<729941382@qq.com>

ENV MYPATH /usr/local
WORKDIR $MYPATH

RUN yum -y install vim 
RUN yum -y install net-tools

EXPOSE 80
CMD echo $MYPATH
CMD echo "------end-------------"
CMD /bin/bash

#2.通过这个文件构建镜像
# 命令:docker build -f dockerfile文件路径 -t 镜像名:[TAG] .
本地测试时,这里有问题:
需要将原始centos upstream后发布新版的cenos1,然后再进行build操作
地址:https://blog.csdn.net/weixin_43252521/article/details/124409151

构建成功输出的信息:
Successfully built bf40fedf541b
Successfully tagged mycentos:0.1

# 3.测试运行
docker run -it mycentos:0.1 /bin/bash
vim test.java # 成功
ifconfig # 成功

# 4.查看镜像构建历史
docker history 镜像id

在这里插入图片描述

5.CMD 与ENTRYPOINT的区别

CMD #指定这个容器启动时需要运行的命令,只有最后一个会生效。有覆盖动作
ENTRYPOINT #指定这个容器启动时需要运行的命令,是追加,无覆盖动作

6.CMD进行dockerfile测试

#1 编写dockerfile-cmd的dockerfile文件
FROM centos
CMD ["ls","-a"]

#2 build成为新镜像
docker build -f dockerfile-cmd -t centos-cmd:1.0 .

#3 测试启动centos-cmd:1.0镜像
docker run centos-cmd:1.0 # 成功

#4.测试加参数,本意想表达 ls -al命令
docker run centos-cmd:1.0 -l # 控制台报错

7.ENTRYPOINT进行dockerfile测试

#1 编写dockerfile-entrypoint的dockerfile文件
FROM centos
ENTRYPOINT ["ls","-a"]

#2 build成为新镜像
docker build -f dockerfile-entrypoint -t centos-entrypoint:1.0 .

#3 测试启动centos-cmd:1.0镜像
docker run centos-entrypoint:1.0 # 成功

#4.测试加参数,本意想表达 ls -al命令
docker run centos-entrypoint:1.0 -l # 成功

8.实战二:构建tomcat镜像

1.准备镜像文件tomcat压缩包,jdk压缩包
在这里插入图片描述
2.编写dockerfile文件,官方命名Dockerfile,build时会自动寻找这个文件并执行,就不需要 -f 指定文件了。

FROM cenos1
MAINTAINER biejihao<729941382@qq.com>

COPY readme.txt /usr/local/readme.txt

ADD jdk-8u301-linux-x64.tar.gz /usr/local
ADD apache-tomcat-8.5.81.tar.gz /usr/local

RUN yum -y install vim

ENV MYPATH /usr/local
WORKDIR $MYPATH

ENV JAVA_HOME /usr/local/jdk1.8.0_301
ENV CLASSPATH $JAVAHOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.81
ENV CATALINA_BASH /usr/local/apache-tomcat-8.5.81

ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin

EXPOSE 8080

CMD /usr/local/apache-tomcat-8.5.81/bin/startup.sh && tail -F /usr/local/apache-tomcat-8.5.81/bin/logs/catalina.out

3.构建镜像

#1.进入到dockerfile文件目录
#2.执行构建命令
docker build -t diytomcat:1.0 .

4.启动镜像

docker run -d -p 9090:8080 --name kuangshentomcat -v /home/build/tomcat/test:/usr/local/apache-tomcat-8.5.81/webapps/test -v /home/build/tomcat/tomcatlogs:/usr/local/apache-tomcat-8.5.81/logs diytomcat:1.0

5.访问测试

curl localhost:9090
# 如果访问不到,就是tomcat没有启动成功
# 1.先排除启动命令是否有误 2.再排除dockerfile脚本是否有误(第一次多半是脚本问题)

6.发布项目(由于做了卷挂载,那么直接在宿主机进行发布项目即可)

在宿主机挂载的test目录进行操作:
mkdir WEB-INF
cd WEB-INF
vim web.xml

web.xml内容

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
        
</web-app>

将index.jsp文件存放到项目test目录下

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<h2>Hello World!</h2>
 
 <%
 System.out.println("--------------test---------------------");
 %>
 
</body>
</html>

启动新的tomcat容器

结果:通过浏览器可以访问成功,并且后台日志可以记录访问信息

9.发布镜像到dockerhub

1.需要注册账号:hub.docker.com
2.确定这个账号可以登录即可
docker login -u 账号 -p 密码
3.在服务器上提交自己的镜像
docker push 镜像名:[tag]

10.发布到阿里云镜像服务

1.登录阿里云
2.找到容器镜像服务
3.创建命名空间(是一个和大的项目组)
在这里插入图片描述4.创建容器镜像(创建时,选择本地仓库)
在这里插入图片描述
5.浏览阿里云信息
在这里插入图片描述
6.退出dockerhub账号
dokcer logout

7.登录阿里云账号
参考第五点做法

小结

在这里插入图片描述

七、Docker网络原理

1.理解dokcer0

理解docker网络,就是理解dokcer0的网络:docker0=路由器 网络请求中转
清空所有的镜像与容器,方便学习docker网络时的理解
在这里插入图片描述

# 启动一个tomcat
docker run -d -P  --name tomcat01 tomcat
# 查看容器的内部网络地址 ip addr,发现容器启动的时候会得到一个eth0@if262 ip地址是docker分配的
docker exec -it tomcat01 ip addr

# 异常请参考文章:https://blog.csdn.net/User_bie/article/details/125642454

在这里插入图片描述

# 思考:linux宿主机能不能ping通容器内部? 答案:可以
> ping 172.17.0.2

PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.077 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.037 ms
.....

2.网络原理

1、每启动一个docker容器,docker就会给容器分配一个ip,完美只要安装了docker就会有一个dokcer0网卡
利用的是桥接模式,使用的是evth-pair技术
宿主机再次测试ip addr
在这里插入图片描述
2、再次启动一个新的容器,发现又多了一对网卡
在这里插入图片描述

# 我们发现这个容器带来网卡,都是一对一对
# evth-pair就是一对虚拟设备接口,都是成对出现,一端连着协议,一端彼此相连
# 正因为有了这个特性,一般用evth-pair充当一个桥梁,专门连接各种虚拟网络设备
# Openstac,docker容器之间的连接,OVS的连接,都是使用的是evth-pair技术

3、测试tomcat01是否可以ping同tomcat02 答:可以

结论:tomcat01与tomcat02是公用一个路由器,dokcer0
所有容器在不指定网络的情况下,都是通过docker0进行路由,docker0会给容器分配一个默认可用的IP。可用ip数为254个
如:17.18.0.1/16 则可以分配 255*255 - 2(0.0.0.0 与255.255.255.255)个ip
如:17.18.0.1/24 则可以分配 255-1(17.18.0.1)=254 个ip

小结

Docker使用的是linux的桥接:
在这里插入图片描述
dokcer中所有的网络接口都是虚拟的。虚拟的转发效率高!
在这里插入图片描述

3.- - link

思考:

场景,编写一个微服务,database url=ip,项目不重启,数据库ip换了,能否根据名称访问容器而不根据ip访问。因为docker容器每次启动ip都是会变化的
在这里插入图片描述
探究:docker network inspect
在这里插入图片描述

docker --link 本质:hosts配置

–link后,会在/etc/hosts配置文件中添加一份映射
在这里插入图片描述
目前已经不推荐使用docker0,需要自定义网络:docker0不支持 容器名连接访问

4.自定义网络:容器互联

查看所有的docker网络
在这里插入图片描述
网络模式:
bridge:桥接docker(默认)
none:不配置网络,不建议
host:和宿主机共享网络
container:容器网络连通(用的少,局限性很大,不建议)

测试:

#1.直接启动的命令 --net bridge 这个参数是默认使用的,即代表dokcer0
docker run -d -P --name tomcat01 --net bridge tomcat

# docker0 特点: 默认网络,域名不能访问, --link可以打通进行连接

#2.我们可以自己定义一个网络,以后启动的容器就在自己定义的网络内运行
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mybet

--driver 网络连接方式
--subnet 子网
--gateway 子网网关
#家用所有的路由器都是这个网络配置

#3.查看当前docker网络
docker networkd ls
#成功

f5aae4c0d555   bridge    bridge    local
66ad3244c031   host      host      local
c54074b0a393   mybet     bridge    local
044d666dd3d7   none      null      local

#4.使用自定义网络启动tomcat
docker run -d -P --name tomcat-net-01 --net mybet tomcat
docker run -d -P --name tomcat-net-02 --net mybet tomcat

#5.再次两个容器进行ping
docker exec -it tomcat-net-01 ping 192.168.0.3  #192.168.0.3为tomcat-net-02的ip
#成功
docker exec -it tomcat-net-01 ping tomcat-net-02 
#成功

自定义的网络docker已经帮我们维护好了对应的网络关系,推荐平时使用自定义网络
好处:
mysql/redis:不同的集群使用不同的网络,保证集群是安全和健康的

5.docker网络连通

如mysql集群需要访问不同网段的redis集群
在这里插入图片描述

A网络容器需要与B网卡连通,才能访问B网段下的服务
在这里插入图片描述

# 测试tomcat01连通mybet网络
docker network connect mybet tomcat01

# 如下图:连通之后,直接会把这个容器加入到这个网络中
# 这种情况再docker中称为一个容器两个ip,比如阿里云服务器,公网ip与私网ip

在这里插入图片描述

结论:假设要跨网络操作,需要使用docker network connect进行连通

6.实战:部署redis集群

redis cluster 多主从集群
在这里插入图片描述

# 1.创建redis集群网络
docker network create redis --subnet 172.38.0.0/16

# 2.通过脚本创建6个redis配置
for port in $(seq 1 6); \
do \
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF >/mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF

docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} \
-v /mydata/redis/node-${port}/data:/data \
-v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; \

done

#3.创建redis集群
#3.1进入到某个redis # 以3-master为例
docker exex -it 82a74538a215 /bin/sh

#3.2执行创建集群
redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1

#3.3中途执行yes

# 注意redis-cli操作集群时,登录需要加参数-c,如:redis-cli -c

小结:使用了docker之后,所有的技术使用的更简单

7.springboot项目打包docker镜像

1.架构springboot项目
2.打包应用
3.编写dockerfile

FROM java:8

COPY *.jar /app.jar

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

EXPOSE 8080

ENTRYPOINT ["java","-jar","/app.jar"]

4.构建镜像
5.发布运行

八、IDEA整合Docker

docker单机版(一至八点)

九、Docker Compose (编排管理,单机环境管理)

简介

Docker Compose轻松高效来管理容器,定义运行多个容器,一键上线。
Compose是Docker官方的开源项目,需要安装。
Dockerfile 文件能让程序再任何地方运行。web服务,redis,mysql,nginx…多个容器

version: "3.9"  # optional since v1.27.0
services:
  web:
    build: .
    ports:
      - "8000:5000"
    volumes:
      - .:/code
      - logvolume01:/var/log
    links:
      - redis
  redis:
    image: redis
volumes:
  logvolume01: {
    
    }

Compose:2个重要概念
服务services:容器-应用(web/redis/mysql…)
项目project:一组关联容器。如博客,web项目,mysql等

1.安装

# 1.国外镜像,下载慢
curl -SL https://github.com/docker/compose/releases/download/v2.6.1/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose

# 国内镜像,下载很快
sudo curl -L https://get.daocloud.io/docker/compose/releases/download/v2.6.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose

# 2.文件授权
sudo chmod +x /usr/local/bin/docker-compose

# 3.是否安装成功
docker-compose --version


卸载:

2.测试与体验app.py

官网:https://docs.docker.com/compose/gettingstarted/
1.创建应用

#1.创建一个文件夹
cd /home && mkdir composetest && cd composetest

#2.创建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)


#3.创建文件requirements.txt需要导入的包
内容:
flask
redis

2.创建dockerfile

# 创建Dockerfile文件,目录/home/composetest
vim 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"]

3.创建docker-compose.yml文件(定义整个服务,需要的环境。web redis mysql 等),完成的上线服务

# 创建docker-compose.yml文件,目录/home/composetest
vim docker-compose.ym

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

4.构建和运行compose

#目录下执行:/home/composetest
docker compose up

5.停止compose

cd /home/composetest && docker-compose stop 
crl + c

3.compse启动流程:docker-compose up

1、创建compose网络
2、执行docker-compose.yml
3、启动服务:

⠿ Network composetest_default Created 0.3s
⠿ Container composetest-redis-1 Created 0.1s
⠿ Container composetest-web-1 Created 0.1s

docker-compose up:执行后,会自动下载镜像并启动

[root@localhost ~]# docker service ls;# 查看所有服务
Error response from daemon: This node is not a swarm manager. Use "docker swarm init" or "docker swarm join" to connect this node to swarm and try again.

默认的服务名:文件名_服务名 _num
注意:_num:副本数量

4.docker-compose 网络规则

#1.查看docker网络
docker network ls;

#2.查看docker-compose默认网络下的应用
docker network inspect 240d9f259d39

#3.如下图,通过compose启动的项目都在同一个网段下,可以通过域名直接访问调用,不用通过ip进行访问

在这里插入图片描述

在这里插入图片描述

docker小结:

1.docker镜像,run=>容器
2.dockerfile构建镜像,服务打包
3.docker-compse启动项目(编排,多个微服务/环境)
4.精通docker网络

6.yaml规则

# 可以理解为核心3层
version: '' 	# 版本

services: 		#服务
  服务1: web
  	#dokcer容器配置
  	images
  	build
  	network
  
  服务2: redis

#其他配置 网络/卷/全局规则等
volumes:
networks:
configs:

7.compose测试:一键启动博客

#1.home目录下创建文件夹:
cd /home && mkdir my_wordpress && cd my_wordpress/

#2.编写docker-compose.yml文件
services:
  db:
    # We use a mariadb image which supports both amd64 & arm64 architecture
    image: mariadb:10.6.4-focal
    # If you really want to use MySQL, uncomment the following line
    #image: mysql:8.0.27
    command: '--default-authentication-plugin=mysql_native_password'
    volumes:
      - db_data:/var/lib/mysql
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=somewordpress
      - MYSQL_DATABASE=wordpress
      - MYSQL_USER=wordpress
      - MYSQL_PASSWORD=wordpress
    expose:
      - 3306
      - 33060
  wordpress:
    image: wordpress:latest
    ports:
      - 80:80
    restart: always
    environment:
      - WORDPRESS_DB_HOST=db
      - WORDPRESS_DB_USER=wordpress
      - WORDPRESS_DB_PASSWORD=wordpress
      - WORDPRESS_DB_NAME=wordpress
volumes:
  db_data:
  
# 3.启动
docker-compose up -d
docker-compose up

8.compse实战:计数器

1.编写微服务项目
2.编写Dockerfile文件,构建镜像

FROM java:8

COPY *.jar /app.jar

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

EXPOSE 8099

ENTRYPOINT ["java","-jar","/app.jar"]

3.编写docker-compose.yml文件,编排项目

version: '3.8'
services:
  kuangapp:
    build:
      dockerfile: Dockerfile
    image: kuangapp
    depends_on:
      - redis
    ports:
      - "8080:8080"
  redis:
    image: "redis:alpine" # 精简版本

4.丢到服务器

1.创建kaungapp目录:在目录下操作
2.启动
docker-compose up -d

小结:未来项目只要有dokcer-compose文件。按照这个规则,启动编排容器

假设项目要重新部署打包:

docker-compose up --build # 重新构建镜像

9.总结:

工程、服务、容器

项目compose:三层

  • 工程project
  • 服务
  • 容器 运行实例 docker k8s等

十、Docker Swarm (集群) - 简化版本的k8s

集群方式的部署、需要购买4台阿里云服务器,2核心4G。swarm暂时买的1核2G

k8s需要2核4G
在这里插入图片描述

1.swarm节点工作模式:

在这里插入图片描述

2.swarm服务工作模式:

3.搭建集群

#1.初始化一个swarm节点 docker-1机器上操作
docker swarm init --advertise-addr 本机ip

在这里插入图片描述

#得到上图两个命令:
# 添加一个工作节点:其他docker机器上操作
docker swarm join --token SWMTKN-1-2lp87oe4q6ez6ehnqz3hs9887hjpe4prasxnafa8y0rsu13q8s-1idmuvh3lojmua824wxgw15ev 172.16.0.105:2377

 # 获取一个节点的token,manager的token与worker加入的节点token是不一样的
docker swarm join-token manager
# 添加一个管理节点
docker swarm join --token SWMTKN-1-2lp87oe4q6ez6ehnqz3hs9887hjpe4prasxnafa8y0rsu13q8s-6lxrwnpfoazek2qzfjirda7qs 172.16.0.105:2377


docker swarm join-token work

在这里插入图片描述

docker node ls;

在这里插入图片描述
在这里插入图片描述1与4主节点。2与3从节点

4.Raft一致性协议:

目前是双主双从:假设一个节点挂了,其他节点是否可用
raft协议:保证大多数节点存活才可以用。集群至少大于3台

5.实验:

将docker1停止(宕机),双主双从的情况下,docker4能否可用?答:不可用
在这里插入图片描述
重启dokcer1机器后,docker1不是leader了,docker4升级为leader

docker swarm leave #如下

在这里插入图片描述
目前1.3.4是主节点:

集群中:至少要保证3个主节点。必须要保证2台主机存活这个集群才可用。

raft协议:保证大多数节点存活,才可以使用,高可用

6.swarm集群弹性创建服务(集群的扩缩容)

在这里插入图片描述
灰度发布:金丝雀发布
docker service create -p 8888:80 --name my-nginx nginx
在这里插入图片描述

1.docker run 容器启动,不具备扩缩容器
2.docker service 服务启动,具备扩容容器,滚动新
dokcer service ls;

在这里插入图片描述

docker service update --replicas 3  my-nginx 

在这里插入图片描述
注意:外网访问不到,需要配置阿里云安全组,开放端口8888
动态扩缩容

服务,集群中任意的节点都可以访问。
服务可以有多个副本动态扩缩容来实现服务高可用

docker service scale my-nginx=5

docker service scale my-nginx=1

7.概念总结

在这里插入图片描述

swarm
集群的管理和编排,docker可以初始化一个swarm集群,其他节点可以加入。(管理或工作者)

node:
就是一个docker节点,docker节点就组成了一个集群网络

service
任务,可以再管理节点或工作节点来运行,核心!

task:
容器内的命令,细节任务

8.Docker Stack

docker-compose 单机项目部署
dockerstack 集群部署

#单机
docker-compose up -d wordpress.yml
#集群
docker stack deploy wordpress.yml

9.Docker Secret

安全!配置密码,证书!

10.Docker Config

配置,统一的配置

十一、CI/CD Jenkins 持续集成与持续交付,持续部署

CI/CD Jenkins 持续集成与持续交付,持续部署

十二、docker相关组件原理

http://t.zoukankan.com/goloving-p-14988269.html

十三、docker安装es

猜你喜欢

转载自blog.csdn.net/User_bie/article/details/127925649