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文件,官方命名,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.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 学习(高级篇)相关推荐

  1. python学习高级篇(part10)--类对象的特殊方法和特殊属性

    学习笔记,仅供参考,有错必纠 文章目录 python 学习高级篇 类对象的特殊方法之`__del__()` 类对象的特殊方法之`__getattr__()` 类对象的特殊方法之`__getitem__ ...

  2. python学习高级篇(part9)--对象的引用计数

    学习笔记,仅供参考,有错必纠 文章目录 python 学习高级篇 类对象的特殊方法之`__str__()` 类对象的特殊方法之`__new__()` 对象的引用计数 什么是引用计数 对象的引用计数加1 ...

  3. python学习高级篇(part8)--类对象的特殊方法

    学习笔记,仅供参考,有错必纠 文章目录 python 学习高级篇 类对象的特殊方法之`__iter__()`和`__next__()` 类对象的特殊方法之`__add__()`和`__radd__() ...

  4. python学习高级篇(part7)--特殊属性和特殊方法

    学习笔记,仅供参考,有错必纠 文章目录 python 学习高级篇 特殊属性和特殊方法 获取对象的信息之特殊属性`__dict__` 获取对象的信息之反射 类对象的特殊方法`__len__()` pyt ...

  5. Docker 之 高级篇(应用复杂安装、DockerFile、Docker网络、Docker-compose、可视化工具)

    前言 前一章介绍了docker的基础知识,适合零基础小白阅读和学习,当然非小白也可用于查阅,查漏补缺,本章开始将记录一些docker的高级部分,难度上也会提升很多,内容较多,比较枯燥,不过看下来一定会 ...

  6. Docker 学习应用篇之一: 初识Docker

    Docker 自从2013年以来就非常的火热,无论是从github上的代码活跃度,还是Redhat在RHE6.5中集成对Docker的支持,等等.第一次接触Docker,还是老师给我们介绍的. 1.初 ...

  7. Docker学习进阶篇

    学自狂神. 视频地址:https://www.bilibili.com/video/BV1kv411q7Qc?share_source=copy_web 目标: 掌握: docker基础,原理.网络. ...

  8. python教学视频m_Python学习基础篇 -1

    前言:本专栏以Python为主题,并尽可能保持每星期两到三更,直到将Python的基础知识浅析和讲解完毕,同时,有一定基础的同学可以移步 Python实战专栏 . 第一篇:Python中的输入与输出 ...

  9. python学习高级篇(part6)--内置函数dir

    学习笔记,仅供参考,有错必纠 内置函数dir 对于类对象或实例对象,可以调用内置函数dir()获得其所有可以访问的属性和方法(包括从父类中继承的属性和方法)的列表. 类对象与实例对象的结果是有区别的, ...

  10. python学习高级篇(part5)--内置函数type

    学习笔记,仅供参考,有错必纠 内置函数type 内置函数type()用于获得指定对象的类型,比如:实例对象的类型是其对应的类对象. 举个例子 代码: class MyClass(object):pas ...

最新文章

  1. 史上最全的CSS hack方式一览(转)
  2. epoll 边沿触发 非阻塞 IO 服务器
  3. (转) SpringBoot接入两套kafka集群
  4. 时间管理——你不可不知的3种时间管理方法
  5. 消息中间件学习总结(9)——RocketMQ与kafka差异比较分析
  6. 微型计算机2014年9月下,2014年9月计算机应用基础》网络教育统考真题.doc
  7. Mybatis Plus配置以及单表操作
  8. 局域网抢速,局域网抢网速软件下载,p2p终结者和反p2p终结
  9. CH372或CH375的USB通讯问题解答
  10. 用于视觉问答的相互注意融合模型《Reciprocal Attention Fusion for Visual Question Answering》
  11. 思科实验4.4.1.2-Packet Tracer - 综合技能练习
  12. Unity Translate方法使用指南
  13. MySQL --- 函数大全3
  14. 百度分享代码--一键分享Baidu Share BEGIN
  15. idea中module项目没有蓝色小方块问题
  16. windows系统IP地址、localhost、127.0.0.1 、0.0.0.0和 本机IP区别
  17. 团队的英文翻译缩写_团队的英语是什么?简写呢?
  18. 《走近心理学》第三章之行为主义理论
  19. 从0到1,反距离加权IDW(Inverse Distance Weighted Interpolation) 插值变形算法
  20. 2023王道计算机408领学班

热门文章

  1. 2022年web前端面试题
  2. 基于安卓/android/微信小程序的自来水收费系统app-#计算机毕业设计
  3. 数据结构—顺序表详解
  4. layui修改头像功能
  5. oracle 英文 简历,简历表英文模板
  6. wps下一步快捷键_wps后退前进快捷键是什么?
  7. knockoutjs总结
  8. python arma_Python实现ARMA模型
  9. 第四章 ARMA模型的特性
  10. 缺少vclie60.bpl的解决方法