概述
文章目录
- Doker概述
- Docker为什么会出现
- Docker简介
- Docker的基本组成
- Docker安装
- 帮助命令
- 镜像命令
- 容器命令
- 可视化
- Docker镜像
- 镜像是什么
- Docker镜像加载原理
- 容器数据卷
- 使用数据卷
- 安装MySQL
- 具名和匿名挂载
- 初始DockerFile
- 数据卷容器
- DockerFile介绍
- DockerFile构建过程
- DockerFile的指令
- 自定义Tomcat镜像
- 发布自己的镜像
- Docker网络
- 理解Docker0
- --link
- 自定义网络
- 网络连通
- 实战:部署Redis集群
- SpringBoot微服务打包Docker镜像
- **总结**
Doker概述
Docker为什么会出现
任何一个东西的产生都是有原因的,那么Docker的出现也不例外。举个栗子:一款产品从开发到上线,一般是有两套环境的,即开发人员的本地的应用环境和配置和项目上线后运维的部署环境。那么很容易产生一种问题:版本更新导致服务不可用,这对于运维人员来说考验巨大,毕竟环境配置是十分麻烦的一件事,比如每台机器都要配置jdk,hadoop集群,redis集群等等,费时又费力。(小声bb:我是大数据专业的,我的基本所有专业课有一半的时间都是水在搭建集群环境!!!)
而Docker就很好的解决了这个问题,传统的过程通俗点来说就是开发打个jar包过来,然后环境部署配置就由运维来做;现在有了docker项目打包部署一套流程做完,或者可以理解为有了docker,在打包项目的时候可以把环境连(镜像)同打包,只需要到Docker仓库下载发布的镜像,直接运行程序即可,十分的nice。
Docker简介
Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。
这些都是官方文档中所描述的,听起来比较高大上,就我的理解来看它与传统的虚拟机的区别就是:它虚拟的不是一个完整的操作系统,容器中的应用直接运行在宿主机的内核,容器是没有自己的内核的,也没有虚拟硬件,所以相比传统的虚拟机更轻便,并且每个容器间是隔离的,每个容器都有自己的文件系统,互不影响。
Docker的基本组成
镜像(image):docker的镜像就好比一个模板,可以通过这个模板来创建容器服务。通过这个镜像可以创建多个容器(最终项目或服务运行就是在容器中的)。
容器(container):docker利用容器技术,独立运行一个或一组应用,通过镜像来创建。这里我是简单的把它理解成一个简易的“轻量”操作系统。
仓库(repository):仓库就是存放镜像的地方,分为公有和私有。同maven仓库的概念一样。
Docker安装
要求:Linux内核3.8以上,Centos7,通过MobaXterm连接到服务。
[root@node1 ~]# uname -r
3.10.0-1062.el7.x86_64
系统版本
[root@node1 ~]# cat /etc/os-release
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"
CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"
#卸载旧版本
yum remove docker
docker-client
docker-client-latest
docker-common
docker-latest
docker-latest-logrotate
docker-logrotate
docker-engine
下载需要的安装包
yum install -y yum-utils
设置镜像仓库
这里需要注意,默认的是使用的国外的镜像源,特别慢,推荐使用阿里或者清华的镜像源。
yum-config-manager
--add-repo
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
更新yum软件包索引
yum makecache fast
安装docker相关的依赖
这里我们选的是docker-ce 社区版
yum install docker-ce docker-ce-cli containerd.io
启动docker
systemctl start docker测试验证helloworld
测试
docker run hello-world
帮助命令
万能命令
docker --help
#系统常用命令
#查看内存占用情况
docker stats
#docker环境信息
docker info | version
#查看容器或镜像信息
docker inspect
镜像命令
#查看自己服务器中docker 镜像列表
docker images
#搜索镜像
docker search 镜像名
docker search --filter=STARS=9000 mysql 搜索 STARS >9000的 mysql 镜像
#拉取镜像 不加tag(版本号) 即拉取docker仓库中 该镜像的最新版本latest 加:tag 则是拉取指定版本
docker pull 镜像名
docker pull 镜像名:tag
#运行镜像
docker run 镜像名
docker run 镜像名:Tag
#删除镜像 当前镜像没有被任何容器使用才可以删除
#删除一个
docker rmi -f 镜像名/镜像ID
#删除多个 其镜像ID或镜像用用空格隔开即可
docker rmi -f 镜像名/镜像ID 镜像名/镜像ID 镜像名/镜像ID
#删除全部镜像 -a 意思为显示全部, -q 意思为只显示ID
docker rmi -f $(docker images -aq)
...........
容器命令
#可以通过run 镜像 来构建 自己的容器实例
#可以加参数
-d 后台运行(守护式运行)
-p 手动端口映射
-P 随机分配端口
-v 卷挂载 可以设置多个
-e 环境配置
--name 容器名
-it 表示 与容器进行交互式启动
/bin/bash 交互路径
......
docker run -it -d --name 要取得别名 镜像名:Tag /bin/bash
#查看正在运行容器列表
docker ps
#查看所有容器 -----包含正在运行 和已停止的
docker ps -a
#停止容器
docker stop 容器名/容器ID
#启动容器
docker start 容器名/容器ID
#重启容器
docker restart 容器名/容器ID
#kill 容器
docker kill 容器ID/容器名
#删除一个容器
docker rm -f 容器名/容器ID
#删除多个容器 空格隔开要删除的容器名或容器ID
docker rm -f 容器名/容器ID 容器名/容器ID 容器名/容器ID
#删除全部容器
docker rm -f $(docker ps -aq)
#进入容器的方式1
docker exec -it 容器名/容器ID /bin/bash
#进入容器的方式2
docker attach 容器名/容器ID
#从容器退出
#-----直接退出 未添加 -d(持久化运行容器) 时 执行此参数 容器会被关闭
exit
# 优雅提出 --- 无论是否添加-d 参数 执行此命令容器都不会被关闭
Ctrl + p + q
#查看容器日志
docker logs -f --tail=要查看末尾多少行 默认all 容器ID
.........
可视化
portainer
官方提供的一个docker可视化工具,也是一个镜像,启动后指定端口,然后在windows下访问,即可使用可视化工具管理docker资源。
docker run -d -p 8088:9000
--restart=always -v /var/run/docker.sock:/var /run/docker.sock --privilegedtrue portainer /portainer
可视化页面访问url: http://39.108.122.21:8088/#/dashboard
Docker镜像
镜像是什么
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。
Docker镜像加载原理
UnionFS (联合文件系统)
UnionFS (联合文件系统):Union文件系统( UnionFS )是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtualfilesystem)。Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性∶一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录
Docker镜像加载原理
docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS.
bootis(boot file system)主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。
roots (root file system),在bootfs之上。包含的就是典型Linux系统中的/dev,/proc, /bin,/etc等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu , Centos等等。
容器数据卷
使用数据卷
方式一:直接使用命令行来挂载
docker run -it -v 主机目录:容器内目录
#测试
[root@along ~]# docker run -it -v /home/test01:/home centos /bin/bash
#启动后通过docker inspect 容器id 查看
结果:
再次测试
1.停止容器
2.宿主机修改文件
3.启动容器
4.容器内数据依旧是同步的
双向同步
好处:我们以后修改只需要再本地修改,容器内会自动同步。
安装MySQL
#获取镜像
[root@along ~]# docker pull mysql:5.7
#运行容器,需要做数据挂载! 安装启动mysql需要配置密码 注意!
#官方测试
$ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
#自己启动
-d 后台运行
-p 端口映射
-v 卷挂载 可以设置多个
-e 环境配置
--name 容器名
[root@along ~]# docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=228228 --name mysql01 mysql:5.7
#启动成功后,再本地使用sqlyog来连接测试一下
#sqlyog-连接到服务器的3306 -- 3306和容器内的3306映射
假设我们将容器删除,发现我们挂载到本地的数据卷依旧没有丢失
这就实现了容器数据持久化功能!
具名和匿名挂载
#匿名挂载
-v 容器内路径
[root@along /]# docker run -d -P --name nginx -v /etc/nginx nginx
#查看所有的挂载情况
[root@along /]# docker volume ls
#具名挂载
-v 卷名:容器内路径
[root@along /]# docker run -d -P --name nginx02 -v nginx-vol:/etc/nginx nginx
-v 只写了容器内路径,没写容器外路径,默认指定了挂载目录。
-v 卷名:容器内路径
#查看卷
[root@along /]# docker volume inspect nginx-vol
所有docker容器内的卷,没有指定目录的情况下都是在==/var/lib/docker/volumes/xxx==下
我们通过具名挂载可以方便的找到我们的一个卷,大多数情况在使用的具名挂载
例如:nginx的配置文件挂载到Linux下
#如何确定是具名挂载还是匿名挂载,还是指定路径挂载?
- -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
初始DockerFile
Dockerfile就是用来构建docker镜像的构建文件!命令脚本!
通过一个脚本生成镜像!
#创建一个dockerfile文件(指令全部大写)
FROM centos
VOLUME ["volume01","volume02"]
CMD echo "----end-----"
CMD /bin/bash
#通过dockerfile构建镜像的命令
#-f 指定路径的dockerfile
#-t 生成的目标镜像的信息
[root@along docker-test-volume]# docker build -f /home/docker-test-volume/dockerfile1 -t along/centos:1.0 .
结果:这就是我们自己生成的镜像
进入我们通过dockerfile创建的镜像,查看:
我们在容器内的volume01新建一个test.txt文件,然后在本地的挂载路径查看是否同步!
[root@along /]# docker inspect 容器id
我们到指定的本地路径下查看,是否也同步创建test.txt文件
数据卷容器
多个mysql同步数据
#使用自己构建的镜像启动一个容器
[root@along /]# docker run -it --name docker01 along/centos:1.0
#使用同一个镜像启动一个新的容器并挂载到之前启动的容器
[root@along /]# docker run -it --name docker02 --volumes-from docker01 along/centos:1.0
这样两个容器之间可以进行数据共享
[root@kuangshen home]# docker run -d -p 3310:3306 -v /etc/mysq1/conf.d -v /var/1ib/mysq1 -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
[root@kuangshen home]# docker run -d -p 3310:3306 -e MYSQL_RO0T_PASSWORD=123456 --name mysq102 --volumes-form mys q101 mysq1:5.7
#这个时候,可以实现两个容器数据同步!
DockerFile介绍
构建步骤:
- 编写一个dockerfile文件
- docker build构建成为一个镜像
- docker run运行镜像
- docker push 发布镜像(DockerHub、阿里云镜像仓库!)
打开Docker Hub官网,搜索centos,选择一个版本点击进入,会跳转到GitHub:
很多官方镜像都是基础包,很多功能没有,我们通常会自己搭建自己的镜像官方既然可以制作镜像,那我们也可以!
DockerFile构建过程
基础知识∶
- 每个保留关键字(指令)都是必须是大写字母
- 执行从上到下顺序执行
- #表示注释
- 每一个指令都会创建提交一个新的镜像层,并提交!|
dockerfile是面向开发的,我们以后要发布项目,做镜像,就需要编写dockerfile文件,这个文件十分简单!Docker镜像逐渐成为企业交付的标准,必须要掌握!I
步骤:
- DockerFile :构建文件,定义了一切的步骤,源代码
- Dockerlmages :通过DockerFile构建生成的镜像,最终发布和运行的产品!
- DockerContainer︰容器就是镜像运行起来的服务
DockerFile的指令
FROM #基础镜像
MAINTAINER #镜像是谁写的 姓名+邮箱
RUN #镜像构建时需要运行的命令
ADD #添加内容
WORKDIR #镜像的工作目录
VOLUME #挂载的目录
EXPOSE #暴露端口配置(在启动时就不用使用-p指定)
CMD #指定容器启动时需要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT #指定容器启动时要运行的命令,可以追加命令
ONBUILD #当构建一个被继承DockerFile这个时候会运行,ONBUILD的指令 触发指令
COPY #类似ADD,将我们文件拷贝到镜像中
ENV #构建的时候设置环境变量
#创建一个自己的centos镜像
#1.编写dockefile文件
[root@along dockerfile]# cat mydockerfile-centos
FROM centos
MAINTAINER along<2238595207@qq.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "----end----"
CMD /bin/bash
#2.构建(坑:新建一个文件夹dockerfile,在该目录下编写dockerfile文件,并且在该目录下执行构建命令。否则系统会提示找不到上下文。)
[root@along dockerfile]# docker build -f mydockerfile-centos -t mycentos:0.1 .
查看:刚刚的镜像已经构建成功
启动我们自己构建的镜像,发现我们新增的命令都已经安装了:
测试CMD和ENTRYPOINT
自定义Tomcat镜像
-
准备镜像文件tomcat压缩包和jdk压缩包,然后新建一个Dockerfile文件
-
编写Dockerfile文件,官方命名Dockerfile。build时会自动寻找这个文件,不用-f指定
FROM centos MAINTAINER along<2238595207@qq.com> COPY readme.txt /usr/local/readme.txt ADD jdk-8u251-linux-x64.tar.gz /usr/local/ ADD apache-tomcat-9.0.46.tar.gz /usr/local/ RUN yum -y install vim ENV MYPATH /usr/local WORKDIR $MYPATH ENV JAVA_HOME /usr/local/jdk1.8.0_251 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.46 ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.46 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin EXPOSE 8080 CMD /usr/local/apache-tomcat-9.0.46/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.46/bin/logs/catalina.out
-
构建镜像
[root@along tomcat]# docker build -t diytomcat .
-
启动容器
[root@along tomcat]# docker run -d -p 9090:8080 --name alongtomcat -v /tomcat/test:/usr/local/apache-tomcat-9.0.46/webapps/test -v /tomcat/tomcatlogs:/usr/local/apache-tomcat-9.0.46/logs diytomcat
-
测试访问
#容器内访问 [root@along ~]# curl localhost:9090
-
外部访问,直接输入IP+端口号即可访问,注意需要在阿里云配置安全组开放对应的端口
-
因为做了卷挂载,所以我们发布项目只需要在本地的tomcat/test目录下编写即可发布。
发布自己的镜像
-
现在Docker Hub官网注册自己的账号
-
登录Doker
[root@along ~]# 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@along ~]# docker tag ceffc54fa152 along1844/helloalong:1.0 [root@along ~]# docker push along1844/helloalong:1.0 # along1844是docker hub的账户名
Docker网络
理解Docker0
#问题: docker是如何处理容器网络访问的?
# 查看容器的内部网络地址ip addr,发现容器启动的时候会得到一个eth0@if262 ip地址,docker分配的!
[root@along ~]# docker exec -it tomcat-test 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
24: eth0@if25: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
# ??? 思考:Linux能否ping通容器内部??
原理:
-
我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡docker0,桥接模式,使用的技术是evth-pair技术!
再次测试ip addr:
再启动一个容器查看:
#发现Linux下又多了一对网卡,通过启动容器新增的网卡都是一对的! #evth-pair技术 就是一对虚拟设备接口,它们成对出现,一端连着协议,一端彼此相连
测试:启动两个容器,测试能否在一个容器中ping通另一个容器?
#启动tomcat-test [root@along ~]# docker exec -it tomcat-test 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 24: eth0@if25: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever #启动tomcat-test1 [root@along ~]# docker exec -it tomcat-test1 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 26: eth0@if27: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.4/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever # 进入tomcat-test [root@along ~]# docker exec -it tomcat-test /bin/bash #tomcat-test 中ping tomcat-test1 root@0f64f7f99b2f:/usr/local/tomcat# ping 172.17.0.4 PING 172.17.0.4 (172.17.0.4) 56(84) bytes of data. 64 bytes from 172.17.0.4: icmp_seq=1 ttl=64 time=0.124 ms 64 bytes from 172.17.0.4: icmp_seq=2 ttl=64 time=0.081 ms 64 bytes from 172.17.0.4: icmp_seq=3 ttl=64 time=0.083 ms 64 bytes from 172.17.0.4: icmp_seq=4 ttl=64 time=0.077 ms 64 bytes from 172.17.0.4: icmp_seq=5 ttl=64 time=0.078 ms ^C --- 172.17.0.4 ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 86ms rtt min/avg/max/mdev = 0.077/0.088/0.124/0.020 ms
ok,可以发现在tomcat-test容器中可以ping通tomcat-test1容器
结论:容器与容器之间可以相互ping通
原因:处于docker0的同一路由下,即在同一个网段,172.17.0.1?但是实际原理并不是这样?
实际上是这样的:
结论:tomcat01和tomcat02是公用的一个路由器,docker0。
所有的容器不指定网络的情况下,都是docker0路由的,docker会给我们的容器分配一个默认的可用IP
Docker使用的是Linux的桥接,宿主机中是一个Docker容器的网桥docker0
只要容器删除,对应的网桥对也会删除。
–link
测试:
#启动tomcat01
[root@along ~]# docker run -it -d -P --name tomcat01 tomcat
f4a76f569523d08eff05797c2d293320dd0759d9a27345277858f03885e7c500
#启动tomcat02
[root@along ~]# docker run -it -d -P --name tomcat02 tomcat
c8d7b647f8580c3f06100543ce75b208c3de6ef11e3efbf99ae1e7bf0cc503ab
#通过容器名 tomcat01 ping 不通 tomcat02
[root@along ~]# docker exec -it tomcat01 ping tomcat02
ping: tomcat02: Name or service not known
#启动tomcat03 --link tomcat02
[root@along ~]# docker run -it -d -P --name tomcat03 --link tomcat02 tomcat
13a297ffef72e8f9ee85f92795513501de64a648d10b39dbd35c639112680d73
#再次测试 tomcat03 可以ping 通tomcat02
[root@along ~]# docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.17.0.4) 56(84) bytes of data.
64 bytes from tomcat02 (172.17.0.4): icmp_seq=1 ttl=64 time=0.119 ms
64 bytes from tomcat02 (172.17.0.4): icmp_seq=2 ttl=64 time=0.077 ms
64 bytes from tomcat02 (172.17.0.4): icmp_seq=3 ttl=64 time=0.081 ms
^C
--- tomcat02 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 82ms
rtt min/avg/max/mdev = 0.077/0.092/0.119/0.020 ms
#反向ping 不能ping通 未配置
[root@along ~]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known
[root@along ~]# docker network inspect 8984975b83a0
# 进入tomcat03容器查看/etc/hosts文件[root@along ~]# docker exec -it tomcat03 cat /etc/hosts
可以发现tomcat03的hosts文件中配置了tomcat02的ip映射,所以可以ping通
# 对比:查看tomcat02的hosts文件中没有配置tomcat03的ip映射,所以tomcat02无法ping通tomcat03
–link 单向绑定
自定义网络
查看所有doker网络
网络模式
bridge:桥接 docker(默认,自己创建也使用bridge模式)
none:不配置网络
host:和宿主机共享网络
container:容器网络连通!(局限大,使用较少)
测试
# 之前我们直接启动容器 默认加了--net bridge参数 这个就是docker0
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat01 --net bridge tomcat
#docker0 默认域名不能访问
# 我们可以自定义一个网络
--driver bridge #桥接模式
--subnet 192.168.0.0/24 #子网掩码
--gateway 192.168.0.1 #网关
[root@along ~]# docker network create --driver bridge --subnet 192.168.0.0/24 --gateway 192.168.0.1 mynet
ae99296ea19bd29e03f3095764cca05f2f797a7b83d19f216e56b14bfee266d9
[root@along ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
8984975b83a0 bridge bridge local
5954083546bc host host local
ae99296ea19b mynet bridge local
59f0a22f01c7 none null local
#查看自己创建的网络
[root@along ~]# docker network inspect mynet
# 这个时候我们就可以在自定义的网络中启动容器,
# 前面说到 --net(network)
# 默认是指定的docker0路由,这里换成我们自己的路由即可。
# 在mynet网络下创建两个容器
[root@along ~]# docker run -it -d -P --name tomcat01 --network mynet tomcat
80f44b9f653d975b7459f92ceb10cb660f78fb84d5958728d18b100b17c3613a
[root@along ~]# docker run -it -d -P --name tomcat02 --network mynet tomcat
9c16a6d18b9a3252e15df72e4ddc2019a5dfc9531819cc0de9bbab5dd2bb57bf
# 再次查看mynet的信息,发现新增了tomct01和tomcat02的相关信息
[root@along ~]# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "ae99296ea19bd29e03f3095764cca05f2f797a7b83d19f216e56b14bfee266d9",
"Created": "2021-05-23T11:10:06.462688205+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/24",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"80f44b9f653d975b7459f92ceb10cb660f78fb84d5958728d18b100b17c3613a": {
"Name": "tomcat01",
"EndpointID": "f7ec4e478f4996abca298d64af4bd61eac6972b321a45e3b34ba6f812f4802ff",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/24",
"IPv6Address": ""
},
"9c16a6d18b9a3252e15df72e4ddc2019a5dfc9531819cc0de9bbab5dd2bb57bf": {
"Name": "tomcat02",
"EndpointID": "004d86cdd7120c02916c9e14a138ae751faf628bc5a5a21b4517e07ee9d1e4b8",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/24",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
# 这样两个容器都在自己配置的网络下,无论通过ip还是容器名都可以ping通!
# 测试
[root@along ~]# docker exec -it tomcat01 ping tomcat02
PING tomcat02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.106 ms
64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.089 ms
64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.077 ms
64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=4 ttl=64 time=0.083 ms
^C
--- tomcat02 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 76ms
rtt min/avg/max/mdev = 0.077/0.088/0.106/0.015 ms
[root@along ~]# docker exec -it tomcat02 ping tomcat01
PING tomcat01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.068 ms
64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.078 ms
64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=3 ttl=64 time=0.083 ms
^C
--- tomcat01 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 29ms
rtt min/avg/max/mdev = 0.068/0.076/0.083/0.009 ms
[root@along ~]# docker exec -it tomcat02 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=4.28 ms
64 bytes from 192.168.0.2: icmp_seq=2 ttl=64 time=0.089 ms
64 bytes from 192.168.0.2: icmp_seq=3 ttl=64 time=0.081 ms
^C
--- 192.168.0.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 40ms
rtt min/avg/max/mdev = 0.081/1.484/4.283/1.979 ms
[root@along ~]# docker exec -it tomcat01 ping 192.168.0.3
PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.097 ms
64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.078 ms
64 bytes from 192.168.0.3: icmp_seq=3 ttl=64 time=0.086 ms
^C
--- 192.168.0.3 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 31ms
rtt min/avg/max/mdev = 0.078/0.087/0.097/0.007 ms
# 思考 我们通常搭建集群时,如redis,mysql集群,我们会把redis集群和mysql集群分别部署在不同的网段下,保证集群的安全性,docker如何实现?
网络连通
**问题:**在我们自定义的网络mynet下有两个容器tomcat-net-01,tomcat-net-02,在系统默认的docker0网络下有两个容器tomcat-01,tomcat-02,tomcat-01/02想直接ping通tomcat-net-01/02是不现实的,只能让tomcat-01先连接到mynet,然后再ping tomcat-net-01/02
测试
#把 tomcat-01 连接到 mynet
[root@along ~]# docker network connect mynet tomcat-01
# 再查看mynet中的信息, 发现多了一个容器tomcat-01 ,
# 并且分配了该网段下的ip
[root@along ~]# docker network inspect mynet
# 这样tomcat-01也被加到mynet网段下了,
# 那么毫无疑问,现在tomcat01是可以ping通tomcat-01的
# 说明:这样tomcat-01就有两个ip,mynet和docker0各有一个ip
# 理解:类似于阿里云服务,一个公网ip,一个私网ip
结论:假设需要跨网络操作,那就需要使用docker network connect 连通
实战:部署Redis集群
# 先创建一个redis的网段
[root@along ~]# docker network create redis --subnet 172.38.0.0/16
# 查看该网段的信息
[root@along ~]# docker network inspect redis
# 编写shell脚本来自动编辑redis-cli配置
for port in $(seq 1 6);
do
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF >/mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done
启动容器
[root@along /]# docker run -p 6371:6379 -p 16371:16379 --name redis-1
-v /mydata/redis/node-1/data:/data
-v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf
-d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
[root@along /]# docker run -p 6372:6379 -p 16372:16379 --name redis-2
-v /mydata/redis/node-2/data:/data
-v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf
-d --net redis --ip 172.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
[root@along /]# docker run -p 6373:6379 -p 16373:16379 --name redis-3
-v /mydata/redis/node-3/data:/data
-v /mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf
-d --net redis --ip 172.38.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
[root@along /]# docker run -p 6374:6379 -p 16374:16379 --name redis-4
-v /mydata/redis/node-4/data:/data
-v /mydata/redis/node-4/conf/redis.conf:/etc/redis/redis.conf
-d --net redis --ip 172.38.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
[root@along /]# docker run -p 6375:6379 -p 16375:16379 --name redis-5
-v /mydata/redis/node-5/data:/data
-v /mydata/redis/node-5/conf/redis.conf:/etc/redis/redis.conf
-d --net redis --ip 172.38.0.15 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
[root@along /]# docker run -p 6376:6379 -p 16376:16379 --name redis-6
-v /mydata/redis/node-6/data:/data
-v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf
-d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
#也可以通过脚本一次性启动6个容器
docker run -p 637${port}:6379 -p 1637${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
done
查看启动的redis容器
#进入容器,启动集群
[root@along ~]# docker exec -it redis-1 /bin/sh
/data # redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.1
4:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1
############
redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.1
4:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1
启动成功:
# 连接到redis客户端
127.0.0.1:6379> CLUSTER INFO
# 查看所有集群所有节点信息
127.0.0.1:6379> CLUSTER NODES
# 测试
# 设置一个k-v 发现是由redis-3来处理的
# 手动停掉redis-3容器
[root@along ~]# docker stop redis-3
# 再次get k 看能否得到v
# 可以发现即使手动宕机redis-3,它的从机redis-4也能接替它进行服务
# 查看节点信息 redis-4取代redis-3成为主节点
# 重新启动redis-3容器,再次进入redis客户端查看集群的节点信息,发现经过重新选举后,redis-4成为主节点,而刚重新启动的redis-3成为了redis-4的从机
SpringBoot微服务打包Docker镜像
-
构建SpringBoot项目
- 在idea中创建一个springboot项目 helloworld
- 在idea中创建一个springboot项目 helloworld
-
打包应用
- package 打成一个jar包
- package 打成一个jar包
-
编写Dockerfile
-
在idea中下载docker插件
-
编写Dockerfile
-
-
构建镜像
-
把jar包和Dockerfile都上传到虚拟机的本地目录
-
通过build构建
通过构建的镜像运行容器,查看结果:
-
-
发布运行
总结
所有笔记时在B站自学kaungshen的Docker视频过程中,自己动手实践整理出来的,目前是对docker有了一个大致的了解。
docker的进阶,如:Docker Compose,Docker Compose,CI/CD之Jenkins等,目前
还在学习中,这里也是非常感谢kuangshen能出这么细致的教程,让我这个小白也能上手。
如果感兴趣的话可以去康康,狂神的Docker进阶篇
最后
以上就是敏感悟空为你收集整理的Docker学习笔记Doker概述Docker安装Docker镜像容器数据卷初始DockerFileDocker网络SpringBoot微服务打包Docker镜像总结的全部内容,希望文章能够帮你解决Docker学习笔记Doker概述Docker安装Docker镜像容器数据卷初始DockerFileDocker网络SpringBoot微服务打包Docker镜像总结所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复