Docker学习及实践笔记

Docker笔记基础

" 不可只停留于run 开端口 "

1. Docker的组成

在这里插入图片描述

镜像(images):

通过镜像这个模板来创建容器服务,镜像 ==> run ==> 容器(提供服务),可以创建多个容器(集群搭建)

容器(container):

是镜像虚拟化的对象,可以独立运行一个或一组应用。start stop rm 这些基本命令

仓库(repository):

是一个存放镜像的地方,分为公有和私有仓库(类似git)

2. Linux上安装Docker

命令行和图形用户界面的切换

# 开机默认进入命令行模式:
sudo systemctl set-default multi-user.target
# 开机默认进入图形用户界面:
sudo systemctl set-default graphical.target

2.1 步骤介绍

# 1、Docker 要求 CentOS 系统的内核版本高于 3.10 ,

uname -r # 查看内核版本

# 2、清除之前的版本
sudo yum remove docker \
      docker-client \
      docker-client-latest \
      docker-common \
      docker-latest \
      docker-latest-logrotate \
      docker-logrotate \
      docker-selinux \
      docker-engine-selinux \
      docker-engine
  
# 3、需要的安装包
sudo yum install -y yum-utils device-mapper-persistent-data lvm2

# 4、配置镜像的仓库  建议阿里云
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# 5、更新yum缓存(为了保证能更新和下载需要的服务:如docker)
sudo yum makecache 

# 6、安装Docker(CE-社区版)会自动下载  containerd.io 和 docker-ce-cli
sudo yum -y install docker-ce

# 7、启动docker服务
sudo systemctl start docker
docker version  # 查看版本信息
docker info # 查看更加详细的信息(容器与镜像数)

# 8、设置开机自启
sudo systemctl enable docker

# 9、测试hello-world
# 第一次是unable to find image  'xxx' locally ,会自动搜索Docker-Hub 并pull ,如果找不到就返回错误
docker run hello-world

# 10、查看镜像
docker images  # 貌似可以简化为docker ps

# 11、卸载docker的步骤
# 卸载依赖
sudo yum remove docker-ce
# 删除资源
sudo rm -rf /var/lib/docker

2.2 阿里云镜像仓库加速

产品服务 -> 弹性计算 -> 容器镜像服务

# 创建文件夹
sudo mkdir -p /etc/docker

# 设置加速器地址【加速地址换成你的】
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://dsvlpgtd.mirror.aliyuncs.com"]
}
EOF

# 重新加载配置
sudo systemctl daemon-reload

# 重启docker
sudo systemctl restart docker

腾讯云也有

# 执行以下命令,打开 /etc/docker/daemon.json 配置文件
vim /etc/docker/daemon.json

# 按 i 切换至编辑模式,添加以下内容,并保存。
{
   "registry-mirrors": ["https://mirror.ccs.tencentyun.com"]
}
# 重新加载配置
sudo systemctl daemon-reload

# 执行以下命令,重启 Docker 即可
sudo systemctl restart docker

2.3 底层原理

是一个CS结构的系统。

工作流程

在这里插入图片描述

外面的Linux服务器是访问不到容器里的东西的,同时各个容器之间也是互相隔离的,如果互通,需要后期的配置

Docker比Vm快

抽象层数比较少,新建一个容器的时候不需要像虚拟机一样重新加载一个操作系统的内核,速度会更快。

虚拟机是加载Guets OS(分钟级),Docker是利用宿主主机的系统(秒级)

2.4 常用命令

帮助文档地址 Reference documentation | Docker Documentation

# 帮助命令(万能)
docker 命令 --help # eg: docker images --help
2.4.1 镜像命令
# 1、search 搜索镜像
docker search mysql
# 可选参数(过滤)
docker search mysql --filter=STARS=3000

# 2、pull 下载镜像
docker pull mysql  # 默认latest version
# image的核心:分层下载 联合文件系统 公有的下次就不用下载了,非常节省内存!!!!
# 指定版本下载(一定要在docker-hub上有)
docker pull mysql:5.7

# 3、images 查看镜像
docker images # 可选参数a(查看所有的) q(只查看ID)

# 4、remove 删除镜像
docker rmi -f 镜像id # 可以通过id或者name来指定删除
docker rmi -f ${docker images -aq}
2.4.2 容器命令

有了镜像才可以创建容器

# 1、下载一个centos
docker pull centos

# 2、启动并进入容器
docker run 镜像id
# 参数说明
--name="Name"		# 容器名字 tomcat01 tomcat02 用来区分容器
-d					# 后台方式运行
-it 				# 使用交互方式运行,进入容器查看内容
-p					# 指定容器的端口 -p 8080(宿主机):8080(容器)
		-p ip:主机端口:容器端口
		-p 主机端口:容器端口(常用)
		-p 容器端口
-P(大写) 				随机指定端口
#eg:docker run -d -p 6030-6049:6030-6049 -p 6030-6049:6030-6049/udp --name tdengine tdengine/tdengine
# 可以加-d后台运行,也可以Ctrl+P+Q退出(不会停止)

# 3、列出所有运行的容器
docker ps # -a可以显示历史运行的 -q只显示id,和images的命令差不多

# 4、删除容器
docker rm 容器id # 删除指定容器
docker rm -f ${docker ps -aq}

# 5、启动和停止容器
docker start 容器id	# 启动容器
docker restart 容器id	# 重启容器
docker stop 容器id	# 停止当前正在运行的容器
docker kill 容器id	# 强制停止当前容器

exit # 容器停止并退出
Ctrl + P + Q # 容器不停止并退出
2.4.3 其他命令
# 1、后台启动的坑
docke run -d centos  
# 当docker ps 的时候发现没有被启动
# 后台运行必须要有前台进程,否则会自动停止
docker run -d centos /bin/bash

# 2、logs日志命令
# 先运行一个新的容器,刚才那个centos,我们可以结束掉,
docker stop centos容器的id
# 编写一段shell脚本 每1秒输出一次xiaowei
docker run -d centos /bin/sh -c "while true;do echo xiaowei;sleep 1;done"  # 小写的c
# 查看一下运行的容器 
docker ps
# 显示日志
docker logs -tf --tail 10 centos容器的id  # 必须要加参数10,显示10条记录数

# 3、查看容器中的进程信息
docker top 容器id

# 4、查看容器的元数据
docker inspect 容器id

# 5、进入当前正在运行的容器
docker exec -it 容器id bash  # 开启一个新的终端
docker attach 容器id   # 进入容器正在执行的终端,不会启动新的进程

# 6、容器内部文件拷贝到主机上
docker cp 容器id:容器内路径 容器外
# 在centos容器里面home目录下新建一个test.txt
docker attach 容器id
cd /home
touch test.txt
# exit 退出到宿主机
docker ps
# 虽然容器停止了,但并不影响我们拷贝文件
docker cp 容器id:/home/test.txt /home
# ls 查看

2.5 实践

2.5.1 安装nginx(端口映射)
# 1、去官网搜索nginx
# 2、拉取镜像
docker pull nginx

# 3、后台创建并启动容器
docker run -d --name nginx01 -p 3001:80 nginx
# -p 3001是外网的端口 80是nginx的默认的端口 这是个映射的概念 
 
# 4、打开端口
firewall-cmd --zone=public --add-port=3001/tcp --permanent 
firewall-cmd --reload

# 5、运行测试
curl localhost:3001
# 宿主机也是可以访问的

# 6、停止容器,就访问不到了
docker stop nginx01
2.5.2 安装tomcat(有坑)
# 1、用完即删 --rm (不建议)
docker run -it --rm tomcat:9.0

# 2、拉取镜像(刚才已经下了)
docker pull tomcat:9.0

# 3、后台创建并启动容器
docker run -d --name tomcat01 -p 4001:8080 tomcat:9.0
# 测试访问正常,但没有页面,因为命令被减了,没有webapps、默认最小的镜像,只保证可运行
# 进入容器内部
docker run -d --name tomcat01 -p 4001:8080 tomcat:9.0
# 拷贝文件到webapps
cp -r webapps.dist/* webapps

# 测试访问就正常了
2.5.3 问题小结Note

查看内存占用情况 docker stats

不能每次部署项目都需要重新进入容器吧,很麻烦,

我们可以在容器外部提供一个映射路径,在外部部署项目,自动同步到内部,用到的概念

--rm是用完即删

2.6 可视化

使用Portainer图形化界面管理工具,提供后台面板操作

docker run -d -p 5001:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
# 记得开端口,重新加载防火墙
image-20220712135049675

3. Docker镜像讲解

3.1 镜像是什么

镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,包含运行某个软件所需的所有内容,包括代码、运行时库、环境变量和配置文件。

所有应用,直接打包docker镜像,就可以直接跑起来!

3.2 Docker镜像加载原理

UnionFs (联合文件系统)

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

Docker镜像加载原理

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

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

3.3 分层理解

最大的好处,我觉得莫过于资源共享了!比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。

3.4 commit镜像

就拿刚才的tomcat来练,修改好webapps之后

docker commit -a="xiaowei" -m="add webapps applications" 容器id tomcat02:1.0
docker images # 即可查看到

这个类似于VMware的快照

4. 容器数据卷

4.1 问题提出

回到上面提的问题

不能每次部署项目都需要重新进入容器吧,很麻烦,我们可以在容器外部提供一个映射路径,在外部部署项目,自动同步到内部,用到的概念

抛出一个问题

如果数据都在容器中,那删除容器,数据都会丢失,但是需要数据可以持久化,比如MySQL的数据,让数据存储在本地,就要使用到容器数据卷,使容器之间有一个数据共享的技术!

目录挂载,挂载到Linux上

4.2 使用数据卷

4.2.1 Centos测试文件关联
-v, --volume list                    Bind mount a volume

docker run -it -v 主机目录:容器内目录  -p 主机端口:容器内端口

/home/ceshi:主机home目录下的ceshi文件夹  映射:centos容器中的/home

docker run -it -v /home/ceshi:/home centos /bin/bash
# 这时候主机的/home/ceshi文件夹就和容器的/home文件夹关联了,二者可以实现文件或数据同步了

# 通过 docker inspect 容器id 查看
docker inspect 6064c490c371

继续测试

停止容器 --> 宿主机修改文件 --> 启动容器 --> 容器内的数据依旧是同步

4.2.2 测试MySQL
# 1、镜像拉取
# 2、创建并运行容器
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

firewall-cmd --zone=public --add-port=3310/tcp --permanent
firewall-cmd --reload

# 3、Navicat测试成功 vm1:3310

# 4、本地测试创建一个数据库test,在linux中home/mysql/data中可以看到

就算容器删除,docker rm -f mysql01,数据也不会丢失,即容器数据卷技术

4.2.3 测试一个TDengine(待测)
docker run -d -p 6030-6049:6030-6049 -p 6030-6049:6030-6049/udp -v td1:/etc/taos --name td1 tdengine/tdengine

这种是具名挂载,不指定目录,会在本机统一的一个目录,里面有taos.cfg 但是修改了FQDN之后就启动不了TDengine了,原因是它默认的FQDN是该容器id,不一致启动不了,而且在创建并run这个TDengine容器的时候,没有提示输入集群点

image-20220712172242540

4.3 具名挂载

# 具名挂载 -P:表示随机映射端口
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
9663cfcb1e5a9a1548867481bfddab9fd7824a6dc4c778bf438a040fe891f0ee

# 查看所有的volume(卷)的情况
$ docker volume ls                  
DRIVER              VOLUME NAME
local               21159a8518abd468728cdbe8594a75b204a10c26be6c36090cde1ee88965f0d0
local               b17f52d38f528893dd5720899f555caf22b31bf50b0680e7c6d5431dbda2802c
local               juming-nginx #多了一个名字


# 通过 -v 卷名:查看容器内路径
# 查看一下这个卷
$ docker volume inspect juming-nginx
[
    {
        "CreatedAt": "2020-05-23T13:55:34+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data", #默认目录
        "Name": "juming-nginx",
        "Options": null,
        "Scope": "local"
    }
]
4.3.1 三种挂载方式
# 三种挂载: 匿名挂载、具名挂载、指定路径挂载
-v 容器内路径			# 匿名挂载
-v 卷名:容器内路径		  # 具名挂载
-v /宿主机路径:容器内路径 # 指定路径挂载 docker volume ls 是查看不到的

所有的docker容器内的卷,没有指定目录的情况下都是在**/var/lib/docker/volumes/自定义的卷名/_data**下,
如果指定了目录,docker volume ls 是查看不到的

4.3.2 拓展
# 通过 -v 容器内路径: ro rw 改变读写权限
ro #readonly 只读
rw #readwrite 可读可写
$ docker run -d -P --name nginx05 -v juming:/etc/nginx:ro nginx
$ docker run -d -P --name nginx05 -v juming:/etc/nginx:rw nginx

# ro 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作!

4.4 数据卷容器

Dockerfile 就是用来构建docker镜像的构建文件!命令脚本!

通过这个脚本可以生成镜像,镜像是一层一层的,脚本是一个个的命令,每个命令都是一层!

4.4.1 通过脚本生成镜像
# 创建一个dockerfile文件,名字可以随便 建议Dockerfile
# 文件中的内容: 指令(大写) + 参数
$ vim home/docker-test-volume/dockerfile1
    FROM centos 					# 当前这个镜像是以centos为基础的

    VOLUME ["volume01","volume02"] 	# 挂载卷的卷目录列表(多个目录)

    CMD echo "-----end-----"		# 输出一下用于测试
    CMD /bin/bash					# 默认走bash控制台

# 这里的每个命令,就是镜像的一层!
# 构建出这个镜像 
-f home/docker-test-volume/dockerfile1 			# f代表file,指这个当前文件的地址
-t xw/centos 	# t就代表target,指目标目录(注意xw镜像名前不能加斜杠‘/’)
. 						# 表示生成在当前目录下
$ docker build -f home/docker-test-volume/dockerfile1 -t xw/centos .
Sending build context to Docker daemon   2.56kB
Step 1/4 : FROM centos
latest: Pulling from library/centos
8a29a15cefae: Already exists 
Digest: sha256:fe8d824220415eed5477b63addf40fb06c3b049404242b31982106ac204f6700
Status: Downloaded newer image for centos:latest
 ---> 470671670cac
Step 2/4 : VOLUME ["volume01","volume02"] 			# 卷名列表
 ---> Running in c18eefc2c233
Removing intermediate container c18eefc2c233
 ---> 623ae1d40fb8
Step 3/4 : CMD echo "-----end-----"					# 输出 脚本命令
 ---> Running in 70e403669f3c
Removing intermediate container 70e403669f3c
 ---> 0eba1989c4e6
Step 4/4 : CMD /bin/bash
 ---> Running in 4342feb3a05b
Removing intermediate container 4342feb3a05b
 ---> f4a6b0d4d948
Successfully built f4a6b0d4d948
Successfully tagged caoshipeng/centos:latest

# 查看自己构建的镜像
$ docker images
REPOSITORY          TAG          IMAGE ID            CREATED              SIZE
xw/centos          latest       f4a6b0d4d948        About a minute ago   237MB

进入这个容器之后ls

image-20220712175211739

前面有个卷挂载

VOLUME [“volume01”,“volume02”]

# docker inspect 容器id
docker inspect ca3b45913df5

image-20220712175337815

4.4.2 测试Centos

父容器的概念 --volumes-from

# 测试 启动3个容器,通过刚才的镜像启动
# 创建docker01
$ docker run -it --name docker01 xw/centos

# 查看容器docekr01内容
$ ls
bin  home   lost+found	opt   run   sys  var
dev  lib    media	proc  sbin  tmp  volume01
etc  lib64  mnt		root  srv   usr  volume02

# 不关闭该容器退出
CTRL + Q + P  

# 创建docker02: 并且让docker02 继承 docker01
$ docker run -it --name docker02 --volumes-from docker01 xw/centos

# 查看容器docker02内容
$ ls
bin  home   lost+found	opt   run   sys  var
dev  lib    media	proc  sbin  tmp  volume01
etc  lib64  mnt		root  srv   usr  volume02

多个容器之间的数据是拷贝

# 测试:可以删除docker01,查看一下docker02和docker03是否可以访问这个文件

# 测试发现:数据依旧保留在docker02和docker03中没有被删除
4.4.3 多个mysql实现数据共享
$ docker run -d -p 3306: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 3310:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01  mysql:5.7

# 这个时候,可以实现两个容器数据同步!

结论:

容器之间的配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止

但是一旦你持久化到了本地,这个时候,本地的数据是不会删除的

5. DockerFile

5.1 构建步骤

1、 编写一个dockerfile文件

2、 docker build 构建成为一个镜像

3、 docker run运行镜像

4、 docker push发布镜像(DockerHub 、阿里云仓库)

很多官方镜像都是基础包,很多功能没有,我们通常会自己搭建自己的镜像!

5.2 构建过程

基础知识:

1、每个保留关键字(指令)都是必须是大写字母

2、执行从上到下顺序

3、每一个指令都会创建提交一个新的镜像层,并提交!

5.3 DockerFile的指令

FROM				# from:基础镜像,一切从这里开始构建
MAINTAINER	# maintainer:镜像是谁写的, 姓名+邮箱
RUN					# run:镜像构建的时候需要运行的命令
ADD					# add:步骤,tomcat镜像,这个tomcat压缩包!添加内容 添加同目录
WORKDIR			# workdir:镜像的工作目录
VOLUME			# volume:挂载的目录
EXPOSE			# expose:暴露端口配置
CMD					# cmd:指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT	# entrypoint:指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD			# onbuild:当构建一个被继承DockerFile这个时候就会运行onbuild的指令,触发指令
COPY				# copy:类似ADD,将我们文件拷贝到镜像中
ENV					# env:构建的时候设置环境变量!

创建一个自己的centos

# 1./home下新建dockerfile目录
$ mkdir dockerfile

# 2. dockerfile目录下新建mydockerfile-centos文件
$ vim mydockerfile-centos

# 3.编写Dockerfile配置文件
FROM centos:7							# 基础镜像是官方原生的centos7,记得指定版本号,不然报错
MAINTAINER xiaowei<1437591651@qq.com> 	# 作者

ENV MYPATH /usr/local				# 配置环境变量的目录 
WORKDIR $MYPATH						# 将工作目录设置为 MYPATH

RUN yum -y install vim				# 给官方原生的centos 增加 vim指令
RUN yum -y install net-tools		# 给官方原生的centos 增加 ifconfig命令

EXPOSE 80							# 暴露端口号为80

CMD echo $MYPATH					# 输出下 MYPATH 路径
CMD echo "-----构建成功-----"				
CMD /bin/bash						# 启动后进入 /bin/bash

# 4.通过这个文件构建镜像
# 命令: docker build -f 文件路径 -t 镜像名:[tag] .
$ docker build -f mydockerfile-centos -t mycentos .  # 千万记住最后这个.

# 5.出现以下则构建成功
Successfully built 8b56fe496ff7
Successfully tagged mycentos:latest

成功创建并进入容器

image-20220712193647461

docker history 镜像id   # 查看镜像构建历史步骤

CMD 和 ENTRYPOINT区别

CMD					# cmd:指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT	# entrypoint:指定这个容器启动的时候要运行的命令,可以追加命令

5.4 实战:Tomcat镜像 Fail

准备tomcat和jdk的tar包,放到home/cestbon/tomcat下备用,创建一个readme.txt

vim dockerfile
FROM centos:7
MAINTAINER xiaowei<1437591651@qq.com>

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

ADD jdk-8u333-linux-x64.tar.gz /usr/local
ADD apache-tomcat-9.0.64-deployer.tar.gz  /usr/local

RUN yum -y install vim

ENV MYPATH /usr/local
WORKDIR $MYPATH

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

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

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

EXPOSE 8080

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

构建镜像

docker build -t diytomcat . # 因为我们的那个文件就是dockerfile所以不需要-f指明文件
docker run -d -p 9090:8080 --name xwtomcat -v /home/cestbon/build/tomcat/test:/usr/local/apache-tomcat-9.0.64/webapps/test -v /home/cestbon/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.64/logs diytomcat 

PS: 貌似出现了问题

5.5 push镜像

发布到docker - hub

# 登录
$ docker login --help
Usage:  docker login [OPTIONS] [SERVER]

Log in to a Docker registry.
If no server is specified, the default is defined by the daemon.

Options:
  -p, --password string   Password
      --password-stdin    Take the password from stdin
  -u, --username string   Username

$ docker login -u 你的用户名 -p 你的密码

# push不上去,因为如果没有前缀的话默认是push到 官方的library
# 解决方法:
# build的时候添加你的dockerhub用户名,然后在push就可以放到自己的仓库了
$ docker build -t xw1437591651/mytomcat:1.0 .
$ docker push xw1437591651/mytomcat:1.0

发布到阿里云上

官网很详细的步骤

$ sudo docker login --username=xxx registry.cn-shenzhen.aliyuncs.com
$ sudo docker tag [ImageId] registry.cn-shenzhen.aliyuncs.com/dsadxzc/xw:[镜像版本号]

# 修改id 和 版本
sudo docker tag a5ef1f32aaae registry.cn-shenzhen.aliyuncs.com/dsadxzc/xw:1.0
# 修改版本
$ sudo docker push registry.cn-shenzhen.aliyuncs.com/dsadxzc/xw:[镜像版本号]

6. Docker网络

6.1 测试两个tomcat

1、清除之前的镜像和容器

# 删容器
[root@vm1 /]# docker rm -f $(docker ps -aq)
3175611d31b2
a88696c1b79a
5d7b213c9400
6718f7cd0132
82d1622e2c66

# 删镜像
[root@vm1 /]# docker rmi $(docker images -aq)
Untagged: diytomcat:latest
Deleted: sha256:146a61c5be3e63763087289bcff44b42439c3df9099194797c7beaf56a70db16
Deleted: sha256:2569c5a6ecdc1c02e23640d79e1677b9d4a4b2dd5548faea4780c1fe7b7184bb
Deleted: sha256:a535f16fa183af8cf5837ce0690383569f2ee7dc6016a17e436190ce7d2080b2
Deleted: sha256:1636e876cf8889ae2f4d00f60bc778bee92315af648c7113ab798a9bab85af5d
Deleted: sha256:995a5eece07c0ffb88177cc2932765f237452a53e01f02eed3b40d8ac5d6f9b7

# 完毕
[root@vm1 /]# docker images
REPOSITORY   TAG       IMAGE ID   CREATED   SIZE
[root@vm1 /]# docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

2、创建启动一个tomcat容器tomcat01

创建之前查看当前的ip 信息 ip addr

image-20220713142040752

# 创建容器
docker run -d -P --name tomcat01 tomcat

# 再次查看ip addr

# 进入容器tomcat01查看ip addr (如果报错没有ip指令)
# 执行如下命令
apt update
apt install -y iproute2
# 查看ip (若报错,章节末有解决办法)
root@6936e1963a31:/usr/local/tomcat# ip a
......
12: eth0@if13: <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  # 可以看到172.17.0.2

# 虚拟机ping容器
[root@vm1 /]# 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.043 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.044 ms

3、再启动一个tomcat02

[root@vm1 /]# docker run -d -P --name tomcat02 tomcat:9.0
190d8f40845ab89341e94d4b76415905e9cee49b3ffca2d742ae8f25dfca9533

# 可以看到两对(12:13 14:15)
13: veth70da156@if12: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether c6:e8:18:05:f4:5d brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::c4e8:18ff:fe05:f45d/64 scope link 
       valid_lft forever preferred_lft forever
15: veth3bdcb93@if14: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether e6:a6:2c:d8:5d:8f brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet6 fe80::e4a6:2cff:fed8:5d8f/64 scope link 
       valid_lft forever preferred_lft forever

# 进入容器tomcat02
docker exec -it tomcat02 bash
apt update
apt install -y iproute2

root@190d8f40845a:/usr/local/tomcat# ip a
......
14: eth0@if15: <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   # 可以看到172.17.0.3

4、测试容器互通

我们来测试下tomcat01和tomcat02是否可以ping通

# (若报错,章节末有解决办法)
[root@vm1 /]# 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.053 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.052 ms

6.2 原理

我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个docker0桥接模式,使用的技术是veth-pair技术!

veth-pair 就是一对的虚拟设备接口,它都是成对出现的。一端连着协议栈,一端彼此相连。 正因为有这个特性 veth-pair 充当一个桥梁,连接各种虚拟网络设备的。

模型图

img

6.3 需求变化

思考一个场景:我们编写了一个微服务,database url=ip: 项目不重启,数据ip换了,我们希望可以处理这个问题,可以通过名字来进行访问容器

比如:docker exec -it tomcat02 ping tomca01 # ping不通

两种解决办法

6.3.1 --link解决(不建议)
# 通过--link来解决(只能正向连接)(不建议使用)
docker run -d -P --name tomcat03 --link tomcat02 tomcat:9.0

# 默认你tomcat有ping命令
[root@vm1 /]# 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.068 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.096 ms

docker exec -it tomcat02 ping tomcat03 # 失败,不能反向ping,下面看原理探究

原理探究

通过网卡信息来看

[root@vm1 /]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
8d890099890e   bridge    bridge    local
84bce780a9bf   host      host      local

# 可以通过docker network inspect 网络id 看信息
docker network inspect 8d890099890e
# 看这个部分(删掉了EndpointID和MacAddress)
"Containers": {
            "190d8f40845ab89341e94d4b76415905e9cee49b3ffca2d742ae8f25dfca9533": {
                "Name": "tomcat02",
                "IPv4Address": "172.17.0.3/16",
            },
            "6936e1963a31e6900586cb7fb740fa0ad4d83362b8109df1df76a106b2345348": {
                "Name": "tomcat01",
                "IPv4Address": "172.17.0.2/16",
            },
            "78bbf798a98e4cfef615b7d81e69052223d846f0ac3b91f321a4c487b3ab1eb8": {
                "Name": "tomcat03",
                "IPv4Address": "172.17.0.4/16",
            }
        }

通过容器的hosts查看

[root@vm1 /]# docker exec -it tomcat03 cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
172.17.0.3	tomcat02 190d8f40845a # 这里
172.17.0.4	78bbf798a98e

# 它是直接在hosts里写死了访问tomcat02的一个地址解析
# 但tomcat02里没有写tomcat03的,所以不能反向ping

结论:–link就是做映射,不建议使用,因为docker0不支持容器名连接访问,使用自定义网络

6.3.2 自定义网络(建议)
# 查看所有的docker网络
[root@vm1 /]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
8d890099890e   bridge    bridge    local
84bce780a9bf   host      host      local

# 网络模式
# bridge :桥接 docker(默认,自己创建也是用bridge模式)
# none :不配置网络,一般不用
# host :和所主机共享网络
# container :容器网络连通(用得少!局限很大)

# rm 之前的tomcat镜像容器

创建自己的网络 mynet

# 创建一个桥接模式的网络,网关是192.168.0.1,范围是192.168.0.2-192.168.255.254
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet

[root@vm1 /]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
8d890099890e   bridge    bridge    local
84bce780a9bf   host      host      local
5d56908490f8   mynet     bridge    local

# 依据刚才的mynet创建两个tomcat容器
docker run -d -P --name tomcat01 --net mynet tomcat
docker run -d -P --name tomcat02 --net mynet tomcat

# 查看这个网络信息
docker network inspect mynet 
 "Containers": {
            "7c7ae41108d7b7310718f318c28bd050282b59f86b32492df861cbe84631fc06": {
                "Name": "tomcat02",
                "IPv4Address": "192.168.0.3/16",
            },
            "fa2aac8af6054082bfbb52aa931595bcf8db33cf8d0eb286f28d44443a8e5fbf": {
                "Name": "tomcat01",
                "IPv4Address": "192.168.0.2/16",
            }
        },

测试容器网络互通 Success

# ping失效的看章节问题解决
[root@vm1 /]# docker exec -it tomcat01 ping tomcat02
PING tomcat02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.057 ms
64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.032 ms
[root@vm1 /]# docker exec -it tomcat02 ping tomcat01
PING tomcat01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.036 ms
64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.068 ms

结论:自定义的docker网络已经维护好了对应的关系,这就是好处,在集群搭建很方便。

6.4 网络连通(容器和网卡)

准备

docker0上两个tomcat容器(tomcat-docker0-01、tomcat-docker0-02)

mynet上两个tomcat容器(tomcat01、tomcat02)

开始

通过connect命令打通docker0上的容器和mynet网卡

[root@vm1 /]# docker network --help
Commands:
  connect     Connect a container to a network
  
[root@vm1 /]# docker network connect --help
Usage:  docker network connect [OPTIONS] NETWORK CONTAINER
# 左边是网络 右边是容器 即 
$ docker network connect mynet tomcat-docker0-01

查看mynet的情况

docker network inspect mynet

image-20220713160640360

可以看到,connect是直接把容器tomcat-docker0-01添加进来到了网卡mynet里面,即一个容器两个ip(类比阿里云的公网IP和私网IP)

测试tomcat-docker0-01和mynet下任意一个网络互通 Success

image-20220713161219034

tomcat-docker0-02是没有打通的哈!自测即可

6.5 实战:部署Redis集群

(非哨兵,用的是分片+高可用+负载均衡)

image-20220713162014416

需要启动6个容器,所以先把之前的容器停止。

[root@vm1 /]# docker stop $(docker ps -aq)
6f64c848d2b9
4579e5bfbeb4
7c7ae41108d7
fa2aac8af605
[root@vm1 /]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

开始创建6个容器

# 创建一个适用于redis的docker网络,像刚才tomcat的mynet一样
docker network create redis --subnet 172.38.0.0/16

# 由于要创建6个容器,所以我们可以写个脚本(非之前的创建镜像的dockerfile)
# 先建立相关文件夹存放6个节点的数据和配置
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
done
[root@vm1 /]# cd mydata/
[root@vm1 mydata]# cd redis/
[root@vm1 redis]# ls
node-1  node-2  node-3  node-4  node-5  node-6

# 创建6个容器,也可以通过脚本(脚本出错,一个个来吧)(应该是要加do 和 EOF done)
for port in $(seq 1 6);\
docker run -p 637${port}:6379 -p 1667${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

docker run -p 6371:6379 -p 16671:16379 --name redis-1 \
-v /mydata/redis/node-1/data:/data \
-v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6372:6379 -p 16672:16379 --name redis-2 \
-v /mydata/redis/node-2/data:/data \
-v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6373:6379 -p 16673:16379 --name redis-3 \
-v /mydata/redis/node-3/data:/data \
-v /mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6374:6379 -p 16674:16379 --name redis-4 \
-v /mydata/redis/node-4/data:/data \
-v /mydata/redis/node-4/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6375:6379 -p 16675:16379 --name redis-5 \
-v /mydata/redis/node-5/data:/data \
-v /mydata/redis/node-5/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.15 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker run -p 6376:6379 -p 16676:16379 --name redis-6 \
-v /mydata/redis/node-6/data:/data \
-v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

进入redis的任意一个容器

# redis默认没有bash
docker exec -it redis-1 /bin/sh 
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
# 结果

image-20220713165303248

测试集群

# 进入redis集群 要加-c 也就是cluster
/data # redis-cli -c
127.0.0.1:6379> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3   # 主从复制 6除以2
cluster_current_epoch:6
cluster_my_epoch:1

查看集群的节点,红色的是主,绿色的是从

image-20220713165422198

存入一个值

127.0.0.1:6379> set username xiaowei
-> Redirected to slot [14315] located at 172.38.0.13:6379  # 自动存在了后缀为13的这个节点上
OK
172.38.0.13:6379> get username  # 当前可以正常取到值
"xiaowei"

我们测试,把这个后缀为13的这个节点给停掉,看还能不能取到值(应该是可以的才是预期结果,因为是存在一个主从节点的概念,一个节点宕机了,另一个节点会顶上,也就是高可用的概念)

# 停掉后缀为13的这个节点,也就是redis-3
[root@vm1 /]# docker stop redis-3
redis-3

查看集群节点状态

image-20220713170202777

因为13宕机了,所以14变成了master。

# 再次取值
127.0.0.1:6379> get username
-> Redirected to slot [14315] located at 172.38.0.14:6379  # 发现是一个重定向到了后缀为14的节点
"xiaowei"

6.6 本章问题解决

1、ip addr显示的是ipv6的地址

(正常,虚拟机显示的是ipv6,但进入容器,有对应的ipv4的)

Docker映射端口时仅有IPv6无法到IPv4解决方法 - 掘金 (juejin.cn)

2、tomcat镜像里面的ip、ping失效

原因:缩水版的tomcat镜像没有这些命令,需要自己安装

apt update
apt install -y net-tools
apt install -y iproute2
apt install -y iputils-ping

7. Spring Boot打包镜像

1、package一个jar包出来,写一个Dockerfile文件(注意大小写,完全符合的话,IDEA是可以识别到的)

FROM java:8

COPY *.jar /app.jar

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

EXPOSE 8080

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

2、上传到Linux上,我的位置在home/cestbon/idea/

[root@vm1 /]# cd /home/cestbon/idea
[root@vm1 idea]# ls
back-manage.jar  Dockerfile

3、构建镜像

# build镜像
[root@vm1 idea]# docker build -t back-manage:1.0 .
Sending build context to Docker daemon  32.38MB
Step 1/5 : FROM java:8

8: Pulling from library/java
.......

# 查看刚才构建的镜像
[root@vm1 idea]# docker images
REPOSITORY    TAG                IMAGE ID       CREATED          SIZE
back-manage   1.0                6f95119a7089   10 seconds ago   676MB

4、push镜像

# 登录
docker login -u 你的用户名 -p 你的密码

# 修改tag 加上自己dockerHub的用户名和版本号
[root@vm1 idea]# docker tag  back-manage:1.0  xw1437591651/back-manage:1.0
[root@vm1 idea]# docker images
REPOSITORY                 TAG                IMAGE ID       CREATED              SIZE
back-manage                1.0                6f95119a7089   About a minute ago   676MB
xw1437591651/back-manage   1.0                6f95119a7089   About a minute ago   676MB

# push 成功
[root@vm1 idea]# docker push xw1437591651/back-manage:1.0
The push refers to repository [docker.io/xw1437591651/back-manage]
4023cf9d4fff: Pushed 
35c20f26d188: Pushed 
c3fe59dd9556: Pushed 
6ed1a81ba5b6: Pushed 
a3483ce177ce: Pushed 
ce6c8756685b: Pushed 
30339f20ced0: Pushed 
0eb22bfb707d: Pushed 
a2ae92ffcd29: Pushed 
1.0: digest: sha256:0101dd1eb94eb83304e2f5c7a8f30dd09ff597a6fda27d0aa7a7f0ff423f6a2b size: 2212

推送镜像被拒绝可能是因为你镜像的命名问题,注意前缀和版本号

5、根据镜像创建并启动容器,测试访问 Success

image-20220713174505003

Docker笔记进阶

1. Docker Compose

1.1 介绍

" 之前的操作步骤 " ==> Dockerfile build run 手动操作,单个容器!

Compose是Docker官方的开源项目,需要安装

Docker Compose 来轻松高效的管理容器,定义运行多个

Dockerfile让程序在任何地方运行。web服务、redis、mysql、nginx… 多个容器。 run

1.2 安装

# 在线安装:
curl -L https://get.daocloud.io/docker/compose/releases/download/2.6.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose

# 建议离线安装:https://github.com/docker/compose/releases/download/v2.6.1/docker-compose-linux-s390x
# 下载后,将docker-compose-Linux-x86_64重命名为docker-compose
# 将刚才下载的docker-compose文件上传到centos7的/usr/local/bin/目录下


# 添加可执行权限
sudo chmod +x /usr/local/bin/docker-compose

# 查看docker-compose版本
docker-compose -v

1.3 快速开始

看官网,很详细 Get started with Docker Compose | Docker Documentation

[root@vm1 home]# mkdir composetest
[root@vm1 home]# cd composetest
[root@vm1 composetest]# vim app.py
# -------------------------
import time
import redis
from flask import Flask
app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)  # 注意这里的redis,并不是我们之前的localhost:xx
 
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)

if __name__ == "__main__":
  app.run(host="0.0.0.0",debug=True)
# -------------------------

[root@vm1 composetest]# vim requirements.txt
[root@vm1 composetest]# vim Dockerfile
# -------------------------因为官网的还有gcc,很大,这里是简化版
FROM python:3.6-alpine
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt
CMD ["python","app.py"]
# -------------------------

[root@vm1 composetest]# vim docker-compose.yml
# -------------------------用于容器的编排
version: '3.8'
services:
  web:
    build: .
    ports:
      - "5000:5000"
    volumes:
      - .:/code
  redis:
    image: "redis:alpine"
# -------------------------

[root@vm1 composetest]# ls
app.py  docker-compose.yml  Dockerfile  requirements.txt
[root@vm1 composetest]# docker-compose -v
Docker Compose version v2.6.1
[root@vm1 composetest]# docker-compose up
# 结果

image-20220714100546969

测试访问 Success

image-20220714100650274

网络规则

会有一个默认的网络,项目中的内容都在同一个网络下,可以通过域名访问,比如mysql:3306 redis:6379

image-20220714101138643

结论:docker-compose编写yml文件,对所有的容器统一进行管理(启动、停止)

1.4 yaml规则(重要)

version: '' # 版本
services: 
  服务1: web
    # 服务配置
    images
    build
    network
    ...
  服务2: 
  服务3:
 
# 其他配置:网络/卷/全局规则
volumes:
networks:
configs:

1.5 实战

1.5.1 WordPress博客

文档地址:Quickstart: Compose and WordPress | Docker Documentation:

version: '3.8'
services:
	db:
		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:

测试 Success:

image-20220714104927327

image-20220714104912570
1.5.2 微服务上线

1、微服务项目打jar包,yml里的spring.redis.host=redis (本地是启动不了的,在docker里可以)

2、Dockerfile构建镜像

FROM java:8

COPY *.jar /app.jar
 
CMD ["--server.port=8080"]
 
EXPOSE 8080
 
ENTRYPOINT ["java", "-jar", "/app.jar"]

3、docker-compose.yml编排项目

version '3.8'
services:
  xwapp:
    build: .
    image: xwapp
    depends_on:
      - redis
    ports:
      - "8080:8080"
  redis:
    image: "library/redis:alpine"

4、项目重新部署构建

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

2. Docker Swarm

2.1 准备服务器

按量计费的买4台服务器

参考文档:https://blog.csdn.net/weixin_44589991/article/details/121704538:

1、生成主节点init,设置ip地址,私网地址

[root@iZ2ze58v8acnlxsnjoulk5Z ~]# docker swarm init --advertise-addr 172.16.250.97
Swarm initialized: current node (otdyxbk2ffbogdqq1kigysj1d) is now a manager.
To add a worker to this swarm, run the following command:
    docker swarm join --token SWMTKN-1-3vovnwb5pkkno2i3u2a42yrxc1dk51zxvto5hrm4asgn37syfn-0xkrprkuyyhrx7cidg381pdir 172.16.250.97:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

2、获取令牌,分为worker和manager

# 获取令牌
docker swarm join-token manager
docker swarm join-token worker

3、加入节点

[root@iZ2ze58v8acnlxsnjoulk6Z ~]# docker swarm join --token SWMTKN-1-3vovnwb5pkkno2i3u2a42yrxc1dk51zxvto5hrm4asgn37syfn-0xkrprkuyyhrx7cidg381pdir 172.16.250.97:2377
This node joined a swarm as a worker.

2.2 Raft协议

1、双主双从:假设一个节点挂了!其他节点是否可用!

Raft协议:保证大多数节点存活才可以用,只要>1,集群至少大于3台(重要)

例子详解Raft协议

4个节点,我们设置3个为manager节点,那么停止1个manager,仍然可以继续使用集群

但是如果2个manager和2个work节点,停止1个manager,就不能使用集群了

2.3 动态扩缩容

[root@iZ2ze58v8acnlxsnjoulk5Z ~]# docker service update --replicas 3 my-nginx
1/3: running   [==================================================>] 
2/3: running   [==================================================>] 
3/3: running   [==================================================>] 
verify: Service converged 
 
 
[root@iZ2ze58v8acnlxsnjoulk5Z ~]# docker service scale my-nginx=5
my-nginx scaled to 5
overall progress: 3 out of 5 tasks 
overall progress: 3 out of 5 tasks 
overall progress: 3 out of 5 tasks 
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@iZ2ze58v8acnlxsnjoulk5Z ~]# docker service scale my-nginx=1
my-nginx scaled to 1
overall progress: 1 out of 1 tasks 
1/1: running   [==================================================>] 
verify: Service converged 

2.4 基本概念

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

node: 就是一个docker节点。多个节点组成一个网络集群。(管理、工作者)

Service:任务,可以在管理节点或者工作节点来运行。核心!用户访问!

**Task:**容器内的命令,细节任务!

CI/CD之Jenkis

Docker实践

Docker安装tDengine

run -d 后台运行容器

然后docker ps 查看运行的容器,docker ps -a是列出所有的容器(包括未运行的)

image-20220706194710708

此时输入taos是没有用的

image-20220706194814114

需要进入这个容器!!!

进入某个容器的命令是docker exec -it name bash (bash是为了打开一个交互式的窗口,防止立马关闭)

image-20220706195013132

此时输入toas即可进入数据库系统,当我们使用完毕之后,退出数据库系统,exit

image-20220706194954643

但此时还是不能使用linux命令的,当前只是退出了数据库系统,没有退出容器

image-20220706195116662

还需要再输入一次exit才可以完全退出!!!!(细心的注意,这里箭头指向的地方的不同之处)

image-20220706195240428

解决VMware和Docker冲突的问题

安装VM15.5以上的版本即可

先去任务管理器关闭docker的自启
每次使用vm和docker的时候,去禁用和开启hyper-v,所以不用管两者同时运行了

使用vm时:

打开windows的【启用或关闭windows功能】-》关闭Hyper-V

image-20220707114358358使用管理员powshell输入命令:bcdedit /set hypervisorlaunchtype off
重启电脑

使用docker时:

打开windows的【启用或关闭windows功能】-》勾选Hyper-V,任务管理器那看下是否开启虚拟化
使用管理员powshell输入命令:bcdedit /set hypervisorlaunchtype auto
重启电脑

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值