视频 Docker 学习(高级篇)
1、容器数据卷
1.1、什么是容器数据卷?
将应用和环境打包成一个镜像!
数据?如果数据都在容器中,那么我们容器删除,数据就会丢失!需求:数据可以持久化!
MySQL,容器删除了,删库跑路,需求:MySQL数据可以存储在本地!
容器之间可以有一个数据共享的技术!Docker容器中产生的数据,同步到本地!
这就是卷技术!目录挂载,将我们容器内的目录,挂载到Linux上面!
总结一句话:容器的持久化和同步操作!容器间也是可以数据共享的。
1.2、使用数据卷
方式一:直接使用命令挂载 -v
-v, --volume list Bind mount a volumedocker 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
测试文件的同步
再来测试!
- 停止容器
- 宿主机修改文件
- 启动容器并进入正在运行的该容器
- 容器内的数据依旧是同步的
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端口要在虚拟机上开放该端口,否则外部无法连接。
当我们在本地用Navicat新建名称为dataease的数据库的时候,容器中也会创建。
假设我们将包含mysql的容器删除的时候
发现,我们挂载到本地的数据卷依旧没有丢失,这就实现了容器数据持久化功能。
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 是查看不到的。
区分三种挂载方式:
# 三种挂载方式: 匿名挂载、具名挂载、指定路径挂载
-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 dockerfile1FROM 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
这个卷和外部一定有一个同步的目录
查看一下卷挂载
# docker inspect 容器id
$ docker inspect ca3b45913df5
测试一下刚才的文件是否同步出去了!
这种方式使用的十分多,因为我们通常会构建自己的镜像!
假设构建镜像的时候没有挂载卷,要手动镜像挂载-v 卷名:容器内路径!(使用的是具名挂载)
5、数据卷容器
多个MySQL同步数据(即容器内部同步数据)!
命名的容器挂载数据卷!
# 测试 启动三个容器,通过刚才自己写的镜像启动
# 创建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
# 再新建一个docker03同样继承docker01
$ docker run -it --name docker03 --volumes-from docker01 itgsh_code/centos:latest
$ cd volume01
$ ls
docker01.txt# 测试:可以删除容器docker01,查看一下docker02和docker03是否可以访问这个文件
# 测试发现:数据依旧保留在docker02和docker03中没有被删除
多个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、阿里云仓库)
点击后跳到一个 Dockerfile
很多官方镜像都是基础包,很多功能都没有,我们通常会自己搭建自己的镜像!
官方既然可以制作镜像,那我们也可以!
DockerFile 构建过程
基础知识:
- 每个保留关键字(指令)都是必须是大写字母
- 执行顺序从下到上
- # 表示注释
- 每一个指令都会创建提交一个新地镜像层,并提交。
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:构建的时候设置环境变量
实战测试:
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,然后配置需要的软件和配置来进行构建。
创建一个自己的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 # 将工作目录设置为MYPATHRUN yum -y install vim # 给官方原生的centos 增加vim指令
RUN yum -y install net-tools # 给官方原生的centos 增加ifconfig指令EXPOSE 8088 # 暴漏端口号为8088CMD 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.出现下图后则构建成功
$ 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
我们平时拿到一个镜像,可以用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的压缩包
2、编写dockerfile文件,官方命名,Dockerfile
,build会自动寻找这个文件,就不需要 -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.jarENV 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 --helpUsage: 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-storeLogin Succeeded
4、提交 push 镜像
# 会发现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/
小结
Docker 网络
理解Docker 0
学习之前清空下前面的docker镜像,容器
# 删除全部的容器
$ docker rm -f $(docker ps -qa)# 删除全部的镜像文件
$ docker rmi -f $(docker images -qa)
三个网络
问题:Docker 是如何处理容器网络访问的?
# 测试 运行一个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 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_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 0inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0valid_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地址)
# 我们发现这个容器带来网卡,都是一对对的
# 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 0inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0valid_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通
结论:tomcat01 和 tomcat02 公用一个路由器,docker0。
所有的容器不指定网络的情况下,都是docker0路由的,docker会给我们分配一个默认的可用ip。
小结
Docker 使用的是Linux的桥接,宿主机是一个Docker容器的网桥 docker0
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
docker network inspect 网络id 网段相同
–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 网络
网络模式
- 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
$ docker network inspect mynet
到这里,我们自己定义的网络就已经创建好了!
在我们定义的网络下,启动两个tomcat,再次查看网络情况:
我们自定义的网络 docker 都已经帮我们维护好了对应的关系,推荐我们平时使用这种网络!
好处:
- redis - 不同的集群使用不同的网络,保证集群是安全和健康的。
- mysql - 不同的集群使用不同的网络,保证集群是安全和健康的。
网络连通
# 测试两个不同的网络连通,再启动两个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)
# 01连通,加入到mynet网络后,此时,已经可以将tomcat01和tomcat-net-01 ping通了
# 02是依旧不通的
结论:假设要跨网络操作别人,就需要使用docker network connect 连通!
实战:部署 Redis 集群
# 创建网卡
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:6379slots:[0-5460] (5461 slots) master
M: ab6cdb5c61ec075f99e777586d6b919dfec7f7ab 172.38.0.12:6379slots:[5461-10922] (5462 slots) master
M: 5199308c04f4b1473f62dd309b59a0e2bdb5a8d4 172.38.0.13:6379slots:[10923-16383] (5461 slots) master
S: f255f93c2e044c787058c5f94531cc8e3ae3ce3b 172.38.0.14:6379replicates 5199308c04f4b1473f62dd309b59a0e2bdb5a8d4
S: f6dfeb8166235e41ac35d631ed09ec0ea757e890 172.38.0.15:6379replicates 139aec873bae9cc4be4671b684741d9aaf892528
S: a70d391ab4263340154558c97ccbf040bd448c2d 172.38.0.16:6379replicates 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:6379slots:[0-5460] (5461 slots) master1 additional replica(s)
S: f255f93c2e044c787058c5f94531cc8e3ae3ce3b 172.38.0.14:6379slots: (0 slots) slavereplicates 5199308c04f4b1473f62dd309b59a0e2bdb5a8d4
M: ab6cdb5c61ec075f99e777586d6b919dfec7f7ab 172.38.0.12:6379slots:[5461-10922] (5462 slots) master1 additional replica(s)
M: 5199308c04f4b1473f62dd309b59a0e2bdb5a8d4 172.38.0.13:6379slots:[10923-16383] (5461 slots) master1 additional replica(s)
S: f6dfeb8166235e41ac35d631ed09ec0ea757e890 172.38.0.15:6379slots: (0 slots) slavereplicates 139aec873bae9cc4be4671b684741d9aaf892528
S: a70d391ab4263340154558c97ccbf040bd448c2d 172.38.0.16:6379slots: (0 slots) slavereplicates 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 之后,给别人交付就算一个镜像即可!
视频 Docker 学习(高级篇)相关推荐
- python学习高级篇(part10)--类对象的特殊方法和特殊属性
学习笔记,仅供参考,有错必纠 文章目录 python 学习高级篇 类对象的特殊方法之`__del__()` 类对象的特殊方法之`__getattr__()` 类对象的特殊方法之`__getitem__ ...
- python学习高级篇(part9)--对象的引用计数
学习笔记,仅供参考,有错必纠 文章目录 python 学习高级篇 类对象的特殊方法之`__str__()` 类对象的特殊方法之`__new__()` 对象的引用计数 什么是引用计数 对象的引用计数加1 ...
- python学习高级篇(part8)--类对象的特殊方法
学习笔记,仅供参考,有错必纠 文章目录 python 学习高级篇 类对象的特殊方法之`__iter__()`和`__next__()` 类对象的特殊方法之`__add__()`和`__radd__() ...
- python学习高级篇(part7)--特殊属性和特殊方法
学习笔记,仅供参考,有错必纠 文章目录 python 学习高级篇 特殊属性和特殊方法 获取对象的信息之特殊属性`__dict__` 获取对象的信息之反射 类对象的特殊方法`__len__()` pyt ...
- Docker 之 高级篇(应用复杂安装、DockerFile、Docker网络、Docker-compose、可视化工具)
前言 前一章介绍了docker的基础知识,适合零基础小白阅读和学习,当然非小白也可用于查阅,查漏补缺,本章开始将记录一些docker的高级部分,难度上也会提升很多,内容较多,比较枯燥,不过看下来一定会 ...
- Docker 学习应用篇之一: 初识Docker
Docker 自从2013年以来就非常的火热,无论是从github上的代码活跃度,还是Redhat在RHE6.5中集成对Docker的支持,等等.第一次接触Docker,还是老师给我们介绍的. 1.初 ...
- Docker学习进阶篇
学自狂神. 视频地址:https://www.bilibili.com/video/BV1kv411q7Qc?share_source=copy_web 目标: 掌握: docker基础,原理.网络. ...
- python教学视频m_Python学习基础篇 -1
前言:本专栏以Python为主题,并尽可能保持每星期两到三更,直到将Python的基础知识浅析和讲解完毕,同时,有一定基础的同学可以移步 Python实战专栏 . 第一篇:Python中的输入与输出 ...
- python学习高级篇(part6)--内置函数dir
学习笔记,仅供参考,有错必纠 内置函数dir 对于类对象或实例对象,可以调用内置函数dir()获得其所有可以访问的属性和方法(包括从父类中继承的属性和方法)的列表. 类对象与实例对象的结果是有区别的, ...
- python学习高级篇(part5)--内置函数type
学习笔记,仅供参考,有错必纠 内置函数type 内置函数type()用于获得指定对象的类型,比如:实例对象的类型是其对应的类对象. 举个例子 代码: class MyClass(object):pas ...
最新文章
- 史上最全的CSS hack方式一览(转)
- epoll 边沿触发 非阻塞 IO 服务器
- (转) SpringBoot接入两套kafka集群
- 时间管理——你不可不知的3种时间管理方法
- 消息中间件学习总结(9)——RocketMQ与kafka差异比较分析
- 微型计算机2014年9月下,2014年9月计算机应用基础》网络教育统考真题.doc
- Mybatis Plus配置以及单表操作
- 局域网抢速,局域网抢网速软件下载,p2p终结者和反p2p终结
- CH372或CH375的USB通讯问题解答
- 用于视觉问答的相互注意融合模型《Reciprocal Attention Fusion for Visual Question Answering》
- 思科实验4.4.1.2-Packet Tracer - 综合技能练习
- Unity Translate方法使用指南
- MySQL --- 函数大全3
- 百度分享代码--一键分享Baidu Share BEGIN
- idea中module项目没有蓝色小方块问题
- windows系统IP地址、localhost、127.0.0.1 、0.0.0.0和 本机IP区别
- 团队的英文翻译缩写_团队的英语是什么?简写呢?
- 《走近心理学》第三章之行为主义理论
- 从0到1,反距离加权IDW(Inverse Distance Weighted Interpolation) 插值变形算法
- 2023王道计算机408领学班