Docker笔记基础
" 不能只停留run 开端口 "
1. Docker的组成
通过镜像模板创建容器服务 ==> run ==> 可创建多个容器(集群建设)
可独立运行一组或一组应用程序的镜像虚拟化对象。start stop rm 这些基本命令
存放镜像的地方分为公共和私人仓库(类似)git)
2. Linux上安装Docker
命令行与图形用户界面之间的切换
# 默认开机进入命令行模式: sudo systemctl set-default multi-user.target # 默认进入图形用户界面: sudo systemctl set-default graphical.target
2.1 步骤介绍
# 1、Docker 要求 CentOS 系统的核心版本高于 3.10 , uname -r # 查看内核版本 # 2.删除以前的版本 sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-selinux \ docker-engine-selinux \ docker-engine # 3.所需的安装包 sudo yum install -y yum-utils device-mapper-persistent-data lvm2 # 4.配有镜像的仓库 建议阿里云 sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 5、更新yum缓存(以确保更新和下载所需的服务:例如docker) sudo yum makecache # 6、安装Docker(CE-自动下载社区版) containerd.io 和 docker-ce-cli sudo yum -y install docker-ce # 7、启动docker服务 sudo systemctl start docker docker version # 查看版本信息 docker info # 查看更详细的信息(容器和镜像数) # 8.设置动设置 sudo systemctl enable docker # 9、测试hello-world # 第一次是unable to find image 'xxx' locally ,会自动搜索Docker-Hub 并pull ,如果找不到,返回错误 docker run hello-world # 10、查看镜像 docker images # 它似乎可以简化为docker ps # 11、卸载docker的步骤 # 卸载依赖 sudo yum remove docker-ce # 删除资源 sudo rm -rf /var/lib/docker
2.2 阿里云镜像仓库加速
产品服务 -> 弹性计算 -> 容器镜像服务
# 创建文件夹 sudo mkdir -p /etc/docker # 设置加速器地址加速地址为您 sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://dsvlpgtd.mirror.aliyuncs.com"] } EOF # 重新加载配置 sudo systemctl daemon-reload # 重启docker sudo systemctl restart dcker
腾讯云也有
# 执行以下命令,打开 /etc/docker/daemon.json 配置文件
vim /etc/docker/daemon.json
# 按 i 切换至编辑模式,添加以下内容,并保存。
{
"registry-mirrors": ["https://mirror.ccs.tencentyun.com"]
}
# 重新加载配置
sudo systemctl daemon-reload
# 执行以下命令,重启 Docker 即可
sudo systemctl restart docker
2.3 底层原理
是一个CS结构的系统。
:
外面的Linux服务器是访问不到容器里的东西的,同时各个容器之间也是互相隔离的,如果互通,需要后期的配置
抽象层数比较少,新建一个容器的时候不需要像虚拟机一样重新加载一个操作系统的内核,速度会更快。
虚拟机是加载Guets OS(分钟级),Docker是利用宿主主机的系统(秒级)
2.4 常用命令
帮助文档地址 Reference documentation | Docker Documentation
# 帮助命令(万能)
docker 命令 --help # eg: docker images --help
2.4.1 镜像命令
# 1、search 搜索镜像
docker search mysql
# 可选参数(过滤)
docker search mysql --filter=STARS=3000
# 2、pull 下载镜像
docker pull mysql # 默认latest version
# image的核心:分层下载 联合文件系统 公有的下次就不用下载了,非常节省内存!!!!
# 指定版本下载(一定要在docker-hub上有)
docker pull mysql:5.7
# 3、images 查看镜像
docker images # 可选参数a(查看所有的) q(只查看ID)
# 4、remove 删除镜像
docker rmi -f 镜像id # 可以通过id或者name来指定删除
docker rmi -f ${docker images -aq}
2.4.2 容器命令
有了镜像才可以创建容器
# 1、下载一个centos
docker pull centos
# 2、启动并进入容器
docker run 镜像id
# 参数说明
--name="Name" # 容器名字 tomcat01 tomcat02 用来区分容器
-d # 后台方式运行
-it # 使用交互方式运行,进入容器查看内容
-p # 指定容器的端口 -p 8080(宿主机):8080(容器)
-p ip:主机端口:容器端口
-p 主机端口:容器端口(常用)
-p 容器端口
-P(大写) 随机指定端口
#eg:docker run -d -p 6030-6049:6030-6049 -p 6030-6049:6030-6049/udp --name tdengine tdengine/tdengine
# 可以加-d后台运行,也可以Ctrl+P+Q退出(不会停止)
# 3、列出所有运行的容器
docker ps # -a可以显示历史运行的 -q只显示id,和images的命令差不多
# 4、删除容器
docker rm 容器id # 删除指定容器
docker rm -f ${docker ps -aq}
# 5、启动和停止容器
docker start 容器id # 启动容器
docker restart 容器id # 重启容器
docker stop 容器id # 停止当前正在运行的容器
docker kill 容器id # 强制停止当前容器
exit # 容器停止并退出
Ctrl + P + Q # 容器不停止并退出
2.4.3 其他命令
# 1、后台启动的坑
docke run -d centos
# 当docker ps 的时候发现没有被启动
# 后台运行必须要有前台进程,否则会自动停止
docker run -d centos /bin/bash
# 2、logs日志命令
# 先运行一个新的容器,刚才那个centos,我们可以结束掉,
docker stop centos容器的id
# 编写一段shell脚本 每1秒输出一次xiaowei
docker run -d centos /bin/sh -c "while true;do echo xiaowei;sleep 1;done" # 小写的c
# 查看一下运行的容器
docker ps
# 显示日志
docker logs -tf --tail 10 centos容器的id # 必须要加参数10,显示10条记录数
# 3、查看容器中的进程信息
docker top 容器id
# 4、查看容器的元数据
docker inspect 容器id
# 5、进入当前正在运行的容器
docker exec -it 容器id bash # 开启一个新的终端
docker attach 容器id # 进入容器正在执行的终端,不会启动新的进程
# 6、容器内部文件拷贝到主机上
docker cp 容器id:容器内路径 容器外
# 在centos容器里面home目录下新建一个test.txt
docker attach 容器id
cd /home
touch test.txt
# exit 退出到宿主机
docker ps
# 虽然容器停止了,但并不影响我们拷贝文件
docker cp 容器id:/home/test.txt /home
# ls 查看
2.5 实践
2.5.1 安装nginx(端口映射)
# 1、去官网搜索nginx
# 2、拉取镜像
docker pull nginx
# 3、后台创建并启动容器
docker run -d --name nginx01 -p 3001:80 nginx
# -p 3001是外网的端口 80是nginx的默认的端口 这是个映射的概念
# 4、打开端口
firewall-cmd --zone=public --add-port=3001/tcp --permanent
firewall-cmd --reload
# 5、运行测试
curl localhost:3001
# 宿主机也是可以访问的
# 6、停止容器,就访问不到了
docker stop nginx01
2.5.2 安装tomcat(有坑)
# 1、用完即删 --rm (不建议)
docker run -it --rm tomcat:9.0
# 2、拉取镜像(刚才已经下了)
docker pull tomcat:9.0
# 3、后台创建并启动容器
docker run -d --name tomcat01 -p 4001:8080 tomcat:9.0
# 测试访问正常,但没有页面,因为命令被减了,没有webapps、默认最小的镜像,只保证可运行
# 进入容器内部
docker run -d --name tomcat01 -p 4001:8080 tomcat:9.0
# 拷贝文件到webapps
cp -r webapps.dist/* webapps
# 测试访问就正常了
2.5.3 问题小结Note
查看内存占用情况 docker stats
不能每次部署项目都需要重新进入容器吧,很麻烦,
我们可以在容器外部提供一个映射路径,在外部部署项目,自动同步到内部,用到的概念
--rm
是用完即删
2.6 可视化
使用Portainer图形化界面管理工具,提供后台面板操作
docker run -d -p 5001:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
# 记得开端口,重新加载防火墙
3. Docker镜像讲解
3.1 镜像是什么
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,包含运行某个软件所需的所有内容,包括代码、运行时库、环境变量和配置文件。
所有应用,直接打包docker镜像,就可以直接跑起来!
3.2 Docker镜像加载原理
UnionFs(联合文件系统):Union文件系统(UnionFs)是一种、轻量级并且高性能的文件系统,支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。Union文件系统是 Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像 :一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
docker的镜像实际上由的文件系统组成,这种层级的文件系统UnionFS。 boots(boot file system)主要包含 bootloader和 Kernel, bootloader主要是引导加 kernel, Linux刚启动时会加bootfs文件系统,在 Docker镜像的最底层是 boots。这一层与我们典型的Linux/Unix系统是一样的,包含boot加載器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由 bootfs转交给内核,此时系统也会卸载bootfs。 rootfs(root file system),在 bootfs之上。包含的就是典型 Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。 rootfs就是各种不同的操作系统发行版,比如 Ubuntu, Centos等等。
对于个精简的OS,rootfs可以很小,只需要包合最基本的命令,工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的Linux发行版, boots基本是一致的, rootfs会有差別,因此不同的发行版可以公用bootfs.
3.3 分层理解
最大的好处,我觉得莫过于资源共享了!比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。
3.4 commit镜像
就拿刚才的tomcat来练,修改好webapps之后
docker commit -a="xiaowei" -m="add webapps applications" 容器id tomcat02:1.0
docker images # 即可查看到
这个类似于VMware的快照
4. 容器数据卷
4.1 问题提出
回到上面提的问题
不能每次部署项目都需要重新进入容器吧,很麻烦,我们可以在容器外部提供一个映射路径,在外部部署项目,自动同步到内部,用到的概念
抛出一个问题
如果数据都在容器中,那删除容器,数据都会丢失,但是需要数据可以持久化,比如MySQL的数据,让数据存储在本地,就要使用到,使容器之间有一个数据共享的技术!
目录挂载,挂载到Linux上
4.2 使用数据卷
4.2.1 Centos测试文件关联
-v, --volume list Bind mount a volume
docker run -it -v 主机目录:容器内目录 -p 主机端口:容器内端口
/home/ceshi:主机home目录下的ceshi文件夹 映射:centos容器中的/home
docker run -it -v /home/ceshi:/home centos /bin/bash
# 这时候主机的/home/ceshi文件夹就和容器的/home文件夹关联了,二者可以实现文件或数据同步了
# 通过 docker inspect 容器id 查看
docker inspect 6064c490c371
继续测试
停止容器 --> 宿主机修改文件 --> 启动容器 --> 容器内的数据依旧是同步的
4.2.2 测试MySQL
# 1、镜像拉取
# 2、创建并运行容器
docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
firewall-cmd --zone=public --add-port=3310/tcp --permanent
firewall-cmd --reload
# 3、Navicat测试成功 vm1:3310
# 4、本地测试创建一个数据库test,在linux中home/mysql/data中可以看到
就算容器删除,docker rm -f mysql01,数据也不会丢失,即容器数据卷技术
4.2.3 测试一个TDengine(待测)
docker run -d -p 6030-6049:6030-6049 -p 6030-6049:6030-6049/udp -v td1:/etc/taos --name td1 tdengine/tdengine
这种是具名挂载,不指定目录,会在本机统一的一个目录,里面有taos.cfg 但是修改了FQDN之后就启动不了TDengine了,原因是它默认的FQDN是该容器id,不一致启动不了,而且在创建并run这个TDengine容器的时候,没有提示输入集群点
4.3 具名挂载
# 具名挂载 -P:表示随机映射端口
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
9663cfcb1e5a9a1548867481bfddab9fd7824a6dc4c778bf438a040fe891f0ee
# 查看所有的volume(卷)的情况
$ docker volume ls
DRIVER VOLUME NAME
local 21159a8518abd468728cdbe8594a75b204a10c26be6c36090cde1ee88965f0d0
local b17f52d38f528893dd5720899f555caf22b31bf50b0680e7c6d5431dbda2802c
local juming-nginx #多了一个名字
# 通过 -v 卷名:查看容器内路径
# 查看一下这个卷
$ docker volume inspect juming-nginx
[
{
"CreatedAt": "2020-05-23T13:55:34+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data", #默认目录
"Name": "juming-nginx",
"Options": null,
"Scope": "local"
}
]
4.3.1 三种挂载方式
# 三种挂载: 匿名挂载、具名挂载、指定路径挂载
-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载
-v /宿主机路径:容器内路径 # 指定路径挂载 docker volume ls 是查看不到的
所有的docker容器内的卷,没有指定目录的情况下都是在**/var/lib/docker/volumes/自定义的卷名/_data**下, 如果指定了目录,docker volume ls 是查看不到的
4.3.2 拓展
# 通过 -v 容器内路径: ro rw 改变读写权限
ro #readonly 只读
rw #readwrite 可读可写
$ docker run -d -P --name nginx05 -v juming:/etc/nginx:ro nginx
$ docker run -d -P --name nginx05 -v juming:/etc/nginx:rw nginx
# ro 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作!
4.4 数据卷容器
!命令脚本!
通过这个,镜像是一层一层的,脚本是一个个的命令,每个命令都是一层!
4.4.1 通过脚本生成镜像
# 创建一个dockerfile文件,名字可以随便 建议Dockerfile
# 文件中的内容: 指令(大写) + 参数
$ vim home/docker-test-volume/dockerfile1
FROM centos # 当前这个镜像是以centos为基础的
VOLUME ["volume01","volume02"] # 挂载卷的卷目录列表(多个目录)
CMD echo "-----end-----" # 输出一下用于测试
CMD /bin/bash # 默认走bash控制台
# 这里的每个命令,就是镜像的一层!
# 构建出这个镜像
-f home/docker-test-volume/dockerfile1 # f代表file,指这个当前文件的地址
-t xw/centos # t就代表target,指目标目录(注意xw镜像名前不能加斜杠‘/’)
. # 表示生成在当前目录下
$ docker build -f home/docker-test-volume/dockerfile1 -t xw/centos .
Sending build context to Docker daemon 2.56kB
Step 1/4 : FROM centos
latest: Pulling from library/centos
8a29a15cefae: Already exists
Digest: sha256:fe8d824220415eed5477b63addf40fb06c3b049404242b31982106ac204f6700
Status: Downloaded newer image for centos:latest
---> 470671670cac
Step 2/4 : VOLUME ["volume01","volume02"] # 卷名列表
---> Running in c18eefc2c233
Removing intermediate container c18eefc2c233
---> 623ae1d40fb8
Step 3/4 : CMD echo "-----end-----" # 输出 脚本命令
---> Running in 70e403669f3c
Removing intermediate container 70e403669f3c
---> 0eba1989c4e6
Step 4/4 : CMD /bin/bash
---> Running in 4342feb3a05b
Removing intermediate container 4342feb3a05b
---> f4a6b0d4d948
Successfully built f4a6b0d4d948
Successfully tagged caoshipeng/centos:latest
# 查看自己构建的镜像
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
xw/centos latest f4a6b0d4d948 About a minute ago 237MB
进入这个容器之后ls
前面有个卷挂载
VOLUME [“volume01”,“volume02”]
# docker inspect 容器id
docker inspect ca3b45913df5
4.4.2 测试Centos
父容器的概念 --volumes-from
# 测试 启动3个容器,通过刚才的镜像启动
# 创建docker01
$ docker run -it --name docker01 xw/centos
# 查看容器docekr01内容
$ ls
bin home lost+found opt run sys var
dev lib media proc sbin tmp volume01
etc lib64 mnt root srv usr volume02
# 不关闭该容器退出
CTRL + Q + P
# 创建docker02: 并且让docker02 继承 docker01
$ docker run -it --name docker02 --volumes-from docker01 xw/centos
# 查看容器docker02内容
$ ls
bin home lost+found opt run sys var
dev lib media proc sbin tmp volume01
etc lib64 mnt root srv usr volume02
多个容器之间的数据是拷贝的
# 测试:可以删除docker01,查看一下docker02和docker03是否可以访问这个文件
# 测试发现:数据依旧保留在docker02和docker03中没有被删除
4.4.3 多个mysql实现数据共享
$ 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=123456 --name mysql01 mysql:5.7
$ docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7
# 这个时候,可以实现两个容器数据同步!
结论:
。
!
5. DockerFile
5.1 构建步骤
1、 编写一个dockerfile文件
2、 docker build 构建成为一个镜像
3、 docker run运行镜像
4、 docker push发布镜像(DockerHub 、阿里云仓库)
很多官方镜像都是基础包,很多功能没有,我们通常会自己搭建自己的镜像!
5.2 构建过程
基础知识:
1、每个保留关键字(指令)都是必须是大写字母
2、执行从上到下顺序
3、每一个指令都会创建提交一个新的镜像层,并提交!
5.3 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:构建的时候设置环境变量!
创建一个自己的centos
# 1./home下新建dockerfile目录
$ mkdir dockerfile
# 2. dockerfile目录下新建mydockerfile-centos文件
$ vim mydockerfile-centos
# 3.编写Dockerfile配置文件
FROM centos:7 # 基础镜像是官方原生的centos7,记得指定版本号,不然报错
MAINTAINER xiaowei<1437591651@qq.com> # 作者
ENV MYPATH /usr/local # 配置环境变量的目录
WORKDIR $MYPATH # 将工作目录设置为 MYPATH
RUN yum -y install vim # 给官方原生的centos 增加 vim指令
RUN yum -y install net-tools # 给官方原生的centos 增加 ifconfig命令
EXPOSE 80 # 暴露端口号为80
CMD echo $MYPATH # 输出下 MYPATH 路径
CMD echo "-----构建成功-----"
CMD /bin/bash # 启动后进入 /bin/bash
# 4.通过这个文件构建镜像
# 命令: docker build -f 文件路径 -t 镜像名:[tag] .
$ docker build -f mydockerfile-centos -t mycentos . # 千万记住最后这个.
# 5.出现以下则构建成功
Successfully built 8b56fe496ff7
Successfully tagged mycentos:latest
成功创建并进入容器
docker history 镜像id # 查看镜像构建历史步骤
CMD 和 ENTRYPOINT区别
CMD # cmd:指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # entrypoint:指定这个容器启动的时候要运行的命令,可以追加命令
5.4 实战:Tomcat镜像 Fail
准备tomcat和jdk的tar包,放到home/cestbon/tomcat下备用,创建一个readme.txt
vim dockerfile
FROM centos:7
MAINTAINER xiaowei<1437591651@qq.com>
COPY readme.txt /usr/local/readme.txt
ADD jdk-8u333-linux-x64.tar.gz /usr/local
ADD apache-tomcat-9.0.64-deployer.tar.gz /usr/local
RUN yum -y install vim
ENV MYPATH /usr/local
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8.0_333
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.64
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.64
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-9.0.64/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.64/logs/catalina.out
构建镜像
docker build -t diytomcat . # 因为我们的那个文件就是dockerfile所以不需要-f指明文件
docker run -d -p 9090:8080 --name xwtomcat -v /home/cestbon/build/tomcat/test:/usr/local/apache-tomcat-9.0.64/webapps/test -v /home/cestbon/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.64/logs diytomcat
PS: 貌似出现了问题
5.5 push镜像
发布到docker - hub
# 登录
$ 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
$ docker login -u 你的用户名 -p 你的密码
# push不上去,因为如果没有前缀的话默认是push到 官方的library
# 解决方法:
# build的时候添加你的dockerhub用户名,然后在push就可以放到自己的仓库了
$ docker build -t xw1437591651/mytomcat:1.0 .
$ docker push xw1437591651/mytomcat:1.0
发布到阿里云上
官网很详细的步骤
$ sudo docker login --username=xxx registry.cn-shenzhen.aliyuncs.com
$ sudo docker tag [ImageId] registry.cn-shenzhen.aliyuncs.com/dsadxzc/xw:[镜像版本号]
# 修改id 和 版本
sudo docker tag a5ef1f32aaae registry.cn-shenzhen.aliyuncs.com/dsadxzc/xw:1.0
# 修改版本
$ sudo docker push registry.cn-shenzhen.aliyuncs.com/dsadxzc/xw:[镜像版本号]
6. Docker网络
6.1 测试两个tomcat
1、清除之前的镜像和容器
# 删容器
[root@vm1 /]# docker rm -f $(docker ps -aq)
3175611d31b2
a88696c1b79a
5d7b213c9400
6718f7cd0132
82d1622e2c66
# 删镜像
[root@vm1 /]# docker rmi $(docker images -aq)
Untagged: diytomcat:latest
Deleted: sha256:146a61c5be3e63763087289bcff44b42439c3df9099194797c7beaf56a70db16
Deleted: sha256:2569c5a6ecdc1c02e23640d79e1677b9d4a4b2dd5548faea4780c1fe7b7184bb
Deleted: sha256:a535f16fa183af8cf5837ce0690383569f2ee7dc6016a17e436190ce7d2080b2
Deleted: sha256:1636e876cf8889ae2f4d00f60bc778bee92315af648c7113ab798a9bab85af5d
Deleted: sha256:995a5eece07c0ffb88177cc2932765f237452a53e01f02eed3b40d8ac5d6f9b7
# 完毕
[root@vm1 /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
[root@vm1 /]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2、创建启动一个tomcat容器tomcat01
创建之前查看当前的ip 信息 ip addr
# 创建容器
docker run -d -P --name tomcat01 tomcat
# 再次查看ip addr
# 进入容器tomcat01查看ip addr (如果报错没有ip指令)
# 执行如下命令
apt update
apt install -y iproute2
# 查看ip (若报错,章节末有解决办法)
root@6936e1963a31:/usr/local/tomcat# ip a
......
12: eth0@if13: <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 # 可以看到172.17.0.2
# 虚拟机ping容器
[root@vm1 /]# 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.043 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.044 ms
3、再启动一个tomcat02
[root@vm1 /]# docker run -d -P --name tomcat02 tomcat:9.0
190d8f40845ab89341e94d4b76415905e9cee49b3ffca2d742ae8f25dfca9533
# 可以看到两对(12:13 14:15)
13: veth70da156@if12: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether c6:e8:18:05:f4:5d brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::c4e8:18ff:fe05:f45d/64 scope link
valid_lft forever preferred_lft forever
15: veth3bdcb93@if14: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether e6:a6:2c:d8:5d:8f brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::e4a6:2cff:fed8:5d8f/64 scope link
valid_lft forever preferred_lft forever
# 进入容器tomcat02
docker exec -it tomcat02 bash
apt update
apt install -y iproute2
root@190d8f40845a:/usr/local/tomcat# ip a
......
14: eth0@if15: <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 # 可以看到172.17.0.3
4、测试容器互通
我们来测试下tomcat01和tomcat02是否可以ping通
# (若报错,章节末有解决办法)
[root@vm1 /]# docker exec -it tomcat01 ping 172.17.0.3
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.053 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.052 ms
6.2 原理
我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个docker0桥接模式,使用的技术是veth-pair技术!
veth-pair 就是一对的虚拟设备接口,它都是成对出现的。一端连着协议栈,一端彼此相连。 正因为有这个特性 veth-pair 充当一个桥梁,连接各种虚拟网络设备的。
:
6.3 需求变化
思考一个场景:我们编写了一个微服务,database url=ip: 项目不重启,数据ip换了,我们希望可以处理这个问题,可以?
比如:docker exec -it tomcat02 ping tomca01 # ping不通
两种解决办法
6.3.1 --link解决(不建议)
# 通过--link来解决(只能正向连接)(不建议使用)
docker run -d -P --name tomcat03 --link tomcat02 tomcat:9.0
# 默认你tomcat有ping命令
[root@vm1 /]# 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.068 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.096 ms
docker exec -it tomcat02 ping tomcat03 # 失败,不能反向ping,下面看原理探究
:
通过网卡信息来看
[root@vm1 /]# docker network ls
NETWORK ID NAME DRIVER SCOPE
8d890099890e bridge bridge local
84bce780a9bf host host local
# 可以通过docker network inspect 网络id 看信息
docker network inspect 8d890099890e
# 看这个部分(删掉了EndpointID和MacAddress)
"Containers": {
"190d8f40845ab89341e94d4b76415905e9cee49b3ffca2d742ae8f25dfca9533": {
"Name": "tomcat02",
"IPv4Address": "172.17.0.3/16",
},
"6936e1963a31e6900586cb7fb740fa0ad4d83362b8109df1df76a106b2345348": {
"Name": "tomcat01",
"IPv4Address": "172.17.0.2/16",
},
"78bbf798a98e4cfef615b7d81e69052223d846f0ac3b91f321a4c487b3ab1eb8": {
"Name": "tomcat03",
"IPv4Address": "172.17.0.4/16",
}
}
通过容器的hosts查看
[root@vm1 /]# docker exec -it tomcat03 cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
172.17.0.3 tomcat02 190d8f40845a # 这里
172.17.0.4 78bbf798a98e
# 它是直接在hosts里写死了访问tomcat02的一个地址解析
# 但tomcat02里没有写tomcat03的,所以不能反向ping
结论:–link就是做映射,不建议使用,因为docker0不支持容器名连接访问,使用自定义网络
6.3.2 自定义网络(建议)
# 查看所有的docker网络
[root@vm1 /]# docker network ls
NETWORK ID NAME DRIVER SCOPE
8d890099890e bridge bridge local
84bce780a9bf host host local
# 网络模式
# bridge :桥接 docker(默认,自己创建也是用bridge模式)
# none :不配置网络,一般不用
# host :和所主机共享网络
# container :容器网络连通(用得少!局限很大)
# rm 之前的tomcat镜像容器
创建自己的网络 mynet
# 创建一个桥接模式的网络,网关是192.168.0.1,范围是192.168.0.2-192.168.255.254 docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet [root@vm1 /]# docker network ls NETWORK ID NAME DRIVER SCOPE 8d890099890e bridge bridge local 84bce780a9bf host host local 5d56908490f8 mynet bridge local # 依据刚才的mynet创建两个tomcat容器 docker run -d -P --name tomcat01 --net mynet tomcat docker run -d -P --name tomcat02 --net mynet tomcat # 查看这个网络信息 docker network inspect mynet "Containers" 标签:
068连接器