Docker基础讲解狂神笔记:容器数据卷,docker compose,docker swarm(2/2)未修订版欢迎留言补漏
L06 容器数据卷相对于01-05难度加大什么是容器数据卷Docker理念:将应用和环境打包成一个镜像!程序要保存数据,数据并不能放在容器里面,因为一旦数据放在容器,误操作删除掉容器,数据也随之消失;数据的持久化成为刚需Eg:Mysql容器->删除容器->删库跑路->需求:Mysql存储在本地因此容器可以有一个数据共享技术:Docker中产生的数据,必须同步到本地这种数据共享技术
L06 容器数据卷
- 相对于01-05难度加大
什么是容器数据卷
Docker理念:将应用和环境打包成一个镜像!
程序要保存数据,数据并不能放在容器里面,因为一旦数据放在容器,误操作删除掉容器,数据也随之消失;数据的持久化成为刚需
Eg:Mysql容器->删除容器->删库跑路->需求:Mysql存储在本地
因此容器可以有一个数据共享技术:
Docker中产生的数据,必须同步到本地
这种数据共享技术->卷技术,将容器内的目录挂载到虚拟机上
总结:容器的持久化和同步操作!容器间可以数据共享!
使用数据卷
方式1:直接命令挂载
docker run -it -v 主机目录:容器目录 镜像名 登陆方式
#1.测试文件的同步
[root@ ~]# docker run -it -v /home/cesh:/home centos /bin/bash
[root@670ff121e9cc /]#
#2.再开一个窗口登录到指定服务器
[root@ ~]#docdocker inspect 670ff121e9cc
"Mounts": [ //挂载 -v卷
{
"Type": "bind",
"Source": "/home/cesh", //主机内地址
"Destination": "/home", //docker容器内地址
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
[root@ ~]# cd /home
[root@ home]# ll
total 8
drwxr-xr-x 2 root root 4096 Oct 26 21:59 cesh
drwx------ 5 lighthouse lighthouse 4096 Oct 26 01:03 lighthouse
[root@ home]# cd cesh
[root@ cesh]# touch suzhuji
#3.容器内相应路径查看
[root@670ff121e9cc /]# cd /home
[root@670ff121e9cc home]# ls
[root@670ff121e9cc home]# ls
suzhuji
#4.容器创建文件
[root@670ff121e9cc home]# touch rongqi
#5.宿主机相应路径查看
[root@ cesh]# ls
rongqi suzhuji
#6.容器退出(停止容器),再去宿主机修改文件测试
[root@670ff121e9cc home]# exit
exit
[root@ cesh]# vim /home/ceshi/suzhuji
i am a boy!
#7.重新启动容器
[root@ ~]# docker start 670ff121e9cc
670ff121e9cc
[root@ ~]# docker attach 670ff121e9cc
[root@670ff121e9cc /]# cd /home
[root@670ff121e9cc home]# ls
rongqi suzhuji
#8.容器内的数据在启动后继续同步
[root@670ff121e9cc home]# cat suzhuji
i am a boy!
总结:以后修改配置文件,数据文件等都可以在宿主机本地进行修改!道道容器的持久化和同步操作,容器之间可以数据共享!
安装MSQL
- 查官方文档
1. hub.docker.com
2. search mysql
3. asure:5.7
4. 查初始登陆说明
5. 运行选项说明
# -d 后台运行 -v 数据卷挂载共享/多个
# -p 端口映射 -e 环境配置
# --name 容器名字
# 镜像名:版本
[root@ ~]# docker run -d -p 3344:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql \
> -e MYSQL_ROOT_PASSWORD=123456 --name mysql_lpz mysql:5.7
70bc152bd24869e48a05d57b3731b9d0a05cb7c57a591c415207cfe65dfc6192
#登陆成功后,本地使用第三方工具:SQLyog测试登陆
#ip
#password
#port
#sqlyog连接到服务器的3344 ,服务器的3344端口与容器内的3306映射,这个时候连接成功
- 通过本地第三方工具间接在容器内创建数据库,查看宿主机数据库数据文件变化
[root@ data]# ls
auto.cnf ca.pem client-key.pem ibdata1 ib_logfil
ca-key.pem client-cert.pem ib_buffer_pool ib_logfile0 ibtmp1
[root@ data]# ls
auto.cnf ibdata1 private_key.pem
ca-key.pem ib_logfile0 public_key.pem
ca.pem ib_logfile1 server-cert.pem
client-cert.pem ibtmp1 server-key.pem
client-key.pem mysql sys
ib_buffer_pool performance_schema test
- 删除数据库测试
[root@ data]# docker kill mysql_lpz
mysql_lpz
[root@ data]# docker rm mysql_lpz
mysql_lpz
[root@ data]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
#测试宿主机
[root@ mysql]# cd /home/mysql
[root@ mysql]# ls data
auto.cnf ca.pem client-key.pem ibdata1 ib_logfile1 mysql private_key.pem server-cert.pem sys
ca-key.pem client-cert.pem ib_buffer_pool ib_logfile0 ibtmp1 performance_schema public_key.pem server-key.pem test
具名挂载和匿名挂载
#匿名挂载
-v 容器内路径!
-P 随机映射
docker run -d -P --name nginx01 -v /etc/nginx nginx
#查看所有的 volume 的情况
docker volume ls
#这里发现,都是匿名挂载,-v只写了容器内路径,没有写容器外路径,volumename显示随机数串
docker
#具名挂载
docker run -d -P --name nginx02 -v jvming-nginx:/etc/nginx nginx
#通过 -v 卷名:容器内路径
#查看卷
clear
docker volume inspect jvming-nginx
#测试
[root@ ~]# docker volume ls
DRIVER VOLUME NAME
local 0a36273b007e4b679abc5863fe5da5029b17804410884def64b4eca4fb54dc3d
[root@ ~]# docker volume inspect 0a36273b007e4b679abc5863fe5da5029b17804410884def64b4eca4fb54dc3d
[
{
"CreatedAt": "2020-10-26T16:16:59+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/0a36273b007e4b679abc5863fe5da5029b17804410884def64b4eca4fb54dc3d/_data",
"Name": "0a36273b007e4b679abc5863fe5da5029b17804410884def64b4eca4fb54dc3d",
"Options": null,
"Scope": "local"
}
]
- 所有docker容器内的卷,没有指定目录的情况下都是在,/var/lib/docker/volumes/xxx/_data
- 我们通过具名挂载可以方便的找到我们的一个卷,大多数情况在使用具名挂载
-v 容器内路径 #匿名挂载
-v 卷名:容器内路径 #具名挂载
-v /宿主机路径:容器内路径 #指定路径挂载
- 拓展:
#通过 -v 容器内路径,ro,rw改变读写权限
#一旦设定了容器权限,容器对我们挂载出来的内容就有限定了
docker run -d -P --name nginx02 -v jvming-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v jvming-nginx:/etc/nginx:rw nginx
#ro 这个路径内容只能通过宿主机来改变,容器内部无法操作
#rw
数据卷容器
-
先参考初识Dockerfile
-
之前课程讲述的都是容器与宿主机之间的数据同步
-
容器与容器之间如何数据同步?
-
多个MySQL同步数据!
-
谁去挂载到谁,谁就是父容器
#启动docker01
[root@ docker-test-volume]# docker images|grep linpengze/centos
linpengze/centos latest 427731168923 About a minute ago 215MB
[root@ docker-test-volume]# docker run -it --name centos01 linpengze/centos:latest
[root@6ab67abce6a4 /]# ls |grep volume
volume1
volume2
#ctrl+p+q
[root@6ab67abce6a4 /]# [root@ docker-test-volume]#
#启动centos02
[root@ docker-test-volume]# docker runrun -it --name docker02 --volumes-from docker01 linpengze/centos
Unable to find image 'linpengze/centos:latest' locally
^C
[root@ docker-test-volume]# docker runrun -it --name centos02 --volumes-from centos01 linpengze/centos
[root@cd54772a7271 /]# ls |grep volume
volume1
volume2
#进入centos01,在volume1目录下做测试操作
[root@ ~]# docker attach centos02
[root@cd54772a7271 /]#
[root@6ab67abce6a4 /]# cd volume1
[root@6ab67abce6a4 volume1]# touch centos01
#在centos02下测试
[root@cd54772a7271 /]# ls volume1
centos01
- 只要通过volumes-from实现数据共享
#删除centos01
[root@ docker-test-volume]# docker stop 6ab67abce6a4
6ab67abce6a4
[root@ docker-test-volume]# docker rm 6ab67abce6a4
6ab67abce6a4
[root@ docker-test-volume]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cd54772a7271 linpengze/centos "/bin/sh -c /bin/bash" 20 minutes ago Up 20 minutes centos02
#测试centos02
[root@ ~]# docker attach centos02
[root@cd54772a7271 /]# ls volume1
centos01
多个mysql实现数据共享
#具名挂载方式创建第一个数据库
docker run -d -p 3344:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql_lpz01 mysql:5.7
#创建第二个数据库,满足共享第一个数据库的数据
docker run -d -p 3355:3306 -e MYSQL_ROOT_PASSWORD=12345678 --name mysql_lpz02 --volumes-from mysql_lpz01 mysql:5.7
- 容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有人使用为止;
- 但是一旦持久化到了本地,这个时候,本地的数据是不会删除的
L07 DockerFile
初识DockerFile
- Dockerfile就是用来构建Docker镜像的构建文件!命令参数脚本!
- 通过这个脚本可以生成镜像;镜像一层层;脚本是一个个命令,每个命令对应一层;
构建步骤:
1.编写dockerfile文件
2.docker build 构建成为一个镜像
3.docker run 运行镜像
4.docker pull 发布镜像 dockerhub 阿里云镜像仓库
- 测试
#进入目录:创建一个dockerfile文件
cd /home
mkdir docker-test-volume
cd docker-test-volume
#文件中的内容 指令大写
$ vim dockerfile1
FROM centos
VOLUME ["volume01","volume02"]
CMD echo "-----end-----"
CMD /bin/bash
#上面的每一个命令,就是镜像的一层
#根据文件创建容器
docker build -f /home/docker-test-volume/dockerfile1 -t linpengze/centos .
docker images
[root@ docker-test-volume]# docker build -f \
> /home/docker-test-volume/dockerfile \
> -t linpengze/centos .
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM centos
---> 0d120b6ccaa8
Step 2/4 : VOLUME ["volume1","volume2"]
---> Running in 13fe60f549b9
Removing intermediate container 13fe60f549b9
---> b7c640c88108
Step 3/4 : CMD echo "------end------"
---> Running in 396202138fe2
Removing intermediate container 396202138fe2
---> 5a76446a2acf
Step 4/4 : CMD /bin/bash
---> Running in 3e8922b656df
Removing intermediate container 3e8922b656df
---> 427731168923
Successfully built 427731168923
Successfully tagged linpengze/centos:latest
[root@ docker-test-volume]# docker images|grep linpengze/centos
linpengze/centos latest 427731168923 About a minute ago 215MB
#进入容器
docker run -it conID /bin/bash
ls |grep volume
#发现自动挂载的数据卷目录
#在共享数据卷里创建文件并退出
cd volume01
touch hahaxixi
exit
docker inspe
ct conID
#查看mounts
查找宿主机volume1下的文件内容
ls /var/lib/docker/volumes/????/_data
- 这个匿名挂载一定有一个同步的目录在宿主机
- 匿名挂载的路径依旧在/var/lib/docker/volumes下
- 这种方式未来使用比较频繁,因为我们通常会构建自己的镜像
- 假设构建镜像的时候没有挂载卷,就要手动镜像挂载 -v 卷名:容器内路径
查看官方镜像
- hub.docker.com搜索centos
- 选择任意的版本进入
- 页面跳转到对应版本的github仓库
- 很多官方镜像都是基础包,很多功能没有,我们通常要自己搭建自己的镜像
- 假设自需:centos+jdk+tomcat+mysql+redis;自制
- 官方可以自己制作镜像,我们也可以!
Dockerfile构建过程
基础知识
1.每个保留关键字(指令)必须是大写字母
2.从上到下执行
3.#表示注释
4.每一个指令都会创建提交一个新的镜像层,并提交!
层级内容(由下而上) | 层级 |
---|---|
可写容器(Container) | 5(顶) |
镜像(Tomcat) | 4 |
镜像(JDK) | 3 |
rootfs基础镜像(Cetos/Ubuntu) | 2 |
Bootfs | 1(底) |
- Dockerfile面向开发,以后要发布项目,做镜像,信息需要编写dockerfile文件,这个文件不难构建!
- Docker逐渐成为企业交付的标准,必须要掌握!
- 步骤:开发,部署,运维。
- DockerFile:构建文件,定义了一切不厚,好比源代码
- DockerImage:通过DockerFile构建生成的镜像,最终发布和运行的产品;
- Docker容器:容器就是镜像运行起来提供服务器
总结:整个课程的设置是要先学会使用镜像和容器命令,最后利用所学来构建Dockerfile:工程领域叫做构建项目,容器技术领域叫做构建镜像;
Dockerfile指令
- 以前是使用别人的镜像,现在可以自己写一个镜像
指令 | 解释 |
---|---|
FROM | 基础镜像 centos |
MAINTAINER | 镜像谁写的,姓名+邮箱 |
RUN | 镜像构建时候需要运行的命令 |
ADD | 步骤,Tomcat压缩包,这个压缩包,添加内容 |
WORKDIR | 设置当前工作目录 |
VOLUME | 设置卷,挂载主机目录 |
EXPOSE | 指定对外端口 |
CMD | 指定容器启动后要运行的命令,只最后一个会生效,-l可被替代 |
ENTRYPOINT | 指定容器启动后要运行的命令,可以追加命令 |
ONBUILD | 当构建一个被继承Dockerfie,这个时候会运行onbuild,触发指令 |
COPY | 类似add,将文件拷贝到镜像中 |
ENV | 构建的时候设置环境变量 |
实战测试
- dockerhub中99%镜像都是从这个基础镜像过来的FROM scrach ,然后配置需要的软件和配置来进行构建
#创建一个自己的centos
#1.编写
[root@ home]# mkdir dockerfile
[root@ home]# cd dockerfile/
[root@ dockerfile]# ls
[root@ dockerfile]# vim mydockerfile-centos
FROM centos
FROM centos
MAINTAINER linpengze<leonlin600@163.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] .
[root@ dockerfile]# docker build -f mydockerfile-centos -t linpengze/centos:0.1 .
...
Successfully built 764dc97d3166
Successfully tagged linpengze/centos:0.1
[root@ dockerfile]# docker images |grep linpengze/centos
linpengze/centos 0.1 764dc97d3166 About a minute ago 295MB
#3.测试运行
[root@ dockerfile]# docker run -it linpengze/centos:0.1
#测试当前目录:确定是预设镜像里所要求的;原生默认是根目录
[root@208ca3b11ab8 local]# pwd
/usr/local
#测试net-tools命令,原生centos没有这个命令
[root@208ca3b11ab8 local]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.4 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:04 txqueuelen 0 (Ethernet)
RX packets 8 bytes 656 (656.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
...
#测试vim,原先没有这个功能
[root@208ca3b11ab8 local]# vim aa
[1]+ Stopped vim aa
- 列出本地对镜像进行的历史变更,查看所有的镜像是怎么生成的,因此,我们也可以平时研究别人怎制作镜像
docker history imageID
CMD和ENTRYPOINT的区别
- 命令追加可否?
命令 | 解释 |
---|---|
CMD | 指定容器启动后要运行的命令,只最后一个会生效,-l可被替代 |
ENTRYPOINT | 指定容器启动后要运行的命令,可以追加命令 |
测试CMD
#编写文件
[root@ docker-test-volume]# cat dockerfile-cmd-test
FROM centos
CMD ["ls","-a"]
#构建
[root@ docker-test-volume]# docker build -f \
> dockerfile-cmd-test -t cmdtest .
Sending build context to Docker daemon 3.072kB
Step 1/2 : FROM centos
---> 0d120b6ccaa8
Step 2/2 : CMD ["ls","-a"]
---> Running in 68836b647119
Removing intermediate container 68836b647119
---> d941b7e1d981
Successfully built d941b7e1d981
Successfully tagged cmdtest:latest
#运行只有最后一个命令会生效,ls -a
[root@ docker-test-volume]# docker run d941b7e1d981
.
..
.dockerenv
bin
...
var
追加一个命令
[root@ docker-test-volume]# docker run d941b7e1d981 -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"-l\": executable file not found in $PATH": unknown.
#cmd的清理下, -l 替换了CMD ["ls","-l"]命令,又由于-l不是命令,所以会报错
[root@ docker-test-volume]# docker run d941b7e1d981 ls -al
total 56
drwxr-xr-x 1 root root 4096 Oct 27 05:42 .
...
测试ENTRYPOINT
[root@ docker-test-volume]# cat dockerfile-cmd-entrypoint
FROM centos
ENTRYPOINT ["ls","-l"]
[root@ docker-test-volume]# docker build -f \
> dockerfile-cmd-entrypoint -t entrypoint-test .
Sending build context to Docker daemon 5.12kB
Step 1/2 : FROM centos
---> 0d120b6ccaa8
Step 2/2 : ENTRYPOINT ["ls","-l"]
---> Running in 4bd5e65558b1
Removing intermediate container 4bd5e65558b1
---> 3333b6d2f71b
Successfully built 3333b6d2f71b
Successfully tagged entrypoint-test:latest
[root@ docker-test-volume]# docker run 3333b6d2f71b
total 48
lrwxrwxrwx 1 root root 7 May 11 2019 bin -> usr/bin
drwxr-xr-x 5 root root 340 Oct 27 06:15 dev
...
[root@ docker-test-volume]# docker run 3333b6d2f71b -h
total 48K
lrwxrwxrwx 1 root root 7 May 11 2019 bin -> usr/bin
- Dockerfile很多命令十分显示,需要了解其中的区别,需要对比然后进行效果测试;
实战:Tomcat镜像
- 准备镜像文件 tomcat压缩包,jdk的压缩包!
jdk安装包
ftp接收
apache-tomcat-9.0.22.tar.gz
Dockerfile
jdk-8ull-linux-x64.tar.gz
read.txt
- 编写dockerfile文件,官方命名Dockerfile,build会自动寻找这个文件,就不需要-f指定了
#原先都是手动配置
touch readme.txt
vim Dockerfile
FROM centos
MAINTAINER linpengze<leonlin600@163.com>
COPY readme.txt /usr/local/readme.txt
ADD jdk-8ull-linux-x64.tar.gz /usr/local
ADD apache-tomcat-9.0.22.tar.gz
/usr/local
RUN yum -y install vim
ENV MYPATH /usr/local
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8.0_11
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/localapache-tomcat-9.0.22
ENV CATALINA_BASH /usr/localapache-tomcat-9.0.22
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-9.0.22/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.22/bin/logs/catalina.out
- 构建镜像(当前目录下)
docker build -t diytomcat .
- 容器运行
#光标按照单词移动修改:ctrl+左右键
docker run -d -p 9090:8080 --name linpengze/tomcat -v /home/linpengze/build/tomcat/test:/usr/local/apache-tomcat-9.0.22/webapps/test -v /home/linpengze/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.22/logs diytomcat
#diytomcat 是第三步构建的镜像名
- 测试
docker exec -it conID /bin/bash
curl localhost:9090
- 发布项目
#由于做了卷的挂载,我们直接在本地编写项目就可以了
cd /home/linpengze/build/tomcat/test
mkdir WEB-INF
cd WEB-INF
vim web.xml
#报读随便找一个精简的样本
vim index.jsp
#随便找一个可用的jsp文件
cat index.jsp
cd tomcatlogs
cat catalina.out
#浏览器测试项目
ip:9090
总结:开发的步骤需要掌握Dockerfile的编写
发布自己的镜像
DockerHub
- 注册账号:hub.docker.com
- 确定这个账号可以登陆
- 在服务器上提交自己的镜像
docker login --help
docker login -u linpengze
Password:
#push自己的镜像到服务器中
docker images
docker push diytomcat
docker push linpengze/diytomcat2:2.0
#自发布的镜像尽量发布版本号
docker tag imageID linpengze/tmcat:1.0
docker push linpengze/tomcat:1.0
#提交的时候也是按照镜像的层级来进行提交
阿里云镜像上发布
- 登陆
- 容器镜像服务
- 找到镜像仓库,创建命名空间
- 创建容器镜像
- 根据官方文档完成操作
docker login --username=? addr
password:
docker tag [ImageID] ...
docker push
小结
-
回顾之前所有的知识点
-
docker save/load --help
-
save:镜像打包成为一个压缩包,发给别人;
L08 Docker网络
理解Docker0
#清空所有环境
docker rm -f $(docker ps -aq)
docker rmi -f $(docker images -aq)
docker ps
docker images
#ip addr
lo 本机回环地址
eth0 阿里云内网地址
docker0 docker地址
[root@ docker-test-volume]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 52:54:00:c2:93:52 brd ff:ff:ff:ff:ff:ff
inet 10.0.8.5/22 brd 10.0.11.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fec2:9352/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:38:0c:11:32 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:38ff:fe0c:1132/64 scope link
valid_lft forever preferred_lft forever
#问题:docker,是如何处理容器网络访问的?
docker run -d -P --name tomcat01 tomcat
#查看容器内部的网络地址
#容器启动的时候会得到一个 eth0@if85 ip地址,docker分配
[root@ docker-test-volume]# docker exec -it tomcat01 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
84: eth0@if85: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
#思考,linux能不能ping通docker容器tomcat01内部? 可以
[root@ docker-test-volume]# ping 172.17.0.2 -c1
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.064 ms
#再次测试 ip addr 多出了
85: vethd36eff7@if84: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 7e:20:cf:13:6d:cb brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::7c20:cfff:fe13:6dcb/64 scope link
valid_lft forever preferred_lft forever
- 再开一个tomcat容器测试网络
[root@ docker-test-volume]# docker run -d -P --name tomcat02 tomcat
[root@ docker-test-volume]# ip addr
#多了
87: veth8f089af@if86: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 3e:47:b8:cf:05:5a brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::3c47:b8ff:fecf:55a/64 scope link
valid_lft forever preferred_lft forever
[root@ docker-test-volume]# docker exec -it tomcat02 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
86: eth0@if87: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
原理
- 我们每启动一个docker容器,docker就会给docker容器分配一个 ip,只启动了docker服务,就会申请一个虚拟网卡docker0,桥接模式。使用技术是veth-pair技术;
- 容器带来的网卡,都是成对存在;veth-pair就是一对虚拟设备接口,一段连着协议,一段彼此相连
- 正是因为有这个特性,evth-pair充当桥梁,连接各种虚拟网络设备
- Openstack,Docker容器之间的连接,OVS的连接,都是使用evth-pari技术
- 容器之间公用路由器,docker0
- 所有容器不指定网络情况下,都是由docker0路由,docker会给容器分配一个默认可用的ip
- docker0网段可分配ip要根据子网掩码位数来确定
- 测试Tomcat01和Tomcat02是否可以ping通
[root@ ~]# docker exec -it tomcat01 ping 172.17.0.3
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.096 ms
[root@ ~]# docker exec -it tomcat02 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.072 ms
- docker使用linux桥接,宿主机中docker0是一个docker容器的网桥
- Docker中所有的网络接口都是虚拟的,虚拟转发效率高!
- Veth网卡都是虚拟网卡;
- Docker的虚拟网卡与所在宿主机的某一个物理网卡进行桥接
- 只要容器删除,对应的网桥一对就消失;
–link 场景思考
场景:编写了一个微服务, database url=ip;项目不重启,数据库ip换掉了,希望可以用名字来进行访问服务—>高可用
[root@ ~]# docker exec -it tomcat02 ping tomcat01
ping: tomcat01: Name or service not known
#通过--link可以解决网络联通问题
[root@ ~]# docker run -d -P --name tomcat03 --link tomcat02 tomcat
6ee67ebeb23f212b9d00715ab00b405b10d425c36b8a5621a713ca1827301549
#tomcat3ping不通tomcat1
[root@ ~]# docker runexec -it tomcat03 ping tomcat01
ping: tomcat01: Name or service not known
#tomcat3ping通tomcat2
[root@ ~]# docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.17.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.082 ms
#但是tomcat2ping不通tomcat3
[root@ ~]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known
docker network ls
docker network inspect ID
- –link本质:修改对应容器里本地host配置文件
- 现在不建议通过–link 来实现名字访问!
[root@ ~]# docker inspect 6ee67ebeb23f|grep tomcat02 -n
62: "/tomcat02:/tomcat03/tomcat02"
#查看hosts配置,这里发现--link的原理
[root@ ~]# docker exec -it tomcat03 cat /etc/hosts|grep tomcat02
172.17.0.3 tomcat02 cb08142e298b
#为什么tomcat02ping不通tomcat03?
[root@ ~]# docker exec -it tomcat02 cat /etc/hosts|grep tomcat03
[root@ ~]#
需求:自定义网络!不适用docker0:docker0不支持容器名连接网络
自定义网络
- 容器互联
- docker network --help
查看所有的docker网络
docker network ls
网络模式
bridge桥接模式:docker(默认),自己创建也使用桥接模式
none:不配置网络
host:仅主机模式,和宿主机共享网络
测试
#我们直接启动的命令 --net bridge,而这个就是我们的docker0
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat01 --net bridge tomcat
#docker0特点,默认,域名无法访问,--link可以打通连接
#可以自定义网络
docker network create --help
[root@ ~]# \
docker network create \
--driver bridge \
--subnet 192.168.0.0/16 \
--gateway 192.168.0.1 \
mynet
7e2d715f2494d80c025a2b2ac6dbec4a400a7e2c764feb53f6fd14a03d82fd1d
[root@ ~]# docker network ls|grep mynet
7e2d715f2494 mynet bridge local
- 搭建自定义网络再进行互ping测试
#搭建容器,查看自定义网络
[root@ ~]# docker run -d -P --name tomcat-net-01 --net mynet tomcat
56408adc4b74df37b7a9d53b1c3befb83168a2f698826d7ad8e953f1fef923fb
[root@ ~]# docker run -d -P --name tomcat-net-02 --net mynet tomcat
29ec24996a1cd4290ec4890a6215b6286dacfa465b543b1e8e85eae55cfa8e78
[root@ ~]# docker runnetwork inspect mynet
[
{
"Name": "mynet",
"Id": "7e2d715f2494d80c025a2b2ac6dbec4a400a7e2c764feb53f6fd14a03d82fd1d",
"Created": "2020-10-28T01:28:21.117679115+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"29ec24996a1cd4290ec4890a6215b6286dacfa465b543b1e8e85eae55cfa8e78": {
"Name": "tomcat-net-02",
"EndpointID": "34591df44e78ee11cd309a5376d492ccdea7ee574efee84a282c956c3fd4cd94",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
},
"56408adc4b74df37b7a9d53b1c3befb83168a2f698826d7ad8e953f1fef923fb": {
"Name": "tomcat-net-01",
"EndpointID": "d73509a5197bdfafa8587cea6f84fee901dfb0b366672830a1d393db0ae20938",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
#互ping测试,成功
[root@ ~]# docker exec -it tomcat-net-01 ping tomcat-net-02
PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.074 ms
[root@ ~]# docker exec -it tomcat-net-02 ping tomcat-net-01
PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.055 ms
总结:我们自定义网络docker都已经帮我们维护好对应的关系,通过容器名进行容器间访问,而docker0没有
好处:
redis-不同集群使用不同的网络保证集群安全健康
mysql-不同集群使用不同的网络保证集群安全健康
网络联通
- 连接一个容器到一个网络
- docker network connect --help
#测试打通
[root@ ~]# docker run -d -P --name tomcat01 tomcat
04fd979c0277e0901d0b13eade1986af984cd7387d9eae8b02f871867f5be352
[root@ ~]# docker exec -it tomcat01 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known
#开始做工作
[root@ ~]# docker network connect mynet tomcat01
#联通之后就是将tomcat01加入mynet网络下,一个容器多个IP!
#阿里云服务,公网ip,私网ip
#总结,网卡与网卡之间不能打通,容器与网卡可以打通
#测试ping,tomcat01打通mynet网段
[root@ ~]# docker netexec -it tomcat01 ping tomcat-net-01
PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.073 ms
- docker network inspect mynet
结论:假设跨网络操作别人,就需要使用docker network connect连通
实战:部署Redis集群
#shell script
#创建网卡
docker network create redis --subnet 172.38.0.0/16
[root@ ~]# docker network ls|grep redis
8438acdc1088 redis bridge local
#批量创建六个集群
...
cd /mydata
ls
cd redis
ls
cd node-1
ls
cd conf
ls
cat redis.conf
#集群启动
docker run -p ?:?√ -p ?:?√ 端口映射
--name ???√ 容器命名
-v ??√:?
-v ??√:? 路径挂载
-d 后台运行
--net ??? 自定义网络
--ip ???√ 绑定ip号
redis:?? 什么版本的镜像
redis-server /etc/redis/redis.conf
通过什么配置文件启动
六次
#进入容器
dcoker ps
docker exec -it redis-1 /bin/sh
ls
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
为你是否要配置三个主机三个从机?
yes
#一台测试
redis-cli -c
cluster info
cluster nodes
set a b
假设主库13响应
#再开一台
docker stop redis-3
#一台测试
get a (由于是13号机测试,又把13号机器关了,请求没有得到应答)
ctrl+c1
redis-cli -c
get a
14机即13从机回应
docker nodes 故障转移
- docker搭建redis集群完成,使用docker,所有的技术慢慢会变得简单起来,直捣核心技术!
SpringBoot微服务打包Docker镜像
- 创建springboot项目
- 写一个helloworld
- 打包应用:jar包拿出来
- 测试打包好的jar包:本地:java -jar demo-0.0.1-SNAPSHOT.jar
- idea装docker插件
- 编写dockerfile
FROM java:8
COPY *.jar /app.jar
CMD ["--server.port=8080"]
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]
-
将jar包和dockerfile传到服务器
-
构建镜像docker build -t linpengze666 .
-
docker images
-
docker run -d -P --name linpengze666-web linpengze666
-
curl localhost:32779/hello
10.28总结:以后使用镜像,给别人交付仅仅是一个镜像即可
问题:如果有100个以上的镜像需要维护,是否麻烦?
- Docker到K8s:Docker编排和集群管理
- 所有的学习资源都需要到官方文档上了解!
- 先知道扩缩容再去学习K8s
L09 Docker compose
简介
- 原先:Dockerfile build run ,手动操作单个容器;微服务100个;
- 现在:DockerCompose来轻松高效地管理容器,定义运行多个容器。
官方介绍
定义,运行多个容器 ;YAMLfile配置文件; 命令有哪些?;所有环境都可以使用Compose
三步骤:
-
Dockerfile: 保证项目在任何地方可以运行
-
docker-compose.yml 如何写;定义什么是服务
-
docker compose up 启动项目
总结:批量容器编排
自己的理解
Compose是docker官方开源项目,需要安装!
Dockerfile 让程序在任何地方运行。web服务,redis,mysql,nginx…多个容器
version: "3.8"
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
- logvolume01:/var/log
links:
- redis
redis:
image: redis
volumes:
logvolume01: {}
#--links标签,先启动redis,在启动web应用
#文件没写错前提下,100个服务可以一件上线
重要概念:
- 服务service:容器,应用(web,redis,mysql)
- 项目project:一组关联的容器–>形成一个业务单元;一个商城有100个微服务,100个微服务跑起来就是一个项目
安装
curl -L https://get.daocloud.io/docker/compose/releases/download/1.27.4/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
[root@ bin]# docker-compose version
docker-compose version 1.27.4, build 40524192
docker-py version: 4.3.1
CPython version: 3.7.7
OpenSSL version: OpenSSL 1.1.0l 10 Sep 2019
总结:多看官网,按照说明来完成
初体验
Estimated reading time: 11 minutes:11分钟完成
On this page you build a simple Python web application running on Docker Compose. The application uses the Flask framework and maintains a hit counter in Redis. While the sample uses Python, the concepts demonstrated here should be understandable even if you’re not familiar with it.
搭建一个运行在docker compose上的python web应用;应用使用flask框架,redis技术记录命中;
Prerequisites:预备:已经安装docker引擎和docker compose服务,不需要提前安装python和redis环境,因为都两者都可以由镜像提供;
第一步:安装
定义应用依赖:
#创建文件夹
[root@ bin]# cd /home
[root@ home]# mkdir composetest
[root@ home]# cd composetest/
#创建py文件
[root@ composetest]# vim app.py
import time
import redis
from flask import Flask
app = Flask(__name__)
#redis,域名访问,同一个网络下,直接通过域名(服务名)访问
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)
#使用6379端口作为redis(容器名)容器在应用所在网络的默认端口
[root@ composetest]# vim requirements.txt
flask
redis
第二步:创建dockerfile文件编写Compose文件
[root@ composetest]# vim Dockerfile
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"]
[root@ composetest]# vim docker-compose.yml
version: "3.8"
services:
web:
build: .
ports:
- "5000:5000"
redis:
image: "redis:alpine"
#原先是docker run ...;docker run ...
[root@ composetest]# ls
app.py docker-compose.yml Dockerfile requirements.txt
第三步:用Compose服务构建并允许app**
#当前目录下 /home/dockercomposetest
docker-compose up
#故障排查
ERROR: Service 'web' failed to build : The command '/bin/sh -c pip install -r requirements.txt' returned a non-zero code: 2
#分析:故障卡在了执行dockerfile的第七步
#查看dockerfile第七步做了什么
[root@ home]# cat /home/composetest/Dockerfile |grep pip
RUN pip install -r requirements.txt
[root@ home]# cat /home/composetest/requirements.txt
flask
redis
#错误状态码2代表的意思:No such file or directory
#1.测试
free 内存正常
#2.执行报错命令
[root@ composetest]# /bin/sh -c pip install -r requirements.txt
install: pip: command not found
#3.安装pip
[root@ composetest]# yum install python-pip
#4.手动安装flask
[root@ composetest]# pip install flask
...
You are using pip version 8.1.2, however version 20.2.4 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
[root@ composetest]# pip install --upgrade pip
Successfully installed pip-20.2.4
[root@ composetest]# pip install redis
#5.重新测试构建compose
[root@ composetest]# docker-compose up
...
web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
#成功
#6.开另一台终端测试
[root@ home]# curl http://0.0.0.0:5000/
Hello World! I have been seen 1 times.
[root@ home]# curl http://0.0.0.0:5000/
Hello World! I have been seen 2 times.
[root@ home]# curl http://0.0.0.0:5000/
Hello World! I have been seen 3 times.
[root@ home]# curl http://0.0.0.0:5000/
分析
#查看服务状态,启动状态
[root@ composetest]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ef3c22478281 redis:alpine "docker-entrypoint.s…" 15 minutes ago Up 15 minutes 6379/tcp composetest_redis_1
848d684e81b5 composetest_web "flask run" 15 minutes ago Up 15 minutes 0.0.0.0:5000->5000/tcp composetest_web_1
#查看镜像(自动安装镜像)
[root@ composetest]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
composetest_web latest 0499a4761d8b 19 minutes ago 195MB
redis alpine c1949ec48c51 21 hours ago 31.2MB
tomcat latest 625b734f984e 5 days ago 648MB
python 3.7-alpine 4d91c1ce4cc8 6 days ago 41.1MB
#
[root@ composetest]# 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.
#查看网络:compose自动生成了一个网络,项目中的内容都在同一个网络中
[root@ composetest]# docker network ls
NETWORK ID NAME DRIVER SCOPE
17eafe1c056a bridge bridge local
8f2db8d83cf3 composetest_default bridge local
2f902f83ffdf host host local
7e2d715f2494 mynet bridge local
318716c6177e none null local
8438acdc1088 redis bridge local
[root@ composetest]# docker network inspect composetest_default
总结:1.编写一个应用;2.编写dockerfile将应用打包为镜像 ;3.编写docker-compose yaml文件定义整个服务,需要的环境,以便完整地上线服务;4.运行服务;
以前都是单个docker run启动一个容器,现在通过docker compose编写yaml配置文件,意见启动所有服务,停止!就三个步骤
Creating composetest_web_1 …done
Creating composetest_redis_1 …done
-
文件名composetest
-
自动的默认规则 ;默认服务名 文件名__服务名__num
-
多个服务器。集群都可能有同一个项目;A B _num 副本数量
-
集群(多个服务器)状态里,服务不可能只有一个运行实例。弹性,HA高并发,因此多个副本就需要一个数字号来表示以便知道这个副本服务是来自那个服务器里
-
kuberctl service 负载均衡
MySQL有十个容器实例:mysql:3306 不用加ip;
停止
docker-compose down
ctrl+c //直接关掉所有容器
总结:
- Docker镜像,run->容器
- dockerfile 构建镜像 (服务打包)
- docker-compose 启动项目(编排,多个微服务/环境)
- docker网络
狂神提醒:num名,ip&host网段,解释镜像/容器
yaml编写规则
#3层
#与docker engine对应版本
version: ''
#服务:build,
services:
服务1:
#服务配置
image
build
network
...
服务2:redis
...
服务3:redis
...
#其他配置 网络,卷,全局规则
volumes:
networks:
configs:
- 参考文档:
web,command,contain_name,depends_on,deploy(replicas),driver,entrypoint,image
- 难度:多写,多看官方文档,开源项目:一键启动,多看别人怎么写
开源项目
- 下载项目(docker-compose.yaml)
- 如果需要文件。Dockerfile
- 文件准备齐全,一键启动项目
$ cd my_wordpress/
$ vim docker-compose.yml
version: '3.3'
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
depends_on: #先下载db,在下载wp
- db
image: wordpress:latest
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
volumes:
db_data: {}
$ docker-compose up -d 后台启动
[root@ my_wordpress]# docker-compose up -d
Creating my_wordpress_db_1 ... done
Creating my_wordpress_wordpress_1 ... done
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w0iB9Fjz-1605940890865)(assets/2020-10-29_021955.jpg)]
掌握:docker基础,原理,网络,服务。集群,错误排查,日志
必备:Linux,Docker,K8s
编写自己的微服务上线
假设项目要重新部署打包:docker-compose up --build
总结:工程,服务,容器
项目 compose:三层
- 工程 project
- 服务 微服务环境
- 容器 运行实例! Docker k8s 管理这些容器进一步封装 pods
- 未来:kubectl create – kubectl apply -f “xxx.yaml”
L10 Docker swarm
环境准备
- Docker compose 单机版;Docker swarm:集群方式部署;
- 腾讯云租4台服务器,1核 2G 按量付钱;预算五块,充值10元;按流量和租赁时间计费’
-
Xshell统一登陆
-
发送键输入到所有会话:执行同步环境安装操作,省时间
- 安装
参考L02
工作模式
Docker Overview->Run Your App in Production->Configure containers->Scale your app->
- 两种节点:管理节点和工作节点
搭建集群
#docker-01/02/03/04 查看网络情况、命令使用方法
docker network ls
docker swarm --help
---------------------------------------
#为了注册集群管理主节点:先预知参数和命令使用方法
docker swarm init --help
ip addr
eth0:172.16.0.11
---------------------------------------
#docker-01成为一个主管理节点:初始化节点
$ docker swarm init --advertise-addr 172.16.0.11
##说明:注册成功
Swarm initialized: current node (lb4ujyjftne3t0ojhb1o7nhhw) is now a manager.
To add a worker to this swarm, run the following command:
##说明:添加工作节点操作
docker swarm join --token SWMTKN-1-30uc8rx1jk9v671nif6tw1otge9lyy3nj45xtzu1q7ehc4h793-8wpc388fnr1t7btyf91b041wj 172.16.0.11:2377
##说明:添加管理节点操作
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
#docker-02 加入为工作节点
docker swarm join --token SWMTKN-1-30uc8rx1jk9v671nif6tw1otge9lyy3nj45xtzu1q7ehc4h793-8wpc388fnr1t7btyf91b041wj 172.16.0.11:2377
#docker-01 两种方式成为该集群的管理节点或工作节点
docker node ls
docker swarm join-token manager
docker swarm join-token worker
#管理节点:生成管理节点或工作节点令牌
docker swarm join-token manager
docker swarm join-token worker
#非管理节点:通过令牌提示命令,执行成为集群的节点
总结步骤:生成init节点;加入集群(管理者,工作者);目标双主双从;
RAFT协议
- 问题:假设一个节点挂了,其他节点是否可用?
- Raft协议:保证大多数节点存活;>1,集群>3
- 01 02 03 03 指的是四台服务器
#将docker1机器停止,宕机
#docker-01
systemctl stop docker
docker-02 docker-04
docker node ls
[root@VM-0-8-centos ~]# docker node ls
Error response from daemon: rpc error: code = DeadlineExceeded desc = context deadline exceeded
#docker-01
systemctl start docker
#docker-03
#工作节点变成管理节点
[root@VM-0-16-centos ~]# docker swarm join --token SWMTKN-1-30uc8rx1jk9v671nif6tw1otge9lyy3nj45xtzu1q7ehc4h793-e5cm85lrpbbcczmmggcsr99dv 172.16.0.8:2377
Error response from daemon: This node is already part of a swarm. Use "docker swarm leave" to leave this swarm and join another one.
[root@VM-0-16-centos ~]# docker swarm leave
Node left the swarm.
[root@VM-0-16-centos ~]# docker swarm join --token SWMTKN-1-30uc8rx1jk9v671nif6tw1otge9lyy3nj45xtzu1q7ehc4h793-e5cm85lrpbbcczmmggcsr99dv 172.16.0.8:2377
This node joined a swarm as a manager.
#docker-04
[root@VM-0-8-centos ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
pdc7fbmtypcqcgdbwkgfeixjo VM-0-7-centos Ready Active 19.03.13
ddosg74pvzbil5cozcyuw4p5f * VM-0-8-centos Ready Active Leader 19.03.13
lb4ujyjftne3t0ojhb1o7nhhw VM-0-11-centos Ready Active Reachable 19.03.13
rp8zyu3xmulxwalabtvuqjw7v VM-0-16-centos Down Active 19.03.13
sbpz4hqc6nps4e0ucxvd8o57g VM-0-16-centos Ready Active Reachable 19.03.13
#至此,将三台机器设置成,管理节点
#在三台管理节点满足高可用前提下,关闭其中一台docker服务,测试
01
[root@VM-0-11-centos ~]# systemctl stop docker
#docker-04 docker-03 照样可以使用
[root@VM-0-8-centos ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
pdc7fbmtypcqcgdbwkgfeixjo VM-0-7-centos Ready Active 19.03.13
ddosg74pvzbil5cozcyuw4p5f * VM-0-8-centos Ready Active Leader 19.03.13
lb4ujyjftne3t0ojhb1o7nhhw VM-0-11-centos Ready Active Unreachable 19.03.13
rp8zyu3xmulxwalabtvuqjw7v VM-0-16-centos Down Active 19.03.13
sbpz4hqc6nps4e0ucxvd8o57g VM-0-16-centos Ready Active Reachable 19.03.13
总结:集群要保证可用,必须要 至少3个主节点;且保证一台管理节点存货;Raft协议保证大部分节点存货才可以使用;
体会
- 使用swarm之后所有操作都属于集群操作范畴
- 应该拥有:弹性,扩缩容,集群
docker run 单机模式下:基础模式/告别
docker-compose up 单机模式下:启动一个项目上线!
docker service 集群swarm下集群节点
k8s service pods
容器变成服务(服务中有个概念叫做副本):redis 多份!单独来说多个容器
集群:高可用,web->redis (3台),分布在不同机器上!
- docker service功能:创建服务,动态扩展服务,动态更新服务
- 灰度发布:金丝雀发布!滚动发布:升级服务不影响旧版使用
docker service --help
#工作节点启动服务失败
[root@VM-0-7-centos ~]# docker service create -p 8888:80 --name mynginx nginx
Error response from daemon: This node is not a swarm manager. Worker nodes can't be used to view or modify cluster state. Please run this command on a manager node or promote the current node to a manager.
#管理节点操作
[root@VM-0-16-centos ~]# docker service create -p 8888:80 --name mynginx nginx
2qcjcuwkex4a7j0z5ee5pp1du
overall progress: 1 out of 1 tasks
1/1: running
verify: Service converged
#总结:docker run 容器启动!不具有扩缩容器
# docker swervice 服务!具有扩缩容器,滚动更新
# docker-管理节点查看
[root@VM-0-16-centos ~]# docker service ps mynginx
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
2mml3eiankpd mynginx.1 nginx:latest VM-0-8-centos Running Running 2 minutes ago
[root@VM-0-11-centos ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
2qcjcuwkex4a mynginx replicated 1/1 nginx:latest *:8888->80/tcp
查看服务 REPLICAS
- 启动服务在管理节点主机里随机启动
#上述启动nginx服务情况只是启动一个副本
#现在给其他两个管理节点增加 服务副本
[root@VM-0-11-centos ~]# docker service update --replicas 3 mynginx
mynginx
overall progress: 3 out of 3 tasks
1/3: running
2/3: running
3/3: running
verify: Service converged
#只要在集群里面,无论访问哪个ip都可以访问服务;
#集群为单位的机器
- 动态扩缩容
#1.扩容测试
[root@VM-0-11-centos ~]# docker service update --replicas 10 mynginx
mynginx
overall progress: 9 out of 9 tasks
1/9: running
2/9: running
3/9: running
4/9: running
5/9: running
6/9: running
7/9: running
8/9: running
9/9: running
verify: Service converged
[root@VM-0-8-centos ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
2qcjcuwkex4a mynginx replicated 9/9 nginx:latest *:8888->80/tcp
#总结:因为容器之间是相互隔离,所以开多少个容器取决于硬件条件允许,一个服务器节点可以同时开多个服务;
#一个服务可以有多个副本,动态扩缩容,实现高可用
#2.缩容测试
#mynginx 服务回滚到一个副本
[root@VM-0-16-centos ~]# docker service update --replicas 1 mynginx
mynginx
overall progress: 1 out of 1 tasks
1/1: running
verify: Service converged
[root@VM-0-16-centos ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
2qcjcuwkex4a mynginx replicated 1/1 nginx:latest *:8888->80/tcp
#3.另一种方式的扩缩容命令
[root@VM-0-16-centos ~]# docker service scale mynginx=5
mynginx scaled to 5
overall progress: 5 out of 5 tasks
1/5: running
2/5: running
3/5: running
4/5: running
5/5: running
verify: Service converged
[root@VM-0-11-centos ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
2qcjcuwkex4a mynginx replicated 5/5 nginx:latest *:8888->80/tcp
#4.移除服务
[root@VM-0-8-centos ~]# docker service rm mynginx
mynginx
[root@VM-0-8-centos ~]# docker service ps mynginx
no such service: mynginx
[root@VM-0-8-centos ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
总结:docer不难
- 弹性,扩缩容非常重要;
- 副本 所对应的服务既可以运行在管理节点也可以运行在工作节点;
- 集群搭建好,服务创建好,任何集群内的ip地址都可以访问集群所提供的服务;
- 一个服务可以有多个副本,动态扩缩容,实现高可用;
- 只要会用docker swarm 搭建集群 docker service create 启动服务,docker service scale 或者docker service update 动态管理容器就可以了
概括总结
swarn
- 集群的管理和编排(好比厨房),docker可以初始化一个集群,其他节点可以加入;(管理节点,工作节点)
- 命令->管理节点->api->调度->工作节点(创建task容器,维护创建)
Node
- 一个Dokcer节点(好比餐桌),多个节点就组成一个网络集群;(管理节点,工作节点)
Service
- 任务群(好比一个做菜清单),可以在管理节点或者工作节点来运行;核心。用户访问;
Task
- 容器内的命令=细节任务(好比做菜清单的一道菜);一个Service有多个task,由集群来调度由哪个node来完成
Replicas
- 服务副本与全局服务
--mode string
docker service create --mode replicated --name mytom tomcat:7.0
docker service create --mode replicated --name haha xixi ping baidu.com
网络模式
- overlay
- ingress:特殊的overlay网络,具有负载均衡功能!IPVS VIP。
- docker在多台机器上,实际上是同一个ingress网络vip,让集群变成一个整体
- 多台服务器搭建成集群,为了能让他们互相ping通,搭建一个网络,使得他们可以互相ping通
Docker-Stack
- Docker-compose:单机玩具,单机部署项目
- Docker-Stack:集群部署
#单机
docker-compose up -d wordpress.yaml
#集群
docker stack --help
docker-stack deploy wordpress.yaml
#docker-compose 文件
#百度:docker stack 案例
#集群下的yaml中service层的字段:deploy:...
Docer-Secret
- 安全!配置密码,证书!
docker secret --help
Docker Config
学习方式
- 网上/开源社区,找案例跑起来!查看命令帮助文档(–help,官网)
- 学习一次总结一次,最后达成对整个知识群的把握。
L11 K8s
云原生时代
- 云应用(商店):项目不用开发,直接云应用下载,新手也可以自己搭建大型网站
- 买服务器->部署K8s->云应用下载下来->自己配置->变成自己的平台
- 大趋势/10台机器以上
学习清单
Go语言:Docker,K8s,存储ETCD;Go是并发语言;
特性:语法类似C,内存安全,垃圾回收,结构形态,并发计算
建议:先学Go再学K8s效果会更好;
方法:入门,基础语法,高级对象,操作数据库,框架
K8s:
Jenkins:
虚拟化技术概念
KVM
-
KVM虚拟化技术属于全虚拟化技术,KVM作为一个运行在主机操作系统的虚拟化软件工具,客户操作系统根据需要运行在KVM虚拟化环境里,在这个环境里,当一个进程要使用CPU指令(特权指令,普通指令),客户操作系统认为自己运行在硬件上,直接对虚拟化的CPU进行调用,但它本身无法执行的,必须经过封装的接口,将其转化为主机操作系统的指令进行调用,进而通过真正的内核对真正的CPU的指令做调用,所以你就明白了[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GmZuDKWR-1605940890881)(C:/Users/Administrator/Desktop/2020-10-26_180639.jpg)]中间为了进行真正的指令转化,需要消耗一部分资源。
-
KVM是一个硬件资源虚拟化的软件工具
-
一方面,KVM工具本身能将CPU和硬盘资源虚拟化,另一方面,为了补齐KVM的短板,实现更加人性化的虚拟化服务,引入qemu工具实现网络和其他I/O设备的虚拟化模拟
-
KVM运行在内核空间,但是QEMU运行在用户空间
-
需要安装什么工具:
libvirt qemu-kvm
-
libvirtd是虚拟机的管理工具,通过virsh管理虚拟机,用它来cpu动态扩容,内存动态调整
-
用qemu-img来进行磁盘管理
Docker
-
容器技术,基于Go语言,遵循Apache2.0协议,虚拟化了谁,虚拟化了内核,即虚拟化的不是硬件层是操作系统层。所以什么,我们可以不用虚拟机同样可以运行Docker容器,提高了资源的利用率。
-
这就意味着 Docker既可以运行在虚拟机操作系统上也可以运行在主机操作系统上;
-
服务器虚拟化解决的是资源调配问题;而容器解决的核心是应用开发测试和部署
-
docker由服务器端和客户端组成
-
docker组件:镜像,容器,仓库
-
镜像组件,涉及到镜像的搜索,获取,导出,导入,查看,删除
-
容器组件,涉及到容器的创建,运行,进入,删除;运行什么,运行镜像+指定命令 docker run
-
仓库组件
-
网络访问:随机映射,指定映射,查看映射
-
数据管理:不同容器之间可以共享数据
-
如何构建Docker镜像 主要是编辑Dockerfile文件 docker build
-
docker应对生产情况架构是什么,底层系统层,中间是运行环境层,顶层是应用服务层;系统层可以是centos,ubuntu,debain系统;运行环境层可以是php,java,python;应用服务层比较多不一一列举
-
设计一个适用于特定场景的docker也是要遵守上面这三层的结构
K8S+Docker+Ceph+ISTIO+Enovy
Docker:容器化技术,应用部署
Kuberneates:容器编排,云平台上的多主机的容器化应用管理
Istio:已部署的服务建立网络,具有负载均衡,服务间认证,监控
Envoy:构建高性能服务间的通信系统,实现边缘和服务代理,用于云原生应用
Ceph:分布式存储系统,中大型架构支持
更多推荐
所有评论(0)