IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 视频 Docker 学习(高级篇) -> 正文阅读

[系统运维]视频 Docker 学习(高级篇)

1、容器数据卷

1.1、什么是容器数据卷?

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

数据?如果数据都在容器中,那么我们容器删除,数据就会丢失!需求:数据可以持久化

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

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

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

5D1kIU.png

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

1.2、使用数据卷

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

-v, --volume list				Bind mount a volume

docker run -it -v 主机目录:容器内目录 -p 主机端口:容器内端口
# /home/dockertest:主机home目录下的dockertest文件夹  映射:centos容器中/home
[root@hadoop1 home]# docker run -it -v /home/dockertest:/home centos /bin/bash
# 这时候主机的/home/dockertest文件夹就和容器的/home文件夹关联了,二者可以实现文件或者数据同步了

# 通过docker inspect 容器id 查看容器的具体信息
[root@hadoop1 home]# docker inspect 5cfdc4449186

5DJ0Xj.png

测试文件的同步

在这里插入图片描述

再来测试!

  • 停止容器
  • 宿主机修改文件
  • 启动容器并进入正在运行的该容器
  • 容器内的数据依旧是同步的

在这里插入图片描述

2、实战:安装MySQL

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

# 获取mysql镜像
[root@hadoop1 home]# docker pull mysql:5.7

# 运行容器,需要做数据挂载,安装启动mysql需要配置密码的,这个要注意
# 参考官网hub
docker run --name mysql5.7 -e MYSQL_ROOT_PASSWORD=120800 -d mysql:5.7

# 启动mysql
# -d 后台运行
# -p 端口映射
# -v 卷挂载
# -e 环境配置
# --name 容器名字
docker run -d -p 3308:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=120800 --name mysql5.7 mysql:5.7

# 启动成功后,我们在本地使用navicat来测试一下
# navicat连接到服务器的3308和容器内的3306映射

# 在容器中创建一个数据库,查看一下我们映射的路径是否ok!

测试连接:注意 3310端口要在虚拟机上开放该端口,否则外部无法连接。

5DszrV.png

当我们在本地用Navicat新建名称为dataease的数据库的时候,容器中也会创建。

5DydIg.png

假设我们将包含mysql的容器删除的时候

5DcSNF.png

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

3、具名挂载和匿名挂载

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

# 查看所有的volume(卷)的情况
[root@hadoop1 ~]# docker volume ls
DRIVER    VOLUME NAME
local     0e23f9760414474c3c53e280fcd7fdf4df8aef6b486fb4f1bc24ba5c0bef41a4
local     9f688d80dee3fe47d730b9243c86882bd2e8fac7cef5b4ab98b3165a2e28f4aa
local     289c0d23a733e8ca4816e5eb346c762c6a0242822f4929f42dc92e7b6de86cce

# 这里发现 这种就是匿名挂载,我们再 -v只写了容器内的路径,没有容器外的路径
# 具名挂载 -P:表示随机映射的端口
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx

# 查看所有卷的情况
[root@hadoop1 ~]# docker volume ls
DRIVER    VOLUME NAME
local     0e23f9760414474c3c53e280fcd7fdf4df8aef6b486fb4f1bc24ba5c0bef41a4
local     9f688d80dee3fe47d730b9243c86882bd2e8fac7cef5b4ab98b3165a2e28f4aa
local     289c0d23a733e8ca4816e5eb346c762c6a0242822f4929f42dc92e7b6de86cce
local     a2aba49caddacce846feae4997c0ae8fa2e83195fb6cbb797f52b46d992e9d41
local     f04ccb7d21cb8f87d89686f0ea2de55f50d7fddfac61c06ccc38f78c61d574dc
local     juming-nginx  # 多了一个具名挂载的名字

# 通过 -v 卷名:容器内的路径
# 查看一下这个卷
[root@hadoop1 ~]# docker volume inspect juming-nginx
[
    {
        "CreatedAt": "2021-10-21T15:12:33+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data", # 默认目录
        "Name": "juming-nginx",
        "Options": null,
        "Scope": "local"
    }
]

docker run -d -P --name nginx03 -v /home/nginx03:/etc/nginx/conf.d nginx

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

5s1SsA.png

区分三种挂载方式

# 三种挂载方式: 匿名挂载、具名挂载、指定路径挂载
-v 容器路径		# 匿名挂载
-v 卷名:容器内路径		# 具名挂载
-v /宿主机路径:容器内路径 	# 指定路径挂载 docker volume ls

拓展:

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

docker run -d -P --name nginx04 -v juming:/etc/nginx:ro nginx
docker run -d -P --name nginx05 -v juming:/etc/nginx:rw nginx

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

4、初识 DockerFile

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

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

# 创建一个dockfile文件,名字看起来随便 建议Dockefile
# 文件中的内容:指令(大写) + 参数

$ vim dockerfile1

	FROM centos			# 当前这个镜像是以centos为基础的
	
	VOLUME ["volume01","volume02"]		# 挂载卷的卷目录(多个列表)卷在容器内
	
	CMD echo "------end---------"  # 创建镜像成功输出这句话用以代表创建成功
	CMD /bin/bash				   # 默认走bash控制台	
	
	# 这里的每个命令,就是镜像的一层

# 构建出这个镜像
-f dockerfile1 			# f代表file,指这个当前文件的地址(这里是当前目录下的dockerfile1)
-t itgsh_code/centos    # t代表target,指的是创建后的镜像名
. 						# 代表生成在当前目录下
[root@hadoop1 docker-test-volume]# docker build -f dockerfile1 -t itgsh_code/centos .
Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM centos
 ---> 5d0da3dc9764
Step 2/4 : VOLUME ["volume01","volume02"] # 卷名列表
 ---> Running in 68a469e7a359
Removing intermediate container 68a469e7a359
 ---> d1da6d81f032
Step 3/4 : CMD echo "-------end-------" # 输出脚本命令 
 ---> Running in 74c5341bf681
Removing intermediate container 74c5341bf681
 ---> 421c9fc6f1ec
Step 4/4 : CMD /bin/bash
 ---> Running in 1a0e23ee4eef
Removing intermediate container 1a0e23ee4eef
 ---> 09f96d12a8b4
Successfully built 09f96d12a8b4
Successfully tagged itgsh_code/centos:latest
	
# 查看自己构建的镜像
Successfully tagged itgsh_code/centos:latest
[root@hadoop1 docker-test-volume]# docker images
REPOSITORY            TAG       IMAGE ID       CREATED         SIZE
itgsh_code/centos     latest    09f96d12a8b4   4 minutes ago   231MB

5sBhKP.png

这个卷和外部一定有一个同步的目录

5sy9IS.png

查看一下卷挂载

# docker inspect 容器id
$ docker inspect ca3b45913df5

5sylRJ.png

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

5syhWQ.png

5sybwV.png

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

假设构建镜像的时候没有挂载卷,要手动镜像挂载-v 卷名:容器内路径!(使用的是具名挂载)

5、数据卷容器

多个MySQL同步数据(即容器内部同步数据)

命名的容器挂载数据卷!

5s6QTf.png

#  测试 启动三个容器,通过刚才自己写的镜像启动
# 创建docker01:因为我本机是最新版,故这里用latest
$ docker run -it --name docker01 itgsh_code/centos:latest

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

# 不关闭容器退出
ctrl + P + Q

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

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9u0stPWq-1635248999192)(https://z3.ax1x.com/2021/10/21/5s54E9.png)]

5s5I41.png

# 再新建一个docker03同样继承docker01
$ docker run -it --name docker03 --volumes-from docker01 itgsh_code/centos:latest
$ cd volume01
$ ls
docker01.txt

# 测试:可以删除容器docker01,查看一下docker02和docker03是否可以访问这个文件
# 测试发现:数据依旧保留在docker02和docker03中没有被删除

5sIPv8.png

多个mysql实现数据共享

$ docker run -d -p 3308:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL-ROOT-PASSWORD=120800 --name mysql01 mysql:5.7

$ docker run -d -p 3308:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql --name mysql02 --volumes-from mysql01 mysql:5.7

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

结论

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

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

6、DockerFile

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

构建步骤:

  • 编写一个 dockerfile 文件
  • docker build 构建成为一个镜像
  • docker run 运行该镜像
  • docker push 发布镜像 (DockerHub、阿里云仓库)

5sx0Mj.png

点击后跳到一个 Dockerfile

5sxyd0.png

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

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

DockerFile 构建过程

基础知识

  • 每个保留关键字(指令)都是必须是大写字母
  • 执行顺序从下到上
  • # 表示注释
  • 每一个指令都会创建提交一个新地镜像层,并提交。

56V5rV.png

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

Docker 镜像逐渐成企业交付的标准,必须要掌握!

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

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

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

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:构建的时候设置环境变量

56eiwT.png

实战测试

scratch镜像(默认为基础镜像)

# 官方的centos默认构建镜像过程
FROM scratch
ADD centos-7-x86_64-docker.tar.xz /

LABEL \
    org.label-schema.schema-version="1.0" \
    org.label-schema.name="CentOS Base Image" \
    org.label-schema.vendor="CentOS" \
    org.label-schema.license="GPLv2" \
    org.label-schema.build-date="20200504" \
    org.opencontainers.image.title="CentOS Base Image" \
    org.opencontainers.image.vendor="CentOS" \
    org.opencontainers.image.licenses="GPL-2.0-only" \
    org.opencontainers.image.created="2020-05-04 00:00:00+01:00"

CMD ["/bin/bash"]

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

56ugcd.png

创建一个自己的centos镜像

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

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

# 3./编写Dockerfile配置文件
FROM centos									# 基础镜像是官方原生的centos
MAINTAINER itgsh_code<itgsh_code@163.com>	# 作者


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

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

EXPOSE 8088									# 暴漏端口号为8088

CMD echo $MYPATH							# 输出下MYPATH路径
CMD echo "------end----"					# 启动后进入/bin/bash
CMD /bin/bash								# 启动后进入/bin/bash目录
 
# 4.通过这个文件构建镜像
# 命令:docker build -f 文件路径 -t 镜像名:[tag]
$ docker build -f mydockerfile_centos -t mycentos:1.0

# 5.出现下图后则构建成功

56KIq1.png

$ docker images
REPOSITORY            TAG       IMAGE ID       CREATED         SIZE
mycentos              1.0       b488d159cf4e   4 minutes ago   336MB

# 6.测试运行
$ docker run -it mycentos:1.0 # 注意带上版本号,否则会去寻找最新版

$ pwd
/usr/local					  # 与Dockerfile文件中WORKDIR设置的MYPATH一致
$ vim						  # vim指令可以使用
$ ifconfig 					  # ifconfig指令可以使用

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

56MhY8.png

我们平时拿到一个镜像,可以用docker history 镜像id 研究一下是什么做的

CMD 和 ENTRYPOINT 的区别

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

测试cmd

# 编写dockerfile文件
$ vim dockerfile_cmd_test
FROM centos
CMD ["ls","-a"]								# 容器启动后执行ls -a命令

# 构建镜像
$ docker build -f dockerfile-tets-cmd -t cmd_test:1.0 .

# 运行镜像
[root@hadoop1 dockerfile]# docker run cmdtest:latest
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var

# 想追加一个命令 -l 成为ls -al :展示详细数据
$ docker run cmdtest:latest -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "-l": executable file not found in $PATH: unknown.

# cmd的情况下,-l 替换了CMD["ls","-a"]而 -l 不是命令所以报错

测试ENTRYPOINT

# 编写dockerfile文件
$ vim dockerfile-test-entrypoint
FROM centos
ENTRYPOINT ["ls","-a"]

# 构建镜像
$ docker build -f dockerfile-test-entrypoint -t entrytest:1.0 .

# 运行镜像
# 我们的命令,是直接拼接再我们得ENTRYPOINT命令后面的 
[root@hadoop1 dockerfile]# docker run entrytest:1.0 -l
total 0
drwxr-xr-x.   1 root root   6 Oct 22 06:04 .
drwxr-xr-x.   1 root root   6 Oct 22 06:04 ..
-rwxr-xr-x.   1 root root   0 Oct 22 06:04 .dockerenv
lrwxrwxrwx.   1 root root   7 Nov  3  2020 bin -> usr/bin
drwxr-xr-x.   5 root root 340 Oct 22 06:04 dev
drwxr-xr-x.   1 root root  66 Oct 22 06:04 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 14:17 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. 261 root root   0 Oct 22 06:04 proc
dr-xr-x---.   2 root root 162 Sep 15 14:17 root
drwxr-xr-x.  11 root root 163 Sep 15 14:17 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 Oct 20 12:03 sys
drwxrwxrwt.   7 root root 171 Sep 15 14:17 tmp
drwxr-xr-x.  12 root root 144 Sep 15 14:17 usr
drwxr-xr-x.  20 root root 262 Sep 15 14:17 var

DockerFile 中很多命令都十分相似,我们需要了解它们的区别,我们最好的学习方式就是对比他们然后测试效果。

7、实战:Tomcat 镜像

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

5643y8.png

2、编写dockerfile文件,官方命名,Dockerfilebuild会自动寻找这个文件,就不需要 -f 进行指定了

编写dockerfile文件

$ vim dockerfile 
FROM centos										# 基础镜像
MAINTAINER itgshcode<itgsh_code@163.com>		# 作者
COPY README /usr/local/README					# 复制README文件
ADD jdk-8u231-linux-x64.tar.gz /usr/local/ 		# 添加jdk,ADD 命令会自动解压
ADD apache-tomcat-9.0.35.tar.gz /usr/local/ 	# 添加tomcat,ADD 命令会自动解压
RUN yum -y install vim 							# 安装vim命令
ENV MYPATH /usr/local							# 环境变量设置 工作目录
WORKDIR $MYPATH 							

ENV JAVA_HOME /usr/local/jdk1.8.0_231 				# 环境变量: JAVA_HOME环境变量
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.35 	# 环境变量: tomcat环境变量
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.35

# 设置环境变量 分隔符是:
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin 	

EXPOSE 8088 										# 设置暴露的端口

CMD /usr/local/apache-tomcat-9.0.35/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.35/logs/catalina.out 					# 设置默认命令

3、构建镜像

# 因为dockerfile命名使用默认命名Dockerfile  因此不需要使用 -f 指定文件
$ docker build -t mytomcat:1.0

4、run镜像

# -d:后台运行 -p:暴漏端口 --name:别名 -v:绑定路径
$ docker run -d -p 8088:8080 --name tomcat01
-v /home/kuangshen/build/tomcat/test:/usr/local/apache-tomcat-9.0.35/webapps/test 
-v /home/kuangshen/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.35/logs mytomcat:1.0

5、访问测试

$ docker exec -it 自定义容器的id /bin/bash

$ curl localhost:8080

6、发布项目

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

发现:项目部署成功,可以直接访问!

我们以后的开发步骤:需要掌握DockerFile的编写!我们之后的一切都是使用docker镜像来发布运行!

发布自己的镜像

发布到Docker HUB

1、地址:https://hub.docker.com/

2、确定这个账号可以登录

3、登录

[root@iZ2ze0jazgwtuvi1lczdqfZ /]# 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
  
[root@iZ2ze0jazgwtuvi1lczdqfZ /]# docker login -u itgshcode20001208
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

4、提交 push 镜像

5IQ8bV.png

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

# 第二种:使用docker tag 然后再次push
$ docker tag 容器id kuangshen/mytomcat:1.0  # 然后再次 push
$ docker push kuangshen/mytomcat

提交的时候也是按照镜像的层级来进行提交的!

发布到阿里云镜像服务上

看官网,很详细 https://cr.console.aliyun.com/repository/

小结

5Ia8Nn.png

Docker 网络

理解Docker 0

学习之前清空下前面的docker镜像,容器

# 删除全部的容器
$ docker rm -f $(docker ps -qa)

# 删除全部的镜像文件
$ docker rmi -f $(docker images -qa)

5IdfzV.png

三个网络

问题:Docker 是如何处理容器网络访问的?

5I2QD1.png

# 测试 运行一个tomcat
$ docker run -p 8080:8080 --name tomcat01 tomcat

# 查看容器网络地址
$ docker exec -it 容器id/容器名 ip addr

# 报错了
OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: "ip": executable file not found in $PATH: unknown

# 这里 因为狂神老师是老版的 追加ip addr的时候是可以使用的,而在我的版本中是不能使用的
# 需要安装这个指令 但是tomcat容器中是没有yum指令的 所以需要先进入到容器中安装
$ docker exec -it tomcat01 /bin/bash
$ apt update && apt install -y iproute2
# 安装好以后ctrl +P +Q 不关闭退出容器
# 查看容器内部网络地址
$ docker exec -it 容器id/容器名 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
50: eth0@if51: <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 foreve
       
# 思考:lInux能不能ping通容器内部?可以 容器内部可以ping通外界嘛?
[root@iZ2ze0jazgwtuvi1lczdqfZ ~]# 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.044 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.040 ms

原理

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

再次测试 ip addr(会发现多了一个ip地址

5IWbu9.png

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

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

# 获取tomcat01的ip 172.17.0.2
$ docker-tomcat docker exec -it tomcat01 ip addr  
550: eth0@if551: <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
       
# 让tomcat02 ping tomcat01       
$ docker-tomcat 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.098 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.071 ms

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

5I4v40.png

结论:tomcat01 和 tomcat02 公用一个路由器,docker0。

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

小结

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

5ITHGq.png

Docker 中所有网络接口都是虚拟的,虚拟的转发效率高。

只要容器删除,对应的一对网桥就没了!

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

–link

$ docker exec -it tomcat02 ping tomcat01 # ping不通
ping: tomca01: Name or service not known

# 运行一个tomcat03 --link toncat02
$ docker run -d -P --name tomcta03 --link tomcat02 tomcat
5f9331566980a9e92bc54681caaac14e9fc993f14ad13d98534026c08c0a9aef

#  3连接2
# 用tomcat03 ping tomcat02 可以ping通
$ 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.115 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.080 ms

# 2连接3
# 用tomcat02 ping tomcat03 ping不通

探究

查询各个网络的 id

5IjFNF.png

docker network inspect 网络id 网段相同

5Ij89H.png

–link 本质就是在hosts配置中添加映射

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

自定义网络,不适用 docker0

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

自定义网络

docker network
connect     Connect a container to a network
create      Create a network
disconnect  Disconnect a container from a network
inspect     Display detailed information on one or more networks
ls          List networks
prune       Remove all unused networks
rm          Remove one or more neworks

查看所有的 Docker 网络

5o3r01.png

网络模式

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

测试

# 我们直接启动的命令 --net bridge,而这个就是我们得docker0
# bridge 就是docker0
$  docker run -d -P --name tomcat01 tomcat ==> 等价于
$  docker run -d -P --name tomcat01 --net bridge tomcat

# docker0 特点:默认,域名不能访问。 -- link可以打通连接,但是很麻烦!
# 我们可以 自定义一个网络
$ docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet

5oJW1U.png

$ docker network inspect mynet

5oN5ng.png

到这里,我们自己定义的网络就已经创建好了!

在我们定义的网络下,启动两个tomcat,再次查看网络情况:

5oaJRx.png

5oaaLD.png

5oaIFs.png

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

好处

  • redis - 不同的集群使用不同的网络,保证集群是安全和健康的。
  • mysql - 不同的集群使用不同的网络,保证集群是安全和健康的。

5odapq.png

网络连通

5o0JWn.png

# 测试两个不同的网络连通,再启动两个tomcat 使用默认网络,即docker0
$ docker run -d -P --name tomcat01 tomcat
$ docker run -d -P --name tomcat02 tomcat
# 此时ping不通
# 要将tomcat01连通tomcat-net-01,连通就是将tomcat01加入到mynet网络中
# 一个容器两个ip (tomcat01)

5oBb4J.png

# 01连通,加入到mynet网络后,此时,已经可以将tomcat01和tomcat-net-01 ping通了
# 02是依旧不通的

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

实战:部署 Redis 集群

5os6AO.png

# 创建网卡
docker network create redis --subnet 172.38.0.0/16

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

# 通过脚本运行六个redis
for port in $(seq 1 6);\
do
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 exec -it redis-1 /bin/sh #redis默认没有bash
done
[root@iZ2ze0jazgwtuvi1lczdqfZ ~]# for port in $(seq 1 6);\
> do
> 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 exec -it redis-1 /bin/sh #redis默认没有bash
> done
docker: Error response from daemon: Conflict. The container name "/redis-1" is already in use by container "760038aa1b947d96f4253816f7b392300e19e8006e10c42cabc5070ad7d2436f". You have to remove (or rename) that container to be able to reuse that name.
See 'docker run --help'.
/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 --cluster-r
eplicas 1
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 172.38.0.15:6379 to 172.38.0.11:6379
Adding replica 172.38.0.16:6379 to 172.38.0.12:6379
Adding replica 172.38.0.14:6379 to 172.38.0.13:6379
M: 139aec873bae9cc4be4671b684741d9aaf892528 172.38.0.11:6379
   slots:[0-5460] (5461 slots) master
M: ab6cdb5c61ec075f99e777586d6b919dfec7f7ab 172.38.0.12:6379
   slots:[5461-10922] (5462 slots) master
M: 5199308c04f4b1473f62dd309b59a0e2bdb5a8d4 172.38.0.13:6379
   slots:[10923-16383] (5461 slots) master
S: f255f93c2e044c787058c5f94531cc8e3ae3ce3b 172.38.0.14:6379
   replicates 5199308c04f4b1473f62dd309b59a0e2bdb5a8d4
S: f6dfeb8166235e41ac35d631ed09ec0ea757e890 172.38.0.15:6379
   replicates 139aec873bae9cc4be4671b684741d9aaf892528
S: a70d391ab4263340154558c97ccbf040bd448c2d 172.38.0.16:6379
   replicates ab6cdb5c61ec075f99e777586d6b919dfec7f7ab
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
....
>>> Performing Cluster Check (using node 172.38.0.11:6379)
M: 139aec873bae9cc4be4671b684741d9aaf892528 172.38.0.11:6379
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: f255f93c2e044c787058c5f94531cc8e3ae3ce3b 172.38.0.14:6379
   slots: (0 slots) slave
   replicates 5199308c04f4b1473f62dd309b59a0e2bdb5a8d4
M: ab6cdb5c61ec075f99e777586d6b919dfec7f7ab 172.38.0.12:6379
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
M: 5199308c04f4b1473f62dd309b59a0e2bdb5a8d4 172.38.0.13:6379
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: f6dfeb8166235e41ac35d631ed09ec0ea757e890 172.38.0.15:6379
   slots: (0 slots) slave
   replicates 139aec873bae9cc4be4671b684741d9aaf892528
S: a70d391ab4263340154558c97ccbf040bd448c2d 172.38.0.16:6379
   slots: (0 slots) slave
   replicates ab6cdb5c61ec075f99e777586d6b919dfec7f7ab
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
/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
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:221
cluster_stats_messages_pong_sent:246
cluster_stats_messages_sent:467
cluster_stats_messages_ping_received:241
cluster_stats_messages_pong_received:221
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:467
127.0.0.1:6379> cluster nodes
f255f93c2e044c787058c5f94531cc8e3ae3ce3b 172.38.0.14:6379@16379 slave 5199308c04f4b1473f62dd309b59a0e2bdb5a8d4 0 1635247636480 4 connected
139aec873bae9cc4be4671b684741d9aaf892528 172.38.0.11:6379@16379 myself,master - 0 1635247636000 1 connected 0-5460
ab6cdb5c61ec075f99e777586d6b919dfec7f7ab 172.38.0.12:6379@16379 master - 0 1635247637482 2 connected 5461-10922
5199308c04f4b1473f62dd309b59a0e2bdb5a8d4 172.38.0.13:6379@16379 master - 0 1635247636579 3 connected 10923-16383
f6dfeb8166235e41ac35d631ed09ec0ea757e890 172.38.0.15:6379@16379 slave 139aec873bae9cc4be4671b684741d9aaf892528 0 1635247636000 5 connected
a70d391ab4263340154558c97ccbf040bd448c2d 172.38.0.16:6379@16379 slave ab6cdb5c61ec075f99e777586d6b919dfec7f7ab 0 1635247637000 6 connected

redis集群搭建完成,我们使用了 docker 之后,所有的技术都会慢慢变得简单起来!

SpringBoot 微服务打包为镜像

  • 构建SpringBoot项目
  • 打包运行
mvn package
  • 编写dockerfile
FROM java:8
COPY *.jar /app.jar
CMD ["---server.port=8080-----"]
EXPOSE 8080
ENTRYPOINT ["java","- jar","app.jar"]
  • 构建镜像
# 1.复制镜像和Dockerfile到服务器
# 2.构建镜像
$ docker build -t 目标镜像:TAG .
  • 发布运行
    以后我们使用了 Docker 之后,给别人交付就算一个镜像即可!
  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-10-27 13:11:54  更:2021-10-27 13:14:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 22:32:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码