首页 > 其他分享 >Docker核心讲解(包括实战内容)

Docker核心讲解(包括实战内容)

时间:2023-05-24 21:44:24浏览次数:41  
标签:实战 容器 -- redis 讲解 镜像 Docker root docker

Docker镜像讲解

镜像是什么

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

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

如何得到镜像:

(1)从远程仓库下载

(2)朋友拷贝给你

(3)自己制作一个镜像DockerFile

Docker镜像加载原理

UnionFS(联合文件系统)

我么下载的时候看到的一层层的就是这个

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

Docker镜像加载原理

docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS.

bootfs(boot file system)主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在Docker像的最底层是bootfs。这一与我们典型的Linux/Ux系统是一样的,包含boot加载聚和内核。当bot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs.

rootfs(root fle svstem),在bootfs之上,包合的就是典型 Linux 系统中的 /dey,/proc,/bin,/etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如ubuntu,Centos等等

image-20230427095136431

平时我们安装的虚拟机的Centos都是好几个G,为什么Docker这里才200M

image-20230427095517065

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

分层理解

分层的镜像

我们可以下载一个镜像,注意观察下载的日志输出,可以看到的是一层层的在下载

image-20230427101030195

理解:

所有的 Docker 镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,
举一个简单的例子,假如基于 Ubuntu Linux 16.04 创建一个新的像,这就是新镜像的第一层;如果在该镜像中添加 Python包,就会在基础镜像层之上创建第二个镜像层,如果继续添加一个安全补丁,就会创建第三个镜像层该镜像当前已经包含 3 个镜像层,

如下图所示(这只是一个用于演示的很简单的例子)。

image-20230427102341326

在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图举了一个简单的例子,每个镜像层包含3个文件,而江西包含了来自俩个镜像层的6个文件

image-20230427102605149

上图中的镜像层跟之前图中的略有区别,主要目的是便于展示文件

下图中展示了一个稍微复杂的三层像,在外部看来整个镜像只 6 个文件,这是因为最上层中的文件 7是文件 5 的一个更新版本。

image-20230427102649259

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

image-20230427102755427

特点

Dokcer镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部。

这一层就是我们通常说的容器层,容器执行的都叫镜像层

image-20230427102906353

如何提交一个自己的镜像

commit镜像

docker commit 提交容器成为一个新的副本

#命令和git原理相似
docker commit -m=“提交的描述信息” -a=“作者” 容器id 目标镜像名:[TAG]

实战测试

#1,启动一个tomcat
docker run -it -p 8080:8080 tomcat
#2.发现这个tomcat是没有webapps应用,镜像的原因,官方的镜像默认webapps下面是没有文件的
#3,我们自己拷贝进去
docker exec -it 49ebb06d49a9 /bin/bash
cp -r webapps.dist/* webapps
#4,将我们操作过的容器通过commit提交为一个镜像,我们以后就使用我们修改过的镜像即可,这是我们自己修改的镜像
docker ps
docker commit -a="xiao" -m="add webapps app" 49ebb06d49a9 tomcat02:1.0

image-20230427104222979

如果以后想要保存当前容器的状态,就可以通过commit来提交,获得一个镜像,
相当于虚拟机的快照。

容器数据卷

什么是容器数据卷

docker回顾

将应用和环境打包成一个镜像!

如果数据都在容器内,我们不小心将容器删除,那么数据就会丢书!需求:数据持久化

MySQL,容器删了,删库跑路!需求:MySQL数据可以存储在本地!

容器之间可以有一个数据共享的技术!Docker容器中产生的数据,同步到本地!

这就是卷技术,目录的挂载,将我们容器内的目录,挂载到Linux上面!

image-20230427110106718

总结:容器的持久化和同步操作!容器间也是可以数据共享的

使用数据集

方式一:直接使用命令来挂载 -v

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

#测试
docker run -it -v /home/ceshi:/home centos /bin/bash
#挂载之后,俩个目录中的数据会同步

#启动之后,可以使用docker inspect 容器id来查看

image-20230427110729305

#测试同步

image-20230427111048117

再来测试

1,退出停止容器

2,修改主机上的文件

3,启动容器

4,进入容器内查看文件

image-20230427111406190

好处:我们以后修改只需要在本地修改即可,容器内会自动同步

实战:安装MySQL

思考:MySQL的数据持久化的问题

#1,查找MySQL镜像
docker search mysql
#2,下载MySQL
docker pull mysql:5.7
#3,运行容器,需要数据挂载   #安装启动MySQL,需要配置密码,注意!!!
-d 后台运行
-p 端口映射
-v 数据卷挂载
-e 环境配置
--name  容器名字
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=123.com --name mysql01 mysql:5.7

image-20230427113629630

假设我们将容器删除

image-20230427113740254

发现,我们挂载到本地的数据卷依旧没有丢失,这就实现了容器数据持久化功能

具名和匿名挂载

#匿名挂载
-v 容器内路径
docker run -d -P --name nginx01 -v /etc/nginx nginx

#查看所有的卷情况
[root@server3 ~]# docker volume ls
local     5d0203e5bd51a7ec9e6ee66b2a08d4fcc45f298d6ec948191f39f247057aebc9

#这里发现,这种就是匿名挂载,我们在-v只写了容器内的路径,没有写容器外的路径

#具名挂载
[root@server3 home]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
[root@server3 home]# docker volume ls
DRIVER    VOLUME NAME
local     juming-nginx
#通过-v 卷名:容器内路径
#查看一下这个卷

image-20230427195922228

所有的docker容器内的卷,没有指定目录的情况下都在:/var/lib/docker/volumes/xxxx/_data

我们通过具名挂载可以方便找到我们的一个卷,大多数情况下在使用的是具名挂载

#如何确定是具名挂载还是匿名挂载,还是指定路径挂载!
-v 容器内路径        #匿名挂载
-v 卷名:容器内路径    #具名挂载
-v /宿主机路径:容器内路径   #指定路径挂载

拓展:

#通过-v 容器内路径:ro  rw 改变读写权限
ro  readonly   #只读
rw  readwrite  #可读可写

#一旦这个设置了容器权限,容器对我们挂载出来的内容就有限定了
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx

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

初始Dockefile

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

通过这个脚本可以生成镜像,镜像是一层

#创建一个dockerfile文件,名字随意
#[root@server3 docker-test-volume]# pwd
/home/docker-test-volume
#[root@server3 docker-test-volume]# vim dockerfile1
#文件的内容 指令(大写) 参数
FROM centos

VOLUME ["volume01","volume02"]

CMD echo "----end-----"
CMD /bin/bash
#这里的每个命令,就是镜像的一层

#运行
docker build -f ./dockerfile1 -t xiao/centos .

image-20230427202527504

#启动自己生成的容器
docker run -it 5c7b97318f1d /bin/bash

image-20230427202853059

这个卷和外部一定有一个

image-20230427204059504

查看一下卷挂载的路径

docker inspect cb59d9df13e3

image-20230427204149037

测试一下刚才的文件是否同步出去了

这种方式使用的十分多,因为通常会构建自己的镜像

假设构建镜像时候没有挂载卷,要手动镜像挂载 -v 卷名:容器内陆

image-20230427204325254

image-20230427210224795

数据卷容器

多个MySQL同步数据

image-20230427210557227

#启动3个容器,通过我们刚才自己的写镜像启动

image-20230427211823873

image-20230427211955182

我们在docker01中的volume01中创建数据,看看docker02中有没有

#切入docker01中
docker ps
docker attach 19313ef46034
#创建数据
cd volume01
touch docker01

#进入docker02中查看

image-20230427212631575

image-20230427213033071

#测试,可以删除docker01,查看docker02和docker03是否还可以访问这个文件
#测试依旧可以访问

image-20230427214005159

多个MySQL实现数据共享

#docker run -d -p 3310:3306 -v /etc/mysql/conf.d -v /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-form mysql101 mysql:5.7

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

结论:

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

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

DockerFile

DockerFile介绍

dockerfile是用来构建docker镜像的文件!命令参数脚本!

构建步骤:

1,编写一个dockerfile文件

2,docker build构成成为一个镜像

3,docker run运行进行

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

查看官方是怎么做的

image-20230427220538032

image-20230427220614681

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

官方既然可以制作镜像,那么我们也可以

DockerFile构建过程

基础知识:

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

2,执行从上到下顺序执行

3,#表示注释

4,每一个指令都会创建提交一个,并提交

image-20230427221050288

dockerfile是面向开发的,以后要发布项目,做镜像,就需要编写dockerfile文件,这个文件十分简单!

Docker镜像逐渐成为了企业交付的标准

DockerFile:构建文件,定义了一切的步骤,源代码

Dockerimages:通过DockerFile构建生成的镜像,最终发布和运行的产品

Docker容器:容器就是镜像运行起来提供服务

DockerFile指令

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

image-20230427222546224

实战测试

Docker Hub中99%镜像都是从这个基础镜像过来的 FROM scrath,然后配置需要的软件和配置进行构建

image-20230427220614681

创建一个自己的centos

#1, 编写DockerFile文件
[root@server3 home]# mkdir dockerfile
[root@server3 home]# cd dockerfile/
[root@server3 dockerfile]# vim mydockerfile-centos
[root@server3 dockerfile]# cat mydockerfile-centos 
FROM centos
MAINTAINER xiao<[email protected]>

ENV MYPATH /usr/local
WORKDIR $MYPATH

RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
RUN sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*(sed这俩条必须加上,要不安装vim会报错)
RUN yum makecache
RUN yum -y install vim 
RUN yum -y install net-tools

EXPOSE 80

CMD echo $MYPATH
CMD echo "-----构建完毕-----"
CMD /bin/bash

#2,通过这个文件构建镜像
#命令 docker build -f dockerfile文件路径 -t 镜像名:[版本号]
docker build -f mydockerfile-centos -t mycentos:0.1 .

#3,测试运行
docker images
docker run -it mycentos:0.1

#发现直接到了我们定义的工作目录,而且ifconfig命令可以用了

image-20230427233525537

对比:之前原生的centos

image-20230427233804501

我们可以列出本地进行的变更历史

image-20230427234002227

我们平时拿到一个镜像,可以研究一下它是怎么做的?

命令是:docker history 镜像id

CMD 和 ENTRYPOINT区别

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

测试cmd

#编写dockerfile文件
[root@server3 dockerfile]# vim dockerfile-cmd
FROM centos
CMD ["ls","-a"]
#构建镜像
[root@server3 dockerfile]# docker build -f dockerfile-cmd -t cmd .
#run运行,发现我们的ls -a命令生效
[root@server3 dockerfile]# docker run b86b1763e009
.
..
.dockerenv
bin
dev
etc
home
lib
lib64

#想追加一个命令-l   ls -al
[root@server3 dockerfile]# docker run b86b1763e009 -l
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "-l": executable file not found in $PATH: unknown.

#cmd的清洗了 -l 替换了CMD ["ls","-a"]命令,-l不是命令所以报错

测试ENTRYPOINT

[root@server3 dockerfile]# vim dockerfile-ENTRYPOINT 
[root@server3 dockerfile]# cat dockerfile-ENTRYPOINT 
FROM centos
ENTRYPOINT ["ls","-a"]
[root@server3 dockerfile]# docker build -f dockerfile-ENTRYPOINT -t entorypoint .
[root@server3 dockerfile]# docker run 82b255a00e
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc

#我们的追加命令,是直接衔接我们的 ENTRYPOINT 命令后面的
[root@server3 dockerfile]# docker run 82b255a00e -l
total 0
drwxr-xr-x.   1 root root   6 Apr 28 08:11 .
drwxr-xr-x.   1 root root   6 Apr 28 08:11 ..
-rwxr-xr-x.   1 root root   0 Apr 28 08:11 .dockerenv
lrwxrwxrwx.   1 root root   7 Nov  3  2020 bin -> usr/bin
drwxr-xr-x.   5 root root 340 Apr 28 08:11 dev
drwxr-xr-x.   1 root root  66 Apr 28 08:11 etc
drwxr-xr-x.   2 root root   6 Nov  3  2020 home
lrwxrwxrwx.   1 root root   7 Nov  3  2020 lib -> usr/lib
lrwxrwxrwx.   1 root root   9 Nov  3  2020 lib64 -> usr/lib64
drwx------.   2 root root   6 Sep 15  2021 lost+found
drwxr-xr-x.   2 root root   6 Nov  3  2020 media
drwxr-xr-x.   2 root root   6 Nov  3  2020 mnt
drwxr-xr-x.   2 root root   6 Nov  3  2020 opt
dr-xr-xr-x. 238 root root   0 Apr 28 08:11 proc
dr-xr-x---.   2 root root 162 Sep 15  2021 root
drwxr-xr-x.  11 root root 163 Sep 15  2021 run
lrwxrwxrwx.   1 root root   8 Nov  3  2020 sbin -> usr/sbin
drwxr-xr-x.   2 root root   6 Nov  3  2020 srv
dr-xr-xr-x.  13 root root   0 Apr 16 16:48 sys
drwxrwxrwt.   7 root root 171 Sep 15  2021 tmp
drwxr-xr-x.  12 root root 144 Sep 15  2021 usr
drwxr-xr-x.  20 root root 262 Sep 15  2021 var

Dockerfile中很多命令都十分相似,要主要它们的区别

实战:Tomcat镜像

1,准备镜像文件 tomcat 压缩包,jdk的压缩包

image-20230428161648791

2,编写dockerfile文件,官方命名:Dockerfile,build会自动寻找这个文件,就不需要-f指定了

#vim Dockerfile 

FROM centos
MAINTAINER xiao<[email protected]>

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

ADD jdk-8u91-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-8.5.16.tar.gz /usr/local/

RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
RUN sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
RUN yum makecache
RUN yum -y install vim

ENV MYPATH /usr/local
WORKDIR $MYPATH

ENV JAVA_HOME /usr/local/jdk1.8.0_91
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.16
ENV CATALINA_BASH /usr/local/apache-tomcat-8.5.16
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin

EXPOSE 8080

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

3,构建镜像

#docker build -t diytomcat .

4,启动镜像,并挂载tomcat的站点目录和日志

docker images 

docker run -d -p 9090:8080 --name xiaotomcat -v /home/tomcat/test:/usr/local/apache-tomcat-8.5.16/webapps/test -v /home/tomcat/logs/:/usr/local/apache-tomcat-8.5.16/logs diytomcat

5,访问测试

image-20230428200802501

6,发布项目(由于做了卷挂载,我们直接在本地编写项目就可以发布了)

#切换到和tomcat站点目录互相挂载的目录
cd /home/tomcat/test/
#编写页面
cat index.jsp 

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<h2>Hello Xiao!</h2>
 
</body>
</html>

#访问http://192.168.10.4:9090/test/进行测试

image-20230428201837648

发布自己的镜像

DockerHub

1,地址https://hub.docker.com/ 注册自己的账户

2,在服务器上提交自己的镜像

[root@server3 test]# docker login --help

Usage:  docker login [OPTIONS] [SERVER]

Log in to a 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

[root@server3 test]# docker login -u xiao1226

3,登录完毕之后,就可以提交镜像了,就是一步 docker push

# push自己的镜像到服务器上

发布到阿里云镜像服务上

1,登录阿里云

2,找到容器镜像服务

3,创建命名空间

image-20230428210615714

4,创建容器镜像

image-20230428210731643

5,浏览这个阿里云

image-20230428210808409

6,发布镜像

#登录阿里云
docker login --username=xiaoxiao9189 registry.cn-hangzhou.aliyuncs.com
(密码是登录阿里云的时候设置的)
#更改一下镜像标签
docker images
docker tag diytomcat registry.cn-hangzhou.aliyuncs.com/xiao1226/xiao:1.0
(必须这样更改标签,如果不这样更改,会找不到仓库)
#推送镜像
docker images
docker push registry.cn-hangzhou.aliyuncs.com/xiao1226/xiao:1.0
#查看阿里云上是否有没有

image-20230428230535275

阿里云容器镜像就参考官方地址

小结:

image-20230428223559092

Docker网络

理解Docker0

清空所有环境

测试

image-20230429200946493

三个网络

#问题,docker 是如何处理容器网络访问的?

image-20230429201157946

#使用我们上传阿里云上面的镜像
docker pull registry.cn-hangzhou.aliyuncs.com/xiao1226/xiao:1.0
docker ps
docker run -d -P --name centos1.0 b8cab41e9c97

#查看容器的内部网路地址 ip addr
[root@server3 ~]# docker exec -it centos1.0 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
56: eth0@if57: <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同容器内部
[root@server3 ~]# 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.290 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.044 ms

#Linux系统可以ping通docker容器内部

原理

1,我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡docker0

桥接模式,使用的技术是evth-pair技术

再次测试本机的ip addr

image-20230430204307574

2,在启动一个容器测试,发现又多了一对网卡

docker run -d -P --name centos2.0 b8cab41e9c97

image-20230430204439160

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

3,我们来测试centos1.0和centos2.0是否可以ping通

[root@server3 ~]# 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.040 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.074 ms

#结论容器和容器之间是可以互相ping通的

绘制网络模型图

image-20230430210030607

结论:centos1.0和centos2.0是公用的一个路由器,docker0

所有的容器不指定网络的情况下,都是docker0路由的,docker会给我们的容器分配一个默认的可用IP

小结

Docker使用的Liunx的桥接,宿主机中是一个Docker容器的网桥,docker0

image-20230430210702980

Docker中的所有的网络接口的虚拟的,虚拟的转发效率高(内网传递文件)

只要容器删除,对应网桥就都没了

#docker网络的命令
docker network --help

image-20230501200915964

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

[root@server3 ~]# docker exec -it centos2.0 ping centos1.0
ping: centos1.0: Name or service not known
(不能ping通)

#如何解决呢
[root@server3 ~]# docker run -d -P --name centos3.0 --link centos2.0 b8cab41e9c97(id号是镜像id号)
bcf7e52995834b13a85220243d3eb742e277800a47122e53b6bcc73e97e6b027
[root@server3 ~]# docker exec -it centos3.0 ping centos2.0
PING centos2.0 (172.17.0.3) 56(84) bytes of data.
64 bytes from centos2.0 (172.17.0.3): icmp_seq=1 ttl=64 time=0.063 ms
64 bytes from centos2.0 (172.17.0.3): icmp_seq=2 ttl=64 time=0.041 ms
#通过--link就可以解决了网络连通问题

#反向可以ping通吗?
[root@server3 ~]# docker exec -it centos2.0 ping centos3.0
ping: centos3.0: Name or service not known

探究:docker network inspect e126f6c33a48

image-20230501201127548

其实这个centos3.0就是在本地配置了centos2.0的配置?

#查看centos3.0中的hosts的配置,在这里原理发现
[root@server3 ~]# docker exec -it centos3.0 cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.3	centos2.0 5575915b7b37
172.17.0.4	bcf7e5299583

本质:--link就是我们在容器中的hosts配置文件增加了172.17.0.3 centos2.0 5575915b7b37

现在在Dokcer中已经不建议使用--link了!

所以我们用自定义网络,docker0并不好用

docker0问题:他不支持容器名连接访问!

自定义网络

查看所有的docker网络

image-20230501203239630

网络模式

bridge:桥接模式,docker(默认,自己创建的也是用bridge模式)

none:不配置网络

hosts:和宿主机共享网络

container:容器内网络联通!(用的少,局限很大)

测试

# --net bridge,这个启动的时候,默认会带上,而这个就是我们的docker0
docker run -d -P --name centos1  b8cab41e9c97
docker run -d -P --name centos1 --net bridge b8cab41e9c97

#docker0特点:默认自带,域名不能访问,但是--link可以打通连接

#我们可以自定义网络
#--driver bridge
#--subnet 192.168.10.0/16
#--gateway 192.168.10.1
[root@server3 ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
359ad7602daceae5fd6f69ca7e0d140d9b9ce6a015be4016eaf7c78569685fe4
[root@server3 ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
e126f6c33a48   bridge    bridge    local
d8a17cffa6eb   host      host      local
359ad7602dac   mynet     bridge    local
b2b72f5ee6b9   none      null      local

我们自己创建的网络就好了,使用下面命令查看我们创建的网络信息

docker network inspect mynet

[root@server3 ~]# docker run -d -P --name centos-net-01 --net mynet b8cab41e9c97
[root@server3 ~]# docker run -d -P --name centos-net-02 --net mynet b8cab41e9c97
[root@server3 ~]# docker network inspect mynet
[
    {
        "Name": "mynet",
        "Id": "359ad7602daceae5fd6f69ca7e0d140d9b9ce6a015be4016eaf7c78569685fe4",
        "Created": "2023-05-01T20:40:25.286230932+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.10.0/16",
                    "Gateway": "192.168.10.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "36462888e4bdbefd3fd76e12a0bd65c6ac8a18a1614182977e1414a91af3965d": {
                "Name": "centos-net-02",
                "EndpointID": "4f667f493ed6959aaf2d13a6d8b67c4c36cb6416c598c48f74aff4e96d9c5574",
                "MacAddress": "02:42:c0:a8:00:02",
                "IPv4Address": "192.168.0.2/16",
                "IPv6Address": ""
            },
            "ff1da24783c31a736ef0079daba90df10e7a0b2a59617e233576d331a3676c47": {
                "Name": "centos-net-01",
                "EndpointID": "3d9a62e3156c08ef335da250ccf948e02ec494857190d9222447d6be32c5cd82",
                "MacAddress": "02:42:c0:a8:00:01",
                "IPv4Address": "192.168.0.1/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]


#再次测试ping连接
[root@server3 ~]# docker exec -it centos-net-01 ping 192.168.0.2
PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data.
64 bytes from 192.168.0.2: icmp_seq=1 ttl=64 time=0.146 ms

#现在不适用--link也可以ping名字了
[root@server3 ~]# docker exec -it centos-net-01 ping centos-net-02
PING centos-net-02 (192.168.0.2) 56(84) bytes of data.
64 bytes from centos-net-02.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.031 ms
64 bytes from centos-net-02.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.043 ms

我们自定义的网络docker都已经帮我们维护好了对应关系,我们平时就这样使用网络!

好处:

redis:不同的集群使用不同的网络,保证集群是安全和健康的

网络联通

image-20230502130308011

image-20230502130354860

#测试打通,使centos01打通 centos-net-01
docker run -d -P --name centos01 b8cab41e9c97
docker run -d -P --name centos02 b8cab41e9c97
[root@server3 ~]# docker ps
CONTAINER ID   IMAGE          COMMAND                   CREATED         STATUS         PORTS                                         NAMES
bae80cd1e214   b8cab41e9c97   "/bin/sh -c '/usr/lo…"   2 minutes ago   Up 2 minutes   0.0.0.0:32769->8080/tcp, :::32769->8080/tcp   centos02
ba9b4651dede   b8cab41e9c97   "/bin/sh -c '/usr/lo…"   2 minutes ago   Up 2 minutes   0.0.0.0:32768->8080/tcp, :::32768->8080/tcp   centos01
36462888e4bd   b8cab41e9c97   "/bin/sh -c '/usr/lo…"   15 hours ago    Up 3 seconds   0.0.0.0:32771->8080/tcp, :::32771->8080/tcp   centos-net-02
ff1da24783c3   b8cab41e9c97   "/bin/sh -c '/usr/lo…"   15 hours ago    Up 5 seconds   0.0.0.0:32770->8080/tcp, :::32770->8080/tcp   centos-net-01

[root@server3 ~]# docker network connect mynet centos01
[root@server3 ~]# docker network inspect mynet
#发现连通之后就是将 centos01 放到了 mynet网络下

image-20230502130701598

[root@server3 ~]# docker exec -it centos01 ping centos-net-01
PING centos-net-01 (192.168.0.1) 56(84) bytes of data.
64 bytes from centos-net-01.mynet (192.168.0.1): icmp_seq=1 ttl=64 time=0.092 ms
64 bytes from centos-net-01.mynet (192.168.0.1): icmp_seq=2 ttl=64 time=0.050 ms

#发现centos02依旧是打不通的
[root@server3 ~]# docker exec -it centos02 ping centos-net-01
ping: centos-net-01: Name or service not known

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

实战:redis集群部署

image-20230502131313297

一共需要6个容器,先清空之前的容器

1,#我们先创建一个redis的网卡
docker network create redis --subnet 172.38.0.0/16
docker network ls
2,通过脚本创建六个redis配置
[root@server3 ~]# vim 1.sh 
#!/bin/bash
for port in {1..6}
do
mkdir -p /mydata/redis/redis-$port/conf
touch /mydata/redis/redis-$port/conf/redis.conf
cat << EOF >/mydata/redis/redis-$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

2,#启动容器
[root@server3 ~]# docker run -p 6371:6379 -p 16371:16379 --name redis1 \
 -v /mydata/redis/redis-1/data:/data \
 -v /mydata/redis/redis-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

[root@server3 ~]# docker run -p 6372:6379 -p 16372:16379 --name redis2 \
 -v /mydata/redis/redis-2/data:/data \
 -v /mydata/redis/redis-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

[root@server3 ~]# docker run -p 6373:6379 -p 16373:16379 --name redis3 \
 -v /mydata/redis/redis-3/data:/data \
 -v /mydata/redis/redis-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
 
[root@server3 ~]# docker run -p 6374:6379 -p 16374:16379 --name redis4 \
 -v /mydata/redis/redis-4/data:/data \
 -v /mydata/redis/redis-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
 
[root@server3 ~]# docker run -p 6375:6379 -p 16375:16379 --name redis5 \
 -v /mydata/redis/redis-5/data:/data \
 -v /mydata/redis/redis-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
 
[root@server3 ~]# docker run -p 6376:6379 -p 16376:16379 --name redis6 \
 -v /mydata/redis/redis-6/data:/data \
 -v /mydata/redis/redis-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
 
3,#创建集群
[root@server3 ~]# docker exec -it redis1 /bin/sh(redis服务器里面没有/bin/bash)

/data # 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 --clust
er-replicas 1

4,#可以进入集群,查看
/data # redis-cli -c
127.0.0.1:6379> cluster info
127.0.0.1:6379> set k1 b1
-> Redirected to slot [12706] located at 172.38.0.13:6379

5,#我们停止一个上面创建值的redis3容器,看看是否高可用
[root@server3 ~]# docker ps
[root@server3 ~]# docker stop redis3
172.38.0.11:6379> get k1
-> Redirected to slot [12706] located at 172.38.0.14:6379
"b1"
(发现k1依旧能获取,那就是redis4替代了redis3)

docker中的redis集群搭建完成

image-20230502213035249

微服务打包Docker镜像

Docker微服务实战

通过IDEA新建一个普通的微服务模块

image-20230506203445510

image-20230506203508699

image-20230506203558353

在自己创建的微服务中修改

image-20230506203752426

运行测试

image-20230506205947974

本机访问测试

image-20230506210148638

打包微服务

image-20230506210301017

将打包文件拖入桌面,尝试在windows中运行

image-20230506210400984

image-20230506210446463

在IDEA中下载docker插件,并直接在IDEA中创建DockerFile文件

image-20230506211543979

别运行,然后将软件包和Dockerfile文件拷入linux中

[root@server3 idea]# pwd
/home/idea
[root@server3 idea]# ls
demo-0.0.1-SNAPSHOT.jar  Dockerfile

#生成镜像
[root@server3 idea]# docker build -f Dockerfile -t xiao666 .

#运行容器
[root@server3 idea]# docker images
[root@server3 idea]# docker run -d -p 8080:8080 --name xiao-spingboot xiao666

#运行测试
[root@server3 idea]# curl localhost:8080/hello
hello xiao

Docker Swarm

介绍

官网介绍:Swarm mode overview | Docker Documentation

Docker Swarm 和 Docker Compose 一样,都是 Docker 官方容器编排项目,但不同的是,Docker Compose 是一个在单个服务器或主机上创建多个容器的工具,而 Docker Swarm 则可以在多个服务器或主机上创建容器集群服务,对于微服务的部署,显然 Docker Swarm 会更加适合。

从 Docker 1.12.0 版本开始,Docker Swarm 已经包含在 Docker 引擎中(docker swarm),并且已经内置了服务发现工具,我们就不需要像之前一样,再配置 Etcd 或者 Consul 来进行服务发现配置了。

docker swarm和k8s本质都是容器编排和管理,两者的对比如下:

    swarm:内嵌在容器引擎内部,是容器引擎的一部分,与容器深度绑定,swarm偏重的是容器的部署,侧重于容器技术的扩展。

    k8s:独立于docker,与docker是分离的,并完全不依赖于底层的docker,它侧重于业务应用的集群部署。k8s对容器的所有操作都渗透着为应用而服务的理念。以服务为中心,docker仅仅是其底层技术支撑的一种技术。

工作模式

image-20230510192502891

Swarm搭建

准备四台服务器

image-20230510192814803

image-20230510192839583

image-20230510193211710

#在四台服务器配置镜像加速器
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://atojdqeh.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

#建立swarm管理节点
[root@server1 ~]# docker swarm init --advertise-addr 192.168.10.2


#让三台服务器成为worker节点加入进来
[root@server2 ~]#  docker swarm join --token SWMTKN-1-4ylg4gubjxqkdsvwgcltrb6ztklwst5azf6s1lhmk0yel8knls-24kpc291bfbnhqdxw1bywtf0j 192.168.10.2:2377

[root@server3 ~]# docker swarm join --token SWMTKN-1-12qmp65w9hyxbikfgi7ycqh8ic3wcdm6jukl6zc45jta3mkk04-9cnnbqw0f6dc38zks7eoyfavz 192.168.10.2:2377

[root@server4 ~]# docker swarm join --token SWMTKN-1-12qmp65w9hyxbikfgi7ycqh8ic3wcdm6jukl6zc45jta3mkk04-9cnnbqw0f6dc38zks7eoyfavz 192.168.10.2:2377

#如果想成为manager节点来加入,就按下面命令
[root@server1 ~]# docker swarm join-token manager

[root@server4 ~]# docker swarm join --token SWMTKN-1-4ylg4gubjxqkdsvwgcltrb6ztklwst5azf6s1lhmk0yel8knls-0b42uydkumfqxcfsfw40egz7q 192.168.10.2:2377

#在主manager节点上查看集群信息
[root@server1 ~]# docker node ls

swarm集群管理

(1),重新生成集群token

如果有新的节点需要加入,加入的token忘记了,就需要重新在管理节点生成一个token,如下:

#只能在manager节点生成token
#1、生成manager token
docker swarm join-token manager
 
#2、生成worker token
docker swarm join-token worker

(2)节点权限升级

比如将server4节点由Worker节点降级为Reachable管理节点

在Leader管理节点server1执行如下命令:

[root@server1 ~]# docker node promote server4
[root@server1 ~]# docker node ls

image-20230515092655999

(3)节点权限降级

比如将server4节点由Reachable管理节点降级为worker节点

在Leader管理节点server1执行如下:

[root@server1 ~]# docker node demote server4
[root@server1 ~]# docker node ls

image-20230515092815132

(4)删除一个集群节点

a、删除集群节点(worker节点),需要被删节点先主动离开集群,然后再由manager节点删除

b、如果删除的是manager节点,则需要先降级为worker节点,再主动离开集群,最后由manager节点删除

  • 删除一个普通worker节点操作如下,以删除server2为例
#在server2被删节点执行如下:
[root@server2 ~]# docker swarm leave -f       #-f参数表示强制离开集群
 
 
#在node1管理节点执行如下:
docker node  ls               #观察server2节点状态STATUS是否变为Down
docker node rm server2          #删除server2节点
  • 删除一个Reachable管理节点,以server4为例
#在server1管理节点操作以下命令:
[root@server1 ~]# docker node demote server4     #先将server4降级为worker

#在server4呗删节点操作:
[root@server4 ~]# docker swarm leave             #离开集群

#在server1管理节点操作如下
[root@server1 ~]# docker node rm server4


(5),其他常用命令

(主要为docker node命令和docker swarm命令,详情可使用docker node --help和docker swarm --help查看所有参数)

#查看集群节点状态,只能在manager节点使用
docker node ls
 
#查看运行节点的任务列表
docker node ps [NODENAME]
 
#查看节点详细信息
docker node inspect [NODENAME]
 
#更新节点
docker node update [NODENAME]

集群高可用演示

高可用介绍

在Docker Swarm中,Swarm manager负责管理整个集群,包括成规模的众多Docker主机资源。如果这个Swarm manager挂了,你必须创建一个新的来解决中断的服务。

    Docker Swarm具有High Availability的特性,当有一个manager实例出现问题,Docker Swarm可以优雅的进行故障转移-failover。你可以创建一个单独的primary manager实例和多个replica实例来使用这个特性。

    一个primary manager是Docker Swarm集群的主要联系人。你也可以创建replica实例作为次要联系人,并与它进行通信。对于replica收到的请求会被自动的代理到primary manager。如果一个primary manager故障,一个replica会成为leader。通过这种机制,你可以始终保持于集群的联系。

高可用切换演示

以如下docker集群状态为例,server1为主管理节点,server2和server4为普通管理节点,server3为工作节点

image-20230515094310385

当server1 Leader节点执行systemctl stop docker,模拟将docker服务挂掉之后,等过一会之后,docker服务会被自动重启,并且集群将重新连接,只是主管理节点(Leader)会转移,如下:

image-20230515094545549

【注意】:如果集群没有设置普通管理节点(Reachable),那么当主管理节点(Leader)挂掉再恢复之后,主管理节点(Leader)不会改变,因为没有普通管理节点(Reachable)参与选举。

通过docker service管理服务

命令详解

image-20230515094711996

(1),创建/启动服务

#创建nginx服务
docker service create nginx
 
#创建nginx服务,并映射80端口
docker service create -p 80:80 nginx
 
#创建nginx容器,并设置5个运行副本
docker service create --replicas 5 nginx

(2)、查看正在运行的服务

[root@server1 ~]# docker service ls

(3)、查看某个服务运行状态

[root@server1 ~]# docker service ps great_euler 

docker service ps [服务名字]

(4)、增加和删除DNS

docker service update --dns-add 222.222.222.222 mynginx
docker service update --dns-rm 222.222.222.222 mynginx

docker service update --dns-参数 222.222.222.222 [服务名字]

(5)、增加和删除端口映射

[root@server1 ~]# docker service update --publish-add 90:90 great_euler
[root@server1 ~]# docker service update --publish-rm 90:90 great_euler

docker service update --publish-参数 端口:端口 [服务名字]

(6)、缩容和扩容

[root@server1 ~]# docker service scale great_euler=2
[root@server1 ~]# docker service scale great_euler=5

docker service scale 服务名字=参数

(7)、显示服务详细信息

[root@server1 ~]# docker service inspect great_euler

[root@server1 ~]# docker service inspect [服务名字]

(8)、获取服务日志

[root@server1 ~]# docker service logs great_euler

[root@server1 ~]# docker service logs [服务名字]

(9)、删除一个或多个服务

[root@server1 ~]# docker service rm great_euler

[root@server1 ~]# docker service rm [服务名字]

(10)、回滚服务

docker service rollback mynginx

docker service rollback [服务名字]

(11)、更新服务

docker service update mynginx

docker service update [服务名字]

使用docker service管理服务演示

(1)创建服务

以在swarm集群创建nginx服务为例:

集群节点状态如下:

image-20230515102038049

创建mynginx服务:
[root@server1 ~]# docker service create --name mynginx -p 80:80 nginx

查看docker service:
[root@server1 ~]# docker service ls
ID             NAME      MODE         REPLICAS   IMAGE          PORTS
t6t85avim7t3   mynginx   replicated   1/1        nginx:latest   *:80->80/tcp
(发现目前REPLICAS为1表示目前只有一个副本在运行)

查看docker service中mynginx的状态和信息:
[root@server1 ~]# docker service ps  mynginx
         
image-20230515102339718

如上图, 可以看到mynginx服务只有一个副本在运行,并且是运行在server3节点上,可以在server3节点执行docker ps -a查看到在运行的mynginx容器:

image-20230515102434392

因为现在mynginx已经在swarm集群运行,并且映射了端口,此时通过node1~4任何一个节点的主机ip都可以访问到nginx服务:

(2),扩容或缩容服务

(当web访问量骤增和骤减,这时候就需要动态的对mynginx服务进行扩容和缩容)

#有以下两种方式,2选1即可
#方式1
docker service update --replicas 5 mynginx   #将运行副本数设置为5
 
 
#方式2
docker srevice scale mynginx=5               #将运行副本数设置为5

查看扩容/缩容后的服务状态:
[root@server1 ~]# docker service ls
ID             NAME      MODE         REPLICAS   IMAGE          PORTS
t6t85avim7t3   mynginx   replicated   5/5        nginx:latest   *:80->80/tcp

[root@server1 ~]# docker service ps mynginx

image-20230515102904377

如上图可以看到,docker service会将所有副本均衡的分布到所有节点上。

Swarm集群数据管理

volume方式管理数据

volume模式:在宿主机上创建一个volume,默认目录为(/var/lib/docker/volume/your_custom_volume/_data),然后把容器的某个目录映射到宿主机的volume上,即使容器挂了,数据还会依然保留在宿主机的volume上。

[root@server1 ~]# docker service create --replicas 1 --mount type=volume,src=nginx,dst=/usr/share/nginx/html --name nginx nginx

#查看服务
[root@server1 ~]# docker service inspect nginx

#查看数据卷
[root@server1 ~]# docker volume inspect nginx

image-20230515104844365

image-20230515104908861

可以看到容器里面的nginx数据目录已经挂在到宿主机的默认目录了

bind mount方式管理数据

bind mount模式:将宿主机某个目录映射到docker容器,很适合于网站,同时把宿主机的这个目录作为git版本目录,每次update代码的时候,容器就会更新。

#创建数据目录
在mananger、worker上创建web网站目录:
[root@server1 ~]# mkdir -p /data/nginx
[root@server3 ~]# mkdir -p /data/nginx

#创建服务
[root@server1 ~]# docker service create --replicas 1 \
--mount type=bind,src=/data/nginx,dst=/usr/share/nginx/html \
--name mynginx \
nginx

#查看服务
[root@server1 ~]# docker service ps mynginx
ID             NAME        IMAGE          NODE      DESIRED STATE   CURRENT STATE            ERROR     PORTS
tqrq2rmz3hhx   mynginx.1   nginx:latest   server1   Running         Running 26 seconds ago             
(发现运行在server1中)

测试宿主机目录和容器目录是映射关系
[root@server1 ~]# cd /data/nginx/
[root@server1 nginx]# echo 'hello' > index.html

[root@server1 nginx]# docker exec -it bacdb6680c36 /bin/bash
root@bacdb6680c36:/# cat /usr/share/nginx/html/index.html 
hello

可以看到我们在宿主机上创建的index.html已经挂在到容器上了!

NFS方式管理数据

前面两种方式都是单机docker上数据共享方式,要是在集群中,这个就不适用了,我们必须使用共享存储或网络存储了。这里我们使用NFS来测试。

image-20230515111314572

我们使用第三台(server3作为NFS服务提供者)

yum install nfs-utils -y

并且在nfs目录放入网站数据内容:

[root@server3 ~]# mkdir -p /nfs/data
[root@server3 ~]# echo "hello nfs" > /nfs/data/index.html
[root@server3 ~]# chmod 777 /nfs/data/
[root@server3 ~]# cat /etc/exports
/nfs/data *(rw)
[root@server3 ~]# systemctl restart nfs
#安装nfs客户端
[root@server1 nginx]# yum install nfs-utils -y

#先手动创建docker volume
root@server1 nginx]# docker volume create --driver local \
--opt type=nfs \
--opt o=addr=192.168.10.4,rw \
--opt device=:/nfs/data \
foo3

#查看一下volume
[root@server1 nginx]# docker volume ls
DRIVER    VOLUME NAME
local     foo3
local     nginx

#看到了docker volume列表中有foo33,查看volume详细
[root@server1 nginx]# docker volume inspect foo3

这里有个问题,如果不用docker compose创建服务的话,你必须在服务所在的节点上创建docker volume
我的服务要创建4个副本,服务可能会分布到4个主机上,那么我在三个主机上都创建docker volume create foo33使用上面的代码在其它3台主机上都执行一遍

#发布服务
[root@server1 nginx]# docker service create \
--name test-nginx-nfs \
--publish 84:80 \
--mount type=volume,source=foo3,destination=/app/share \
--replicas 4 \
nginx

#查看服务分布的节点
[root@server1 nginx]# docker service ps test-nginx-nfs
ID             NAME               IMAGE          NODE      DESIRED STATE   CURRENT STATE            ERROR     PORTS
67lujrhuj7ef   test-nginx-nfs.1   nginx:latest   server4   Running         Running 6 minutes ago              
knwg2o4h5tro   test-nginx-nfs.2   nginx:latest   server2   Running         Running 56 seconds ago             
ittn55i32cpn   test-nginx-nfs.3   nginx:latest   server3   Running         Running 56 seconds ago             
ywktwchn44fd   test-nginx-nfs.4   nginx:latest   server1   Running         Running 55 seconds ago             


#测试server1
我们在搭建nfs服务器上创建一个文件
[root@server3 ~]# cd /nfs/data/
[root@server3 data]# touch xiao

#我们先查看宿主机目录
[root@server1 nginx]# docker volume inspect foo3
[root@server1 nginx]# ll /var/lib/docker/volumes/foo3/_data/
总用量 4
-rw-r--r--. 1 root root 10 5月  15 11:15 index.html
-rw-r--r--. 1 root root  0 5月  15 11:35 xiao

#查看容器目录
[root@server1 nginx]# docker ps
[root@server1 nginx]# docker exec -it 68431db127bf /bin/bash
root@68431db127bf:/# cd app/share/
root@68431db127bf:/usr/share/nginx/html# ls
index.html  xiao



Docker-compose

介绍

compose、machine 和 swarm 是docker 原生提供的三大编排工具。简称docker三剑客。

Docker Compose能够在 Docker 节点上,以单引擎模式(Single-Engine Mode)进行多容器应用的部 署和管理。多数的现代应用通过多个更小的微服务互相协同来组成一个完整可用的应用。

部署和管理繁多的服务是困难的。而这正是 Docker Compose 要解决的问题。Docker Compose 并不 是通过脚本和各种冗长的 docker 命令来将应用组件组织起来,而是通过一个声明式的配置文件描述整 个应用,从而使用一条命令完成部署。应用部署成功后,还可以通过一系列简单的命令实现对其完整声 明周期的管理。甚至,配置文件还可以置于版本控制系统中进行存储和管理。

下载安装

#1,将docker-compose-Linux-x86_64软件包拖入进去

#2,将文件复制到/usr/local/bin下,并改名字
[root@server3 ~]# mv docker-compose-Linux-x86_64 /usr/local/bin/docker-compose

#3,给权限
chmod 777 /usr/local/bin/docker-compose 
#4,查看测试版本
[root@server3 ~]# docker-compose -version

标签:实战,容器,--,redis,讲解,镜像,Docker,root,docker
From: https://www.cnblogs.com/xiao1226/p/17402987.html

相关文章

  • Docker - docker入门
    Docker学习之路  弱小和无知不是生存的障碍,傲慢才是。      ——《三体》  Docker学习之路Docker概述Docker安装Docker命令镜像命令容器命令操作命令......Docker镜像容器数据卷DockerFileDocker 网络原理IDEA整合DockerDockerCompo......
  • docker 快速入门
               ......
  • 你真正了解什么是接口测试么?接口实战一“篇”入魂
    最近在工作中,看到一些新手测试同学,对接口测试存在很多疑问,甚至包括一些从事软件测试3,5年的同学,在聊到接口时,也是一知半解;今天借着这个机会,对接口测试做个实战教学,顺便总结一下经验,分享给大家。计划拆分成4个模块跟大家做一个分享,(接口测试、接口基础知识、接口自动化、接口进阶)感兴......
  • Docker容器使用和操作
    1、容器概念1.1、什么是容器容器(Container):在docker中指的是从镜像创建的应用程序运行实例。可以将容器看作将一个 应用程序及其依赖环境打包 而成的集装箱。容器的实质是进程,与直接在主机执行不同,容器进程在属于自己的独立的命名空间内运行。这种特性使得容器封装的应用程序比直......
  • 国产麒麟(Kylin-Server-10)系统无外网环境安装docker
    由于某些原因服务器环境不给开放外网,只能提前在有外网环境准备好相关资源后再部署。先在有外网环境制作yum安装包,再将压缩包拷贝到无外网环境通过ansible安装docker。制作ansible、docker离线安装包ansible离线安装包#查看依赖包yumdeplistansible#拉取ansible所有关联包......
  • docker 容器container 镜像image 删除常用备忘
    首先是注意:上面jeecgboot和datahub的容器和镜像都在一起,删除容器的和镜像要注意。要重新部署的话首先要先停掉在跑的容器。通过dockerps查看 红框部分是jeecgboot的前后端容器,其他的是datahub的容器。 2.Jeecgboot是通过jar包部署在cl-mdm容器中。3.部署的过程如下:......
  • HOMER docker版本配置优化
     概述HOMER是一款100%开源的针对SIP/VOIP/RTC的抓包工具和监控工具。HOMER是一款强大的、运营商级、可扩展的数据包和事件捕获系统,是基于HEP/EEP协议的VoIP/RTC监控应用程序,并可以使用即时搜索、处理和存储大量的信令、RTC事件、日志和统计信息。之前的文章中,我们介绍过HOME......
  • Docker - 安装portainer
    本质就是拉取镜像安装的过程,确保docker容器已经安装完成。1、查询当前有哪些Portainer镜像dockersearchportainer2、下载镜像dockerpulldocker.io/portainer/portainer3、安装Portainer镜像(1)创建一个数据卷portainer_datadockervolumecreateportainer_data(2)宿主......
  • docker在多网口使用下,某个网口无法使用端口
    https://blog.csdn.net/weixin_44911287/article/details/123638796开启IP转发功能编辑/etc/sysctl.conf文件:nano/etc/sysctl.conf添加该行内容或去除注释该行内容:net.ipv4.ip_forward=1退出并保存,运行改行命令。sysctl-preboot......
  • Docker 镜像原理(commit、容器数据卷)
    dokcer镜像原理联合文件系统(UnionFS)理解:假设:docker中包含的tomcat和mysql均需要使用linux内核,这里使用的linux内核是共用的。下载时候看到的一层层就是这个,Docker镜像实际是由一层一层的文件系统组成联合文件系统时Docker镜像的基础,镜像通过分层来进行继承特性:......