docker系列
docker基础
dockers为什么会出现
开发-----运维。问题:我在我电脑上可以运行!版本更新,导致服务不可用!所以对运维来说考验就十分大。环境配置时十分麻烦的,每一个机器都要部署环境(集群Redis,ES,Hadoop…)费时费力。
所以发布一个项目能不能都带上环境安装打包! windows的东西到Linux上也能用。
传统:开发jar,运维来给电脑配置环境。
现在:开发打包部署上线,一套流程做完。
例如:手机的应用游戏
java ------做成apk—然后发布到(应用商店)—张三使用apk----安装即可用。
那么: 举个docker的例子
Java —jar(环境)----打包项目带上环境(镜像)----(然后放到Docker仓库:商店)—别人下载我们发布的镜像-------直接运行即可
docker的核心思想:
docker的思想来自于集装箱。隔离:docker的核心思想!打包装箱!每个箱子(容器)是互相隔离的。
docker通过隔离机制,可以将服务器利用到机制!
docker的历史:
dotcloud公司开发感觉虚拟机笨重,所以开发了docker,后来因为没有引起行业注意,就活不下去!所以开放源代码。docker越来越多的人发现了docker的优点!火了!docekr为什么会这么火呢?
虚拟机:在Windows中装一个VMware, 隔离,需要开启多个虚拟机! 占用内存至少几个G。启动要几分钟
docker:隔离,镜像(最核心的环境 4m+jdk+mysql)十分小巧,只运行镜像就可以了, 占用内存几个M,多说也就是几百M。秒及启动。
docker是什么语言开发的,docker官网
docker是基于GO语言开发的。docker官方网址:https://www.docker.com/
docker仓库网址:https://hub.docker.com/
docker能做什么
虚拟机: 模拟的一个完整的操作系统。
虚拟机技术缺点:
1,资源占用十分多
2.启动很慢
3.一个地方出错,可能导致全盘出错。
容器化技术
容器化技术不是模拟的一个完整的操作系统
比较docker和虚拟机技术的不同:
传统虚拟机,虚拟出一条硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件。容器内的应用直接运行在宿主机,容器没有自己的内核,也没有虚拟硬件,所以就轻便了。
每个容器间是互相隔离,每个容器内都有一个属于自己的文件系统,互不影响。
DevOps(开发、运维) ,(docker相比于虚拟机的优点)
**1.应用更快速的交付和部署**传统:一堆帮助文档,安装程序
Docker:打包镜像发布测试,一键运行
2.更快捷的升级和扩缩容
使用docker,将应用打包成镜像后,服务器A坏掉了,所以服务器B要接替运行,此时直接将镜像,放到服务器B上,直接运行就行了
项目要升级了,需要升级环境(redis5 romcat 8 …),学docker之前需要一个一个的将环境升级。学docker之后,只要将这些环境打包,然后整体升级。
3.更简单的系统运维
在容器化之后,docker把应用程序和它所需要的环境锁死在一起。然后运维人员就不用管环境配置了。所以系统变得简单和高效。

4.更高效的计算资源利用
docker是内核级别的虚拟化,可以在一个物理机上运行很多的容器实例!服务器的性能可以被压缩到极致。
docker的基本组成
镜像(image):
docker镜像就像一个模板,可以通过这个模板来创建容器服务,tomcat镜像==>docker run==>romcat01容器,通过镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)。
容器(container):
docker利用容器技术,独立运行一个或者一个组应用,通过镜像来创建的。
启动、停止、删除,基本命令!
可以简单将容器理解为一个简易的Linux系统
仓库(repository):
仓库就是放存放镜像的地方。
分为共有仓库和私有仓库。
docker hub (默认是国外的)。
阿里云…都有容器服务(配置镜像加速!)
docker学习步骤:
概述------>安装命令(镜像、容器、操作)等
docker镜像----->容器数据卷
dockerfile------>docker网络原理
IDA整合docker----->docker Compose ------>docker Swarm------> CI\CD Jenkins
安装docker和配置阿里云加速器
Linux查看当前版本命令 [root@han ~]# cat /etc/os-release
docke安装
1.卸载docker旧的版本
sudo yum remove -y docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine \
2.安装docker,需要的安装包
yum install -y yum-utils
3.设置镜像源的仓库
yum-config-manager --add-repo https://repo.huaweicloud.com/docker-ce/linux/centos/docker-ce.repo
4.安装docker相关的 docker-ce 社区 ee企业版
yum install docker-ce docker-ce-cli containerd.io
临时禁用GPG验证:
sudo yum install -y docker-ce docker-ce-cli containerd.io --nogpgcheck
5.启动docker
[root@han ~]# systemctl start docker
然后使用docker version查看是否安装成功
7. 使用 docker run 拉取 hello-world镜像
## /var/lib/docker 是docker的默认工作路径!
然后查看下载的hello-world镜像

Run的流程和Docker原理
docker run的流程图:
docker底层原理:
docker是一个Client -Server 结构的系统,Docker的命令进程运行在主机(服务器)上。通过Socket从客户端访问! Dockerserver 接收到Docker-Client的指令,就会执行这个命令!

Docker为什么比VM快?
1.docker 有着比虚拟机更少的抽象层。
2.docker利用的是宿主机的内核,vm需要的是 guest os (操作系统)

新建一个容器的时候,docker不需要像虚拟机一样重新加载一个操作系统内核。
虚拟机是加载Guest OS(内核),分钟级别。
docker是利用宿主机的操作系统,省略了这个复杂的过程,秒级。
Docker常用命令
```plain docker version 查看docker的版本信息 docker info #显示docker的系统信息,包括镜像和容器的数量 docker 命令 --help #万能命令
<h3 id="rJHjc">镜像命令:</h3>
docker images
```xml
[root@han docker]# docker images 命令
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest ad5708199ec7 3 weeks ago 192MB
#解释
REPOSITORY 镜像的仓库源
TAG 镜像标签
IMAGE 镜像的id
CREATED 镜像的创建时间
SIZE 镜像的大小
#可选项
-a, --all Show all images (显示所有镜像)
-q, --quiet Only show image IDs(只显示镜像的id)
[root@han docker]# docker search mysql 命令
NAME DESCRIPTION STARS OFFICIAL
mysql MySQL is a widely used, open-source relation… 15904 [OK]
bitnami/mysql Bitnami container image for MySQL 141
circleci/mysql MySQL is a widely used, open-source relation… 32
root@han docker]# docker search mysql --filter=STARS=5000 搜索STARS大于5000的
NAME DESCRIPTION STARS OFFICIAL
mysql MySQL is a widely used, open-source relation… 15904 [OK]
[root@han docker]# docker pull mysql 命令 docker pull 【镜像名】
Using default tag: latest #如果不写tag,默认就是 latest(最新版)
latest: Pulling from library/mysql
500d7b2546c4: Pull complete #分层下载,docker image的核心 联合文件系统
fc5138e88017: Pull complete
b534c7c08c95: Pull complete
5525b1bd2d5d: Pull complete
9effc86d91a3: Pull complete
a1bcea418c7c: Pull complete
fc3e1c37f699: Pull complete
30e3c68e682c: Pull complete
50786f9db9d5: Pull complete
4ea0fa0ace0c: Pull complete
Digest: sha256:439bfb4044dc59ade76c4e5c4065c02e5ba4d4007db32c40ac58d55c03069916 #签名(可以验证是否是官方正版)
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest #真实地址
docker pull mysql 等价于 docker pull docker.io/library/mysql:latest
[root@han docker]# docker pull mysql:5.7 指定下载版本为5.7
5.7: Pulling from library/mysql
20e4dcae4c69: Pull complete
1c56c3d4ce74: Pull complete
e9f03a1c24ce: Pull complete
68c3898c2015: Pull complete
6b95a940e7b6: Pull complete
90986bb8de6e: Pull complete
ae71319cb779: Pull complete
ffc89e9dfd88: Pull complete
43d05e938198: Pull complete
064b2d298fba: Pull complete
df9a4d85569b: Pull complete
Digest: sha256:4bc6bc963e6d8443453676cae56536f4b8156d78bae03c0145cbe47c2aad73bb
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
dockek rmi -f 【可以是镜像ID】 命令
[root@han docker]# docker rmi -f 1b44b5a3e06a ID可以是前几位数字,只要不和别的镜像前几位数字相同就行。
dockek rmi -f 【镜像ID】【镜像ID】 【镜像ID】【镜像ID】 删除多个镜像
docker rmi -f $(docker images -aq ) 删除全部的容器
-q选项让 docker images命令只输出所有镜像的 ID。这些纯净的 ID 被顺利地传递给 docker rmi -f命令,从而正确删除所有镜像
容器命令:
说明:有了镜像之后才能创建容器,Linux,下载一个centos镜像来测试学习。新建容器并启动:
docker run [可选参数] image 命令
#参数说明
--name="Name" 容器的名字,用来区分容器
-d 后台方式运行
-it 使用交互方式运行,进入容器查看内容
-p(小写) 指定容器的端口 -p 8080:8080
-p ip:主机端口:容器端口
-p 主机端口:容器端口(常用)
-p 容器端口
-P(大写) 随即指定端口
[root@han docker]# docker run -it centos /bin/bash 进入容器内部
[root@d6e373f7b880 /]# ls #查看容器内部的centos,基础版本,很多命令都是不完善的。
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@d6e373f7b880 /]# exit 在容器中退回主机
exit
[root@han docker]# docker ps #查看当前正在运行的容器
-a #查看当前所有的容器 (正在运行的+历史运行过的)
docker ps -aq 显示当前所有容器的id号
ctrl +p +q 在容器内部推出,但是不停止运行容器
docker rm(容器id) #删除容器命令,不能删除正在运行的命令
[root@han ~]# docker rm -f $(docker ps -aq) #强制删除所有容器
237e6d1fdf0b
c22e9fda9b6b
265e75567e7e
f0a53883cae9
docker ps -aq | xargs docker rm #删除所有容器
启动和停止容器:
docker start 容器id #启动容器
docker restart 容器id #重启容器
docker stop 容器id #停止当前正在运行的容器
docker kill 容器id #强制停止当前容器
docker ps -aq | xargs docker rm #删除所有容器

常用其他命令
后台启动命令
```shell #后台启动容器 dcoker run -d 镜像名 [root@han ~]# docker run -d centos #问题docker ps ,发现centos停止了 #常见的坑,docker 容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止 #例如 nginx,容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了 所以要加上 -it ```查看日志
```shell docker logs #查看日志命令 docker logs -f -t --tail 行数 镜像名 #-f是follow(跟踪) -t 是timestamps(时间戳) --tail(显示行数) #-ft 持续显示日志 --tail number 显示日志的条数 [root@han ~] docker run -d centos /bin/bash -c "while true;do echo kuangshen;sleep 1;done" #这条命令的含义是在后台启动一个基于 centos镜像的 Docker 容器,并让这个容器每隔 1 秒无限循环打印"kuanshen" #在 Docker 命令中尝试执行一个 while循环但没有正确使用 done关键字来结束循环时,Shell 会认为命令语法不完整或错误,从而导致容器启动失败。 [root@han ~]# docker logs -ft --tail 10 reverent_stonebraker 实时查看 reverent_stonebraker 这个容器的日志,最开始显示容器日志已经产生的最后10行,并持续跟踪 ```查看容器中的信息
```shell docker top 容器id #显示容器的基本信息 [root@han ~]# docker top pensive_clarke UID PID PPID C STIME TTY TIME CMD root 14092 14072 0 13:35 ? 00:00:00 /bin/bash -c while true;do echo kuangshen;sleep 1;done root 17262 14092 0 14:01 #UID 就是当前的用户id #PID就是进程ID ```删除容器或镜像命令
```shell 删除所有容器命令 $(...)命令替换:先执行 ...里的命令,并将其标准输出结果替换到 $()所在的位 [root@han home]# docker rm -f $(docker ps -aq ) b0d44ad624bd b4d459a82b65 98dfa82ab43c#删除所有镜像命令
[root@han home]# docker rmi -f $(docker images -aq)
<h4 id="cUUzS">查看镜像的元数据</h4>
```shell
#docker inspect 容器id 命令
[root@han ~] docker inspect pensive_clarke
[
{
"Id": "10acd9ea6bbdb20a4a69714895a8b751f3ea08c71c69dbad604d3d8b7f04366c",
"Created": "2025-09-05T05:35:05.231299504Z",
"Path": "/bin/bash",
"Args": [
"-c",
"while true;do echo kuangshen;sleep 1;done"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 14092,
"ExitCode": 0,
"Error": "",
"StartedAt": "2025-09-05T05:35:05.410753468Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6",
"ResolvConfPath": "/var/lib/docker/containers/10acd9ea6bbdb20a4a69714895a8b751f3ea08c71c69dbad604d3d8b7f04366c/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/10acd9ea6bbdb20a4a69714895a8b751f3ea08c71c69dbad604d3d8b7f04366c/hostname",
"HostsPath": "/var/lib/docker/containers/10acd9ea6bbdb20a4a69714895a8b751f3ea08c71c69dbad604d3d8b7f04366c/hosts",
"LogPath": "/var/lib/docker/containers/10acd9ea6bbdb20a4a69714895a8b751f3ea08c71c69dbad604d3d8b7f04366c/10acd9ea6bbdb20a4a69714895a8b751f3ea08c71c69dbad604d3d8b7f04366c-json.log",
"Name": "/pensive_clarke",
"RestartCount": 0,
"Driver": "overlay2",
"Platform": "linux",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "",
"ExecIDs": null,
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "bridge",
"PortBindings": {},
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount": 0
},
"AutoRemove": false,
"VolumeDriver": "",
"VolumesFrom": null,
"ConsoleSize": [
16,
66
],
"CapAdd": null,
"CapDrop": null,
"CgroupnsMode": "host",
"Dns": [],
"DnsOptions": [],
"DnsSearch": [],
"ExtraHosts": null,
"GroupAdd": null,
"IpcMode": "private",
"Cgroup": "",
"Links": null,
"OomScoreAdj": 0,
"PidMode": "",
"Privileged": false,
"PublishAllPorts": false,
"ReadonlyRootfs": false,
"SecurityOpt": null,
"UTSMode": "",
"UsernsMode": "",
"ShmSize": 67108864,
"Runtime": "runc",
"Isolation": "",
"CpuShares": 0,
"Memory": 0,
"NanoCpus": 0,
"CgroupParent": "",
"BlkioWeight": 0,
"BlkioWeightDevice": [],
"BlkioDeviceReadBps": [],
"BlkioDeviceWriteBps": [],
"BlkioDeviceReadIOps": [],
"BlkioDeviceWriteIOps": [],
"CpuPeriod": 0,
"CpuQuota": 0,
"CpuRealtimePeriod": 0,
"CpuRealtimeRuntime": 0,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": [],
"DeviceCgroupRules": null,
"DeviceRequests": null,
"MemoryReservation": 0,
"MemorySwap": 0,
"MemorySwappiness": null,
"OomKillDisable": false,
"PidsLimit": null,
"Ulimits": [],
"CpuCount": 0,
"CpuPercent": 0,
"IOMaximumIOps": 0,
"IOMaximumBandwidth": 0,
"MaskedPaths": [
"/proc/asound",
"/proc/acpi",
"/proc/kcore",
"/proc/keys",
"/proc/latency_stats",
"/proc/timer_list",
"/proc/timer_stats",
"/proc/sched_debug",
"/proc/scsi",
"/sys/firmware",
"/sys/devices/virtual/powercap"
],
"ReadonlyPaths": [
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
]
},
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/f3796ec1d552b4e2ff63d4cbc5f27c56ba2a81b7f4cebce04d9bd3bf9b06ee64-init/diff:/var/lib/docker/overlay2/6cd39f895f6803196e912ef5ba0d786cff37cd93e99df0ad79c7507af44b90d9/diff",
"MergedDir": "/var/lib/docker/overlay2/f3796ec1d552b4e2ff63d4cbc5f27c56ba2a81b7f4cebce04d9bd3bf9b06ee64/merged",
"UpperDir": "/var/lib/docker/overlay2/f3796ec1d552b4e2ff63d4cbc5f27c56ba2a81b7f4cebce04d9bd3bf9b06ee64/diff",
"WorkDir": "/var/lib/docker/overlay2/f3796ec1d552b4e2ff63d4cbc5f27c56ba2a81b7f4cebce04d9bd3bf9b06ee64/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "10acd9ea6bbd",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/bash",
"-c",
"while true;do echo kuangshen;sleep 1;done"
],
"Image": "centos",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {
"org.label-schema.build-date": "20210915",
"org.label-schema.license": "GPLv2",
"org.label-schema.name": "CentOS Base Image",
"org.label-schema.schema-version": "1.0",
"org.label-schema.vendor": "CentOS"
}
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "e5da1cbbd34958ada34d3e3f6082003a28fe2017daaad0278fc4fb7fb6cc125c",
"SandboxKey": "/var/run/docker/netns/e5da1cbbd349",
"Ports": {},
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "4d63961484ee4e5a053f23e7fe06443703c30236b0a1df7174fc8a5c59110c27",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:02",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"MacAddress": "02:42:ac:11:00:02",
"NetworkID": "1e8e4be7503a0f7d8a36b896289267dad207431ce7ec0da7e1414126a7bbf83e",
"EndpointID": "4d63961484ee4e5a053f23e7fe06443703c30236b0a1df7174fc8a5c59110c27",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"DriverOpts": null,
"DNSNames": null
}
}
}
}
]
[root@han ~]#
进入当前正在运行的容器
```shell #容器通常都是后台运行的,此时需要进入容器,修改一些命令 #命令 docker exec 进入正在运行的容器 [root@han ~] docker exec -it pensive_clarke /bin/bash[root@han ~] docker exec -it pensive_clarke /bin/bash
[root@10acd9ea6bbd /] ls
bin etc lib lost+found mnt proc run srv tmp var
dev home lib64 media opt root sbin sys usr
[root@10acd9ea6bbd /] ps -ef #ps -ef 用于查看当前系统中所有正在运行的进程的详细信息
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 05:35 ? 00:00:01 /bin/bash -c while true;do echo kuangshen;sleep 1;done
root 2752 0 0 06:20 pts/0 00:00:00 /bin/bash
root 2782 1 0 06:20 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bi
root 2783 2752 0 06:20 pts/0 00:00:00 ps -ef
方式二
[root@han ~]# docker attach pensive_clarke
kuangshen
kuangshen
kuangshen
…(正在执行当前代码)
#docker exec 进入容器后开启一个新的终端,可以在里面操作(常用)
#docker attach 进入容器正在执行的终端,不会启动新的进程
<h4 id="pKL0w">从容器内拷贝文件到主机上)</h4>
```shell
docker cp 容器id:文件路径 主机路径 #不用管容器是否正在运行,因为数据一直在,所以直接复制就行
[root@han ~] docker exec -it pensive_clarke /bin/bash
[root@10acd9ea6bbd /] ls #查看当前目录
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@10acd9ea6bbd /] touch kuangshen #创建kuangshen文件
[root@10acd9ea6bbd /] ls
bin dev etc home kuangshen lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@10acd9ea6bbd /] exit #退出该容器
exit #不能再容器内部实现docker cp 因为容器内部没有docker相关的命令,里面只是一些基础命令
[root@han ~]#
[root@han ~] docker cp 10acd9ea6bbd:/kuangshen / #将id为10acd9ea6bbd的容器在/kuangshen目录上,复制到容器外(主机的目录/下)
Successfully copied 1.54kB to /
[root@han ~] ls /
bin boot dev etc home kuangshen lib lib64 media mnt opt proc root run sbin srv sys tmp usr var

docker进阶
视化(web管理docker界面)
```shell docker run -d -p 9000:9000 -p 8000:8000 --name portainer --restart=always \ -v /var/run/docker.sock:/var/run/docker.sock \ -v portainer_data:/data \ portainer/portainer-ce ```Rancher(CI/CD再用)
搭建私有镜像仓库
```shell #拉取私有仓库镜像 docker pull registry:2 #启动这个私有仓库的服务 docker run -d --name registry -p 5000:5000 registry:2#给镜像添加标签,只有打上私有仓库地址的镜像才能上传到私有仓库
[root@han ~]# docker tag tomcat:latest 127.0.0.1:5000/tomcat:latest
#上传本地已经有的私有仓库地址
[root@han ~]# docker push 127.0.0.1:5000/tomcat:latest
The push refers to repository [127.0.0.1:5000/tomcat]
5f70bf18a086: Layer already exists
52ea43ee2fac: Layer already exists
9503b0d63d4e: Layer already exists
050d3ba63b63: Layer already exists
e3bea14ded36: Layer already exists
304ae9dcf6df: Layer already exists
6844f4c89beb: Layer already exists
9d592720ced4: Layer already exists
latest: digest: sha256:655257db19fcaa9e2ffaee57d3df4936fad6f02da47a1a0587d8f4ce78216c94 size: 2201
#curl 看一下是否存在
[root@han ~]# curl http://192.168.12.44:5000/v2/_catalog
{“repositories”:[“tomcat”]}
#在 Docker Registry 的 RESTful API 中,
#/v2/_catalog 是一个特定的 API 端点(Endpoint)
#用于列出当前 Docker Registry 中所有可用的镜像仓库(Repositories)。
#在搞一个MySQL看看
[root@han ~]# docker tag mysql:latest 127.0.0.1:5000/mysql:latest
[root@han ~]# docker push 127.0.0.1:5000/mysql:latest
The push refers to repository [127.0.0.1:5000/mysql]
f9181aceb81b: Pushed
6c01c2dc9edc: Pushed
b85d161b0894: Pushed
c35516682e65: Pushed
017828aeab37: Pushed
7b727121b0b9: Pushed
869d1e563d2c: Pushed
2aa0edf78281: Pushed
ad1915ad4275: Pushed
b7433112edcc: Pushed
latest: digest: sha256:85b933a8135f8e235ea0bb225757fee7d5a55900b2521bc3b326cd1eed1169fe size: 2412
[root@han ~]# curl http://192.168.12.44:5000/v2/_catalog
{“repositories”:[“mysql”,“tomcat”]}
[root@han ~]#
<h3 id="iAg9O">镜像原理之联合文件系统</h3>
<h4 id="wYkUr">镜像是什么:</h4>
镜像是一种轻量级可执行的独立软件包,用来打包软件环境和基于运行环境开发的软件,包含了运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。
<h4 id="f455f">如何得到镜像:</h4>
1,在远程仓库下载
2,朋友拷贝
3,自己制作一个镜像DockerFile
<h4 id="JF05h">UnionFS(联合文件系统)</h4>
docker pull 下载的时候看到的一层层的就是这个;
可以将不同目录挂载到同一个虚拟文件系统下
UnionFS的核心:
高校共享:多个实例(如容器)可共享相同的制度基础层,极大节省存储空间和内存
资源隔离:每个实例的写操作被隔离在各自的可写层,互不干扰。
快速部署:<font style="color:rgb(0, 0, 0);">基于分层镜像,可以快速创建和启动新的实例。</font>
<h4 id="gyFLr">docker镜像加载原理:</h4>
docker的镜像实际上由一层一层的文件系统组成,就是层级的文件系统UnionFS。
**<font style="color:rgb(0, 0, 0);">BootFS</font>**<font style="color:rgb(0, 0, 0);">:Docker 容器</font>**<font style="color:rgb(0, 0, 0);">共享宿主机的内核</font>**<font style="color:rgb(0, 0, 0);">。这意味着容器启动时</font>**<font style="color:rgb(0, 0, 0);">并不需要包含独立的 BootFS</font>**<font style="color:rgb(0, 0, 0);">,也无需加载自己的内核,从而显著减少了开销和资源占用</font>
**<font style="color:rgb(0, 0, 0);">RootFS</font>**<font style="color:rgb(0, 0, 0);">:每个 Docker 容器都需要自己的 </font>**<font style="color:rgb(0, 0, 0);">RootFS</font>**<font style="color:rgb(0, 0, 0);">。这个 RootFS 是一个</font>**<font style="color:rgb(0, 0, 0);">高度精简版</font>**<font style="color:rgb(0, 0, 0);">的文件系统,通常只包含运行特定应用程序所需的</font>**<font style="color:rgb(0, 0, 0);">最小化环境</font>**<font style="color:rgb(0, 0, 0);">(如最基本的命令、库文件和依赖),而不是一个完整的操作系统发行版(如完整的 Ubuntu 或 CentOS 的所有目录和文件)。这正是 Docker 镜像如此轻量级的原因之一。</font>
<h4 id="HS3UL">镜像原理之分层理解</h4>
下载镜像的时候,可以看到是一层一层的在下载。

思考:docker为什么要采用这种分层结构:
特点:资源共享,例如多个镜像都是从相同的base镜像构建而来,那么宿主机只需要在磁盘上保留一份base镜像,同时内存也只需要加载一份base镜像。因此就可以为所有容器服务了,并且镜像的每一层都可以被共享。
```shell
[root@han ~]# docker inspect redis:latest
[
{
"Id": "sha256:9d1fe3a9a889c69d0b4febf6affb4a8d90213cc35196e11d379c87a753658ff1",
"RepoTags": [
"redis:latest"
],
"RepoDigests": [
"redis@sha256:cc2dfb8f5151da2684b4a09bd04b567f92d07591d91980eb3eca21df07e12760"
],
"Parent": "",
"Comment": "buildkit.dockerfile.v0",
"Created": "2025-08-18T16:44:26Z",
"DockerVersion": "",
"Author": "",
"Config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"6379/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-8.2.1.tar.gz",
"REDIS_DOWNLOAD_SHA=e2c1cb9dd4180a35b943b85dfc7dcdd42566cdbceca37d0d0b14c21731582d3e"
],
"Cmd": [
"redis-server"
],
"Image": "",
"Volumes": {
"/data": {}
},
"WorkingDir": "/data",
"Entrypoint": [
"docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": null
},
"Architecture": "amd64",
"Os": "linux",
"Size": 137141036,
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/cc51e226d3fea8055d8ebb2c1adecf42c82d34d3fd3b81831230d4ff47908ce7/diff:/var/lib/docker/overlay2/39918f4502333ac535ff3b72c2db0d38de0af49771aeff329791af60e70423b2/diff:/var/lib/docker/overlay2/0663fcf14fb81446af88681477d84eda8ea848848a22b8523f0a2a9bc670aef0/diff:/var/lib/docker/overlay2/5100e2415feb7737b82c718ebca82b3d57ab0edb1776acbd32b6550e7d35a098/diff:/var/lib/docker/overlay2/e14bf70362ea1130bbb2d8cd1bbed2d378e717cdcb0da179083c914fc8640790/diff:/var/lib/docker/overlay2/0057214736a2984c7b75b39558be04f08aff2d95690d677745dd16af27d33d0e/diff",
"MergedDir": "/var/lib/docker/overlay2/ae9e2bef65df0091fd01c255ba2a79bb7842ad7b43703b448989e06788e687c7/merged",
"UpperDir": "/var/lib/docker/overlay2/ae9e2bef65df0091fd01c255ba2a79bb7842ad7b43703b448989e06788e687c7/diff",
"WorkDir": "/var/lib/docker/overlay2/ae9e2bef65df0091fd01c255ba2a79bb7842ad7b43703b448989e06788e687c7/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:eb5f13bce9936c760b9fa73aeb1b608787daa36106cc888104132e353ed37252",
"sha256:5b34e7b7ec41462b813b5a6cdea8776ee7ae671972b9abaafa4c9301489de698",
"sha256:0256a7df0b756d518be6228166ae83b404ca14be61be416c09800ad2833d14f9",
"sha256:7f32c228fb8af465641c506e9b12e96d9c5d2ce8e931351c6cd37bb4ab6bf62f",
"sha256:cfb4bd9f69a76849e89eea790cd5a69d1baf40ec368aaaf025ab38f2e1fe76ac",
"sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef",
"sha256:803d653c7ad737166e4ddbad9f12eaccf4e6af519e75b8e4ee9df0c2ba12ab48"
]
},
"Metadata": {
"LastTagTime": "0001-01-01T00:00:00Z"
}
}
]
所有的docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。

在添加额外的镜像层的同时,镜像始终保持是当前镜像的组合。
比如下面:每个镜像层包含了3个文件,而镜像包含了两个镜像层的6个文件。
最后会进行压缩,让这两个大层变成6个层,因为有6个文件。

如果新添加的文件是已有文件的更新版,那么会直接覆盖掉原始文件。

docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部!
这一层就是容器层,容器之下都叫镜像层。

如何制作一个自己的镜像
如果想要保存当前容器的状态(已经在原有镜像的基础上添加完操作了),就可以通过commit来提交,获得一个镜像。 (VMware中的快照差不多)
docker commit 提交容器成为一个 新的副本
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]
实战测试
```shell 1.启动一个tomcat [root@han ~]# docker run -it -p 8080:8080 tomcat [root@han ~]# docker exec -it xenodochial_colden /bin/bash2.发现官方默认tomcat镜像,没有webapps应用,因为官方镜像webapps默认下面是没有文件的!
3.自己拷贝进入了基本的文件
root@237b12da6a44:/usr/local/tomcat# cp -r webapps.dist/* webapps
4.将修改完的容器通过commit提交为一个镜像!以后就可以使用修改过的文件了
[root@han ~]# docker commit -a=“ayu” -m=“add webapps app” 237b12da6a44 tomcat02:0
sha256:8468de9e0fda11951d160450c216e55a3e78447be1fc9ef705a9d077a7ecb6a5
#-a 作者
#-m 镜像的信息
[root@han ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat02 0 8468de9e0fda 9 seconds ago 474MB #这是修改后的镜像
portainer/portainer-ce latest 79b66b8e24d3 10 days ago 186MB
redis latest 9d1fe3a9a889 2 weeks ago 137MB
nginx latest ad5708199ec7 3 weeks ago 192MB
tomcat latest bb9b6342d7e5 4 weeks ago 468MB
mysql latest 2c5440daffa8 6 weeks ago 921MB
centos latest 5d0da3dc9764 3 years ago 231MB
<h3 id="Ib1mk">容器数据卷 </h3>
<h4 id="eSCde">docker回顾:</h4>
docker目的是:将应用和环境打包成一个镜像!
如果数据都在容器中,那么容器删除,数据就会丢失!<font style="color:#DF2A3F;">需求:数据可以持久化</font>
危害:MySQL,容器删了,就能删库跑路!!! <font style="color:#DF2A3F;">需求:MySQL数据可以存储在本地! </font>
<h4 id="NLukw">容器卷</h4>
容器之间可以有一个共享的技术! docker容器中产生的数据,同步到本地!
这就是卷技术!(目录的挂载,将容器内的目录,挂载到Linux上面。反而言之一样,因为挂载是双向映射)

为什么要用容器卷技术? 总结:为了容器的持久化和同步操作。容器间也可以数据共享。
<h4 id="UR5XM">容器卷的好处</h4>
以后修改只需要在本地修改即可,容器内会自动同步!
<h4 id="jTRmL">容器的使用</h4>
```shell
docker run -it -v /home/ceshi1:/home tomcat /bin/bash
#-v (容器外)主机目录(被挂载到的目录):容器内目录
#将容器tomcat下的/home目录,同步到linux的/home/ceshi1目录中。
#-v 相当于Linux中[root@han home]# mount --bind 要挂载的文件 被挂载的文件 #--bind挂在文件的时候用
[root@han ~]# docker exec -it quirky_curran /bin/bash
#进入到容器内部,在/home目录下创建文件,验证Linux的/home/ceshi1中是否同步
cd /home
touch kuangshen
#退出到linxu中
exit
[root@han ~]# cd /home/ceshi1
[root@han ceshi1]# ls #ls命令查看
kuangshen #发现到已经同步
#反而言之,在Linux/home/ceshi1目录下创建文件也会同步到容器里
#使用 docker inspect 查看容器的元数据
[root@han ceshi1]# docker inspect quirky_curran #发现已经有了Mounts
"Mounts": [
{
"Type": "bind",
"Source": "/home/ceshi1",
"Destination": "/home",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
MySQL的同步
```shell [root@han ~]# docker run -d -p4567:3306 --name mysql02 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123 mysql #-d 后台运行 #--name 容器的名字 #-p 端口映射 -p4567:3306 容器的端口必须是3306(容器内部没有监听其他端口的时候) #-v 将数据库的文件挂载到Linux里面,想挂载几个文件,就有几个-v/etc/mysql/conf.d
#-e 环境配置(这里指设置MySQL的密码) -e MYSQL_ROOT_PASSWORD=123 这里必须是大写,小写的不行
#配置完之后,即使删掉MySQL容器,Linux本地被挂在的目录下依然有数据。
<h4 id="xmNjV">具名挂载和匿名挂载</h4>
```shell
#匿名挂载
-v 容器内路径!
[root@han ~]# docker run -d -P --name nginx01 -v /etc/nginx nginx
#-p 不指定端口,随机端口
#-v 后面直接写路径(代表容器内部路径) 不指定挂在到主机的路径
[root@han docker]# docker volume ls
DRIVER VOLUME NAME
local 000104fb09f1b4aba774504d95b5409af73617301b46fbe6d295eef420df490a
local 068957fc50e1eaf0b4c798b474e3d8530d567333135d972dc9781c02a76f7045
local c90666c0ea6bcece7c1533a3775e6d1a55e5a2297371de7a4c4d259dd1933764
local faa6a8161b70eefbed4ab34d6b345d32354db245203deb58ddcfb89f1a26e3ee
local portainer_data
#这就是匿名挂载,后面由许多数字
#就是只在-v 后面写了容器内的路径,没有写容器外的路径
#具名挂载
[root@han docker]# docker run -d -P --name nginx02 -v 123-nginx:/etc/nginx nginx
9083aa061c9a4c5785a63b4eb8af592fa09194b55bbec2cb601334f1291917d1
[root@han docker]# docker volume ls
DRIVER VOLUME NAME
local 000104fb09f1b4aba774504d95b5409af73617301b46fbe6d295eef420df490a
local 123-nginx
local 068957fc50e1eaf0b4c798b474e3d8530d567333135d972dc9781c02a76f7045
local c90666c0ea6bcece7c1533a3775e6d1a55e5a2297371de7a4c4d259dd1933764
local faa6a8161b70eefbed4ab34d6b345d32354db245203deb58ddcfb89f1a26e3ee
local portainer_data
#这是具名挂载,就是起了个容器卷的名字。和匿名挂载都是放在/var/docker/volum 这里
# -v 卷名:容器内路径 卷名前面不加/ 否则就成为指定路径了
#查看123-nginx容器卷的的元数据
[root@han docker]# docker volume inspect 123-nginx
[
{
"CreatedAt": "2025-09-07T12:52:13+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/123-nginx/_data",
"Name": "123-nginx",
"Options": null,
"Scope": "local"
}
]
[root@han ~]# cd /var/lib/docker/volume #所有docker容器内的卷,没有指定目录的情况下都是放在这个目录下
#通过具名挂载可以方便的找到我们的一个卷,大多数情况下在使用 具名挂载
#如何确定是具名挂载还是匿名挂在,还是指定路径挂载。
-v 容器内的路径 #匿名挂载
-v 卷名:容器内路径 #具名挂载 #匿名挂载和具名挂载都是放在/var/lib/docker/volume 目录下,区分就是具名挂载起了个名字,而匿名挂载一串乱码
-v /宿主机路径:容器内路径 #指定路径挂载
数据卷之DockerFile
DockerFile就是用来构建docker镜像的构建文件! 命令脚本!通过这个脚本可以生成镜像,镜像是一层一层的,脚本一个个的命令,每个命令都是一层
#创建一个dockerfile 文件,名字可以随机 建议 dockerfile
#文件中的内容 指令(大写)参数
[root@han home]# mkdir docker-text-volume #创建一个目录用于存放数据卷
[root@han home]# cd docker-text-volume/
[root@han docker-text-volume]# vim dockerfile 创建dockerfile文件(文件名无所谓),并编写
#创建一个dockerfile 文件,名字可以随机 建议 dockerfile
#文件中的内容 指令(大写)参数
[root@han docker-text-volume]# docker build -f /home/docker-text-volume/dockerfile -t kuangshen/centos:1.0 .
[+] Building 0.1s (5/5) FINISHED docker:default
=> [internal] load build definition from dockerfile 0.0s
=> => transferring dockerfile: 176B 0.0s
=> [internal] load metadata for docker.io/library/centos:latest 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [1/1] FROM docker.io/library/centos:latest 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:88a327c6cfeef6087c83f9cbfdf13f022fe72f5c346e9500b5932d19e 0.0s
=> => naming to docker.io/kuangshen/centos:1.0 0.0s
[root@han docker-text-volume]#
-f(全称 --file)用于指定 Dockerfile 的路径 <dockerfile的路径>
-t是标签名:kuangshen/centos:1.0 <镜像名>:<标签名>
.用当前目录来构建上下文

[root@han docker-text-volume]# cat dockerfile
FROM centos #FROM 指定构建新镜像所基于的基础镜像,后续所有指令都在此镜像之上执行。
VOLUME ["volume01","volume02"]
#作用:创建匿名数据卷(Anonymous Volumes)。这会在镜像中创建两个名为 volume01和 volume02的挂载点
#目的:当容器运行时,任何写入 volume01或 volume02目录的数据都会存储在由 Docker 管理的卷中,即使容器被删除,这些数据也会保留,实现了数据持久化
#注意:Dockerfile 中的 VOLUME指令本身不能指定主机目录路径,主机路径的绑定只能在 docker run时通过 -v参数实现。
CMD echo "----end----"
CMD /bin/bash
#功能:CMD指令用于指定容器启动时默认执行的命令。
#关键特性:一个 Dockerfile 中可包含多条 CMD指令,但仅有最后一条会生效。因此,此处的 CMD echo "----end----"会被后续的 CMD /bin/bash覆盖。
[root@han docker-text-volume]# docker build -f /home/docker-text-volume/dockerfile -t kuangshen/centos:1.0
ERROR: "docker buildx build" requires exactly 1 argument.
See 'docker buildx build --help'.
Usage: docker buildx build [OPTIONS] PATH | URL | -
Start a build
报错了,原因是命令最后没有加上. 这个点 .是在告诉 Docker:“请把我当前目录下的所有东西(构建上下文)都打包给你,请根据我的 Dockerfile 指令,用这些材料来制作镜像”。

查看镜像是否建造成功:
[root@han docker-text-volume]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat02 0 8468de9e0fda 21 hours ago 474MB
portainer/portainer-ce latest 79b66b8e24d3 11 days ago 186MB
redis latest 9d1fe3a9a889 2 weeks ago 137MB
nginx latest ad5708199ec7 3 weeks ago 192MB
tomcat latest bb9b6342d7e5 4 weeks ago 468MB
mysql latest 2c5440daffa8 6 weeks ago 921MB
centos latest 5d0da3dc9764 3 years ago 231MB
kuangshen/centos 1.0 88a327c6cfee 3 years ago 231MB
#可以看到已经成功了,建造的镜像存在
运行该文件:
[root@han ~]# docker run -it kuangshen/centos:1.0 /bin/bash
[root@acb8bb34461b /]# ls -l
total 0
lrwxrwxrwx. 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x. 5 root root 360 Sep 7 06:21 dev
drwxr-xr-x. 1 root root 66 Sep 7 06:21 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 2021 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. 236 root root 0 Sep 7 06:21 proc
dr-xr-x---. 2 root root 162 Sep 15 2021 root
drwxr-xr-x. 11 root root 163 Sep 15 2021 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 Sep 7 04:28 sys
drwxrwxrwt. 7 root root 171 Sep 15 2021 tmp
drwxr-xr-x. 12 root root 144 Sep 15 2021 usr
drwxr-xr-x. 20 root root 262 Sep 15 2021 var
drwxr-xr-x. 2 root root 6 Sep 7 06:21 volume01
drwxr-xr-x. 2 root root 6 Sep 7 06:21 volume02 #这个目录就是生成容器的时候自动挂载的,数据卷目录
检验看有没有成功;
#在容器中的挂载目录,创建一个文件,看是否同步到主机
[root@acb8bb34461b /]# cd /volume01
[root@acb8bb34461b volume01]# touch container.text
[root@acb8bb34461b volume01]# ls
container.text
#因为dockerfile文件里面写的是匿名挂载,所以数据卷名是一串乱码
#所以就需要使用docekr inspect 查看一下
[root@han ~]# docker inspect acb8bb34461b 查看容器id是acb8bb34461b的元数据
"Mounts": [
{
"Type": "volume",
"Name": "db5630b01da16dba8ae35c2196c556c55c3a2ad51ae76a3a4a70b053d318280c",
"Source": "/var/lib/docker/volumes/db5630b01da16dba8ae35c2196c556c55c3a2ad51ae76a3a4a70b053d318280c/_data", #这个目录就是容器外的挂载目录
"Destination": "volume01",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "8676897ae9c9f4b0e804113d943b2e5f4b457147c4decea02f57bf5d46679763",
"Source": "/var/lib/docker/volumes/8676897ae9c9f4b0e804113d943b2e5f4b457147c4decea02f57bf5d46679763/_data",
"Destination": "volume02",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
所以只需要cd /var/lib/docker/volumes/db5630b01da16dba8ae35c2196c556c55c3a2ad51ae76a3a4a70b053d318280c/_data 就行了
[root@han ~]# cd /var/lib/docker/volumes/db5630b01da16dba8ae35c2196c556c55c3a2ad51ae76a3a4a70b053d318280c/_data
[root@han _data]# ls
container.text
#这里可以看到已经同步到Linux主机了
#反而言之,在Linux中创建文件,也会同步到docker里面
数据卷容器(容器之间的同步)
比如图像:
[root@han _data]# docker run -it --name kuangshen2 --volumes-from awesome_faraday kuangshen/centos:1.0
#这条命令的作用是依据镜像kuangshen/centos:1.0创建一个名为 kuangshen2的新容器,并让它共享继承另一个名为 awesome_faraday的容器的所有数据卷(Volume)。
#--volumes-from 参数是 docker run(创建并启动新容器)时使用的,用于指定新容器要继承哪个已有容器的数据卷
[root@aee2d2e5b5b3 /]# ls -l
total 0
lrwxrwxrwx. 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x. 5 root root 360 Sep 7 07:02 dev
drwxr-xr-x. 1 root root 66 Sep 7 07:02 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 2021 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. 221 root root 0 Sep 7 07:02 proc
dr-xr-x---. 2 root root 162 Sep 15 2021 root
drwxr-xr-x. 11 root root 163 Sep 15 2021 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 Sep 7 04:28 sys
drwxrwxrwt. 7 root root 171 Sep 15 2021 tmp
drwxr-xr-x. 12 root root 144 Sep 15 2021 usr
drwxr-xr-x. 20 root root 262 Sep 15 2021 var
drwxr-xr-x. 2 root root 47 Sep 7 06:39 volume01
drwxr-xr-x. 2 root root 6 Sep 7 06:21 volume02
#可以看到已经 共享继承awesome_faraday的容器的所有数据卷(Volume)
#检验一下是否同步 #现在在容器name是kuangshen2里面
[root@aee2d2e5b5b3 /]# cd volume01
[root@aee2d2e5b5b3 volume01]# ls
centos.text container.text
[root@aee2d2e5b5b3 volume01]# touch docker2.text #在挂载的目录下,创建了了一个docker2.text的文件
[root@aee2d2e5b5b3 volume01]#
#登录到 awesome_faraday,查看有没有docker2.text文件
[root@han ~]# docker exec -it awesome_faraday /bin/bash
[root@acb8bb34461b /]#
[root@acb8bb34461b /]#
[root@acb8bb34461b /]#
[root@acb8bb34461b /]#
[root@acb8bb34461b /]# cd v
var/ volume01/ volume02/
[root@acb8bb34461b /]# cd volume01
[root@acb8bb34461b volume01]# ls
centos.text container.text docker2.text #可以看到已经同步备份了
与此相同:备份同步MySQL的数据(多个MySQL实现数据共享)

结论:容器之间配置信息的传递,数据卷容器的的生命周期一直持续到没有容器使用为止。
就是只要容器共享之后,所有数据都会同步过去,(删除父级挂载容器,子级挂载容器的内容也不会被清除)
DockerFile
dockerfile介绍
dockerfile是用来构建docker镜像的文件!命令参数脚本!构建步骤:
1.编写一个dockerfile文件。
2.docker build 构建成为一个镜像
3.docker run 运行镜像
4.docker push 发布镜像(dockerhub、阿里云镜像仓库)
DockerFile构建过程
基础知识:1.每个保留关键字(指令)都必须是大写字母
2.执行从上到下顺序执行
3.#表示注释
4.每一个指令都会创建提交一个新的镜像层。

dockerfile是面向开发的,以后要发布项目,做镜像,就需要编写dockerfile文件,这个文件十分简单!
DockerFile:构建文件,定义了一切的步骤,源代码。
DockerImages:通过DockerFile 构建生成的镜像,最终发布和运行的产品。
docker容器:容器就是镜像运行起来提供服务器 。
DockerFile的指令
以前时使用别人的,现在知道了这些指令之后,就可以自己练习写一个镜像。FROM #基础镜像
MAINTAINER #镜像的作者(维修工),一般是姓名+邮箱
RUN #镜像构建的时候需要运行的命令
ADD #步骤:tomcat镜像,要将tomcat压缩包添加
WORKDIR #镜像的工作目录 (进入容器的 起始目录)
VOLUME #镜像的挂载卷
EXPOSE #暴露端口,声明容器在运行时监听的网络端口
CMD #指定这个容器在启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT #指定这个容器在启动的时候要运行的命令,可以追加命令
ONBUILD #它让你能在构建一个基础镜像时,先预设一些命令。但这些命令不会立刻执行,而是要等到别人用你这个镜像作为基础,去构建他们自己的镜像时,才会被触发执行。
COPY #类似ADD,可以将我们的文件拷贝到镜像中
ENV #构建的时候设置环境变量(如MySQL密码)

实战:构建自己centos
dockerfile问价$地址符
FROM centos
MAINTAINER kuangshen<24736743@qq.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
# 修复 CentOS 8 软件源
RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* && \
sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "----end----"
CMD /bin/bash
#WORKDIR设置成功:一启动容器就在 /usr/local证明了这一点。
#WORKDIR设置了您的出生点(/usr/local)
[root@han docker-text-volume]# docker build -f dockerfile2 -t mycentos:1.0 .
#然后基于这个dockerfile,去构建是一个镜像,名字是 mycentos 版本是1.0
-t 镜像名:版本
[root@han docker-text-volume]# docker run -it mycentos:1.0 /bin/bash
#然后基于这个dockerfile
#使用ifocnfig 看dockerfile是否成功
[root@7f8d464e6d8c local]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)
RX packets 8 bytes 656 (656.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
docker history 镜像名/镜像ID
[root@han docker-text-volume]# docker history 7c6837737ddb
IMAGE CREATED CREATED BY SIZE COMMENT
7c6837737ddb 11 minutes ago CMD ["/bin/sh" "-c" "/bin/bash"] 0B buildkit.dockerfile.v0
<missing> 11 minutes ago CMD ["/bin/sh" "-c" "echo \"----end----\""] 0B buildkit.dockerfile.v0
<missing> 11 minutes ago CMD ["/bin/sh" "-c" "echo $MYPATH"] 0B buildkit.dockerfile.v0
<missing> 11 minutes ago EXPOSE map[80/tcp:{}] 0B buildkit.dockerfile.v0
<missing> 11 minutes ago RUN /bin/sh -c yum -y install net-tools # bu… 14.7MB buildkit.dockerfile.v0
<missing> 11 minutes ago RUN /bin/sh -c yum -y install vim # buildkit 66.3MB buildkit.dockerfile.v0
<missing> 11 minutes ago RUN /bin/sh -c sed -i 's/mirrorlist/#mirrorl… 8.8kB buildkit.dockerfile.v0
<missing> 2 hours ago WORKDIR /usr/local 0B buildkit.dockerfile.v0
<missing> 2 hours ago ENV MYPATH=/usr/local 0B buildkit.dockerfile.v0
<missing> 2 hours ago MAINTAINER kuangshen<24736743@qq.com> 0B buildkit.dockerfile.v0
<missing> 3 years ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 3 years ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 3 years ago /bin/sh -c #(nop) ADD file:805cb5e15fb6e0bb0… 231MB
[root@han docker-text-volume]#
CMD和ENTRYPOIN区别
```shell CMD #指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代 ENTRYPOINT #指定这个容器启动的时候要运行的命令,可以追加命令 ```创建dockerfile文件
[root@han docker-text-volume]# cat dockerfile
FROM centos
CMD ["ls","-a"]
#使用docker build 命令构建容器
[root@han docker-text-volume]# docker build -f dockerfile -t cmdtest .
[root@han docker-text-volume]# docker run 2b06f9641629(或者镜像的名字)
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
#docekrfile文件 代码参数生效
#若想追加一个命令 -l
#只能
[root@han docker-text-volume]# docker run cmdtest ls -al
total 0
drwxr-xr-x. 1 root root 6 Sep 7 11:40 .
drwxr-xr-x. 1 root root 6 Sep 7 11:40 ..
-rwxr-xr-x. 1 root root 0 Sep 7 11:40 .dockerenv
lrwxrwxrwx. 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x. 5 root root 340 Sep 7 11:40 dev
drwxr-xr-x. 1 root root 66 Sep 7 11:40 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 2021 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. 220 root root 0 Sep 7 11:40 proc
dr-xr-x---. 2 root root 162 Sep 15 2021 root
drwxr-xr-x. 11 root root 163 Sep 15 2021 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 Sep 7 04:28 sys
drwxrwxrwt. 7 root root 171 Sep 15 2021 tmp
drwxr-xr-x. 12 root root 144 Sep 15 2021 usr
drwxr-xr-x. 20 root root 262 Sep 15 2021 var
不能这样:
[root@han docker-text-volume]# docker run cmdtest -l
docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "-l": executable file not found in $PATH: unknown.
#因为CMD 的清理下 -l 替换了dockerfile文件里面的 CMD["ls","-a"] 不是命令所以报错
[root@han docker-text-volume]# cat dockerfile1
FROM centos
ENTRYPOINT ["ls","-a"]
[root@han docker-text-volume]# docker build -f dockerfile1 -t ENTRTYPOINT/centos .
#此时可以看到可以追加命令
[root@han docker-text-volume]# docker run ENTRTYPOINT/centos -l
total 0
drwxr-xr-x. 1 root root 6 Sep 7 11:53 .
drwxr-xr-x. 1 root root 6 Sep 7 11:53 ..
-rwxr-xr-x. 1 root root 0 Sep 7 11:53 .dockerenv
lrwxrwxrwx. 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x. 5 root root 340 Sep 7 11:53 dev
drwxr-xr-x. 1 root root 66 Sep 7 11:53 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 2021 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. 220 root root 0 Sep 7 11:53 proc
dr-xr-x---. 2 root root 162 Sep 15 2021 root
drwxr-xr-x. 11 root root 163 Sep 15 2021 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 Sep 7 04:28 sys
drwxrwxrwt. 7 root root 171 Sep 15 2021 tmp
drwxr-xr-x. 12 root root 144 Sep 15 2021 usr
drwxr-xr-x. 20 root root 262 Sep 15 2021 var
在dockerhub发布自己的镜像



docker所有流程小结


使用docker load 和 docker import 的主机需要配置docker。
这两条命令是 Docker 工具链的一部分,必须在安装了 Docker 的机器上才能执行。
Docker网络
清空所有环境(镜像、容器)测试容器外(Linux上能不能和容器内通信):
1、查看主机的IP地址[root@han ~]# 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
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qle n 1000
link/ether 00:0c:29:de:05:c8 brd ff:ff:ff:ff:ff:ff
inet 192.168.12.44/24 brd 192.168.12.255 scope global ens33
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fede:5c8/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:15:1e:ed:93 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:15ff:fe1e:ed93/64 scope link
valid_lft forever preferred_lft forever
2,用docker进入一个容器,并查看容器的地址。
[root@han ~]# docker exec -it fervent_shockley /bin/bash
[root@2a8e32857c91 local]# 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
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
28: eth0@if29: <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
3.容器内部的IP
[root@han ~]# docker exec -it fervent_shockley /bin/bash
[root@2a8e32857c91 local]# 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
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
28: eth0@if29: <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
#28这个网卡和Linux主机里的29网卡对应
4.看容器外和容器内部是否能ping通。 (测试说明Linux可以ping通docker容器内部的)
[root@2a8e32857c91 local]#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.033 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.081 ms
^C
--- 172.17.0.3 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.033/0.057/0.081/0.024 ms
原理:
1.每启动一个docker容器,docker就会给docker容器分配一个IP,我们只要安装了docker,就会有一个网卡docker0(桥接模式),使用的技术是evth-pair技术!2.在启动一个容器测试(现在已经启动了两个了),发现又多了一对网卡(容器内和容器外各一个,这两个网卡是对应的)!
[root@han ~]# 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
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qle n 1000
link/ether 00:0c:29:de:05:c8 brd ff:ff:ff:ff:ff:ff
inet 192.168.12.44/24 brd 192.168.12.255 scope global ens33
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fede:5c8/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:15:1e:ed:93 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:15ff:fe1e:ed93/64 scope link
valid_lft forever preferred_lft forever
9: veth68c5ce2@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 stat e UP group default
link/ether 1a:cb:56:95:1e:56 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::18cb:56ff:fe95:1e56/64 scope link
valid_lft forever preferred_lft forever
29: veth7fffc26@if28: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 st ate UP group default
link/ether ae:69:f4:7e:b2:94 brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::ac69:f4ff:fe7e:b294/64 scope link
valid_lft forever preferred_lft forever
33: veth24e4743@if32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 st ate UP group default
link/ether 76:b9:44:c5:20:52 brd ff:ff:ff:ff:ff:ff link-netnsid 2
inet6 fe80::74b9:44ff:fec5:2052/64 scope link
valid_lft forever preferred_lft forever
#这个29网卡和容器内部的28网卡对应
#发现这个容器带来的网卡都是一对对的;
#evth-pair 就是一对的虚拟设备接口,他们都是成对出现的,一段连着协议,一段彼此相连
#正因为有这个特性,evth-pair充当一个桥梁,连接各种虚拟网络设备的
#Openstac,docker容器之间的连接,OVS的连接,都是使用evth-pair 技术
3.现在来测试连个容器间是否可以ping通
#进入容器,并查看IP地址
[root@han ~]# docker exec -it fervent_shockley /bin/bash
[root@2a8e32857c91 local]# 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
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
28: eth0@if29: <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
[root@2a8e32857c91 local]# exit
exit
#进入另一个容器查看自己的IP地址,并且去ping刚刚那个容器的地址,看是否可以互通的。
[root@han ~]# docker exec -it centos02 /bin/bash
[root@fc2534fca8c4 local]# 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
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
32: eth0@if33: <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
[root@fc2534fca8c4 local]# 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.204 ms
64 bytes from 172.17.0.4: icmp_seq=2 ttl=64 time=0.072 ms
^C
--- 172.17.0.4 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.072/0.138/0.204/0.066 ms
[root@fc2534fca8c4 local]#
#结论:容器和容器之间可以互相ping通
docker网络模型图:
结论: centos01和centos02是公用的一个路由器,docker0
所有的容器不指定网络的情况下,都是docker0路由的,docker会给我们的容器分配一个默认的可用IP。

Docker中的所有的网络接口都是虚拟的。虚拟的转发效率高!(内网传递文件)
只要将容器删除,对应网桥(一对)就都没了!

--Link (新手用)
```shell #思考一个场景,编写了一个微服务,database url=ip; 项目不重启,数据库IP换掉了,我们希望可以处理这个问题, #希望可以用名字来进行访问容器 ```#查看容器:
[root@han ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e05f9d6e8211 mycentos:1.0 "/bin/sh -c /bin/bash" 6 seconds ago Up 6 seconds 0.0.0.0:32769->80/tcp, :::32769->80/tcp mycentos02
130e0284a5c0 mycentos:1.0 "/bin/sh -c /bin/bash" 41 seconds ago Up 40 seconds 0.0.0.0:32768->80/tcp, :::32768->80/tcp mycentos01
#ping测试看是否能通,答案是不能。原因是因为没有使用--link
[root@han ~]# docker exec -it mycentos01 ping mycentos02
ping: mycentos02: Name or service not known
#创建容器mycentos03,并使用--link,将mycentos03和centos02建立连接
[root@han ~]# docker run -it -P -d --name mycentos03 --link mycentos02 mycentos:1.0
a485fcaffb5e80c19bd171def23db34e103063ba25e3a29d26735143edc2a343
#mycentos03 到 mycentos02的ping的
[root@han ~]# docker exec -it mycentos03 ping mycentos02
PING mycentos02 (172.17.0.3) 56(84) bytes of data.
64 bytes from mycentos02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.065 ms
64 bytes from mycentos02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.386 ms
64 bytes from mycentos02 (172.17.0.3): icmp_seq=3 ttl=64 time=0.103 ms
--- mycentos02 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 0.065/0.184/0.386/0.144 ms
[root@han ~]#
#看反向是否能ping通,答案是不行的。需要做配置。w
[root@han ~]# docker exec -it mycentos02 ping mycentos03
ping: mycentos03: Name or service not known
#查看 docker network --help
[root@han ~]# docker network --help
Usage: docker network COMMAND
Manage networks
Commands:
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 networks
Run 'docker network COMMAND --help' for more information on a command.
在mycentos03中查看和mycentos02的映射关系。
[root@han ~]# docker exec -it mycentos03 cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 mycentos02 e05f9d6e8211 #/etc/hosts:容器内负责本地域名解析的系统文件,其中包含了 IP 地址和主机名的映射关系。 当mycentos03 ping mycentos02或者e05f9d6e8211的时候,会直接去访问172.17.0.2
172.17.0.3 a485fcaffb5e # 两个容器和 mycentos03在同一个 Docker 网络中,并且 mycentos03容器可以直接通过主机名 mycentos02或容器 ID a485fcaffb5e来访问它们
。
--link 就是在容器mycentos03中hosts配置中增加了172.17.0.2 mycentos02 e05f9d6e8211
#反过来mycentos02 ping mycentos03看能不能通
[root@han ~]# docker exec -it mycentos02 ping mycentos03
ping: mycentos03: Name or service not known
#不能,因为在mycentos02中hosts没有配置映射mycentos03的容器名或ID到mycentos03的IP地址
[root@han ~]# docker exec -it mycentos02 cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 e05f9d6e8211
自定义网络(高手用)
查看现有的所有docker网络[root@han ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
e862d36f2d3e bridge bridge local
93129c2601f3 host host local
0ac6eb914b16 none null local
网络模式
bridge : 桥接docker(默认,自己创建也是用 bridge 模式),共用一个网卡none : 不配置网络,IP地址也没有(仅用于测试)
host:和宿主机(linux)共享网络,直接就是用的Linux的IP地址,和Linux的端口了,容易产生冲突。
container:容器网络联通!(用的少!局限性很大) (一般不用)
创建一个网络(网卡),并查看这个网卡的元数据
```shell#docker0特点,默认,域名不能访问, --link可以打通连接
#现在来自定义一个网络! #相当于搞了一个虚拟网卡。 在linux中也能看到。
#–driver bridge 使用桥接网络
#–subnet 192.168.0.0/16 设置子网
#–gateway 192.168.0.1 设置网关
#mynet (网卡)网络名称
[root@han ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
05771ac7e9835369d89d5c74b333379cc605179f18d5f5a3a212846ee0d2ac75
[root@han ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
e862d36f2d3e bridge bridge local
93129c2601f3 host host local
05771ac7e983 mynet bridge local
0ac6eb914b16 none null local
#查看一下我们自己创建的网络
[root@han ~]# docker network inspect mynet
[
{
“Name”: “mynet”,
“Id”: “05771ac7e9835369d89d5c74b333379cc605179f18d5f5a3a212846ee0d2ac75”,
“Created”: “2025-09-08T21:29:32.064416917+08:00”,
“Scope”: “local”,
“Driver”: “bridge”,
“EnableIPv6”: false,
“IPAM”: {
“Driver”: “default”,
“Options”: {},
“Config”: [
{
“Subnet”: “192.168.0.0/16”,
“Gateway”: “192.168.0.1”
}
]
},
“Internal”: false,
“Attachable”: false,
“Ingress”: false,
“ConfigFrom”: {
“Network”: “”
},
“ConfigOnly”: false,
“Containers”: {},
“Options”: {},
“Labels”: {}
}
]
<h5 id="UcWOK">自定义网络测试</h5>
```shell
#自定义网络
#创建一个网络(网卡)
[root@han ~]# docker network create --driver bridge --subnet 172.168.12.0/24 --gateway 172.168.12.1 mynet01
#查看现在docker的所有网络(网卡),可以看到已经有了我们刚刚创建的网络(网卡)
[root@han ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
77330e76294d bridge bridge local
93129c2601f3 host host local
42c3f224fea7 my_shared_net bridge local
05771ac7e983 mynet bridge local
ca7e74fd445c mynet01 bridge local
0ac6eb914b16 none null local
#基于这块网卡创建两个容器
#让这两个容器,使用这个网络(网卡)。如果不指定网卡,默认是使用docker0网卡
[root@han ~]# docker run -it -d --name my-centos--mynet01 --network mynet01 1111:1.0
325a3857f6eb052273c7d0721847d997cbff67732a054c9b5c46abb5b75e8aac
[root@han ~]# docker run -it -d --name my-centos02--mynet01 --network mynet0 1 1111:1.0
c2a0c8e2550061d1854309678b389a9429cc4c245388dc759a37ca3936fdf144
#已经完成
#现在可以使用容器my-centos--mynet01 ping 容器my-centos02--mynet01 看是否连通了
#使用容器name名字去ping测试
[root@han ~]# docker exec -it my-centos--mynet01 ping my-centos02--mynet01
PING my-centos02--mynet01 (172.168.12.5) 56(84) bytes of data.
64 bytes from my-centos02--mynet01.mynet01 (172.168.12.5): icmp_seq=1 ttl=64 time=0.183 ms
64 bytes from my-centos02--mynet01.mynet01 (172.168.12.5): icmp_seq=2 ttl=64 time=0.174 ms
64 bytes from my-centos02--mynet01.mynet01 (172.168.12.5): icmp_seq=3 ttl=64 time=0.052 ms
64 bytes from my-centos02--mynet01.mynet01 (172.168.12.5): icmp_seq=4 ttl=64 time=0.113 ms
^C
--- my-centos02--mynet01 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3002ms
rtt min/avg/max/mdev = 0.052/0.130/0.183/0.053 ms
#现在使用my-centos02--mynet01的容器ID 去 ping my-centos--mynet01的容器ID
[root@han ~]# docker exec -it c2a0c8e25500 ping 325a3857f6eb
PING 325a3857f6eb (172.168.12.3) 56(84) bytes of data.
64 bytes from my-centos--mynet01.mynet01 (172.168.12.3): icmp_seq=1 ttl=64 time=0.129 ms
64 bytes from my-centos--mynet01.mynet01 (172.168.12.3): icmp_seq=2 ttl=64 time=0.086 ms
64 bytes from my-centos--mynet01.mynet01 (172.168.12.3): icmp_seq=3 ttl=64 time=0.090 ms
^C
--- 325a3857f6eb ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.086/0.101/0.129/0.022 ms
为什么用使用docker网络而不适用--link(总结)
```shell #因为默认是不能通过容器name或者容器ID,进行ping测试的 #低级的手段是使用 --link 去创建一个映射到某个容器的容器,使得创建的这个容器/etc/hosts配置里面有 某个容器的name/ID和IP地址的映射。这样去ping容器name/ID时,数据会自动转向给对方IP地址 [root@han ~]# docker run -it -P -d --name mycentos03 --link mycentos02 mycentos:1.0#就可以实现
[root@han ~]# docker exec -it mycentos03 ping mycentos02
PING mycentos02 (172.17.0.3) 56(84) bytes of data.
64 bytes from mycentos02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.065 ms
#但是反过来不行,因为同样也需要在mycentos02配置映射
#所以很不方便,所以就直接使用自定义docker网络
:’
🔧 为何自定义 Bridge 网络能直接解析容器名?
当你创建并使用了自定义 bridge 网络(例如 mynet)时,Docker 会为这个网络自动启用一个内嵌的 DNS 服务器。
DNS 查询:当你在一个容器(比如 container1)里执行 ping container2时,这个请求会被发送到容器内配置的 DNS 服务器(通常是 Docker 内置的 DNS 服务器 127.0.0.11)。
自动解析:Docker 的 DNS 服务器维护着该自定义网络内所有容器名称与 IP 地址的映射关系。它收到对 container2的查询后,会返回正确的 IP 地址。
建立连接:container1拿到 container2的 IP 后,就能成功发起 ping 请求或进行其他通信了。
’
<h5 id="RufgE">自定义网络中 connect命令</h5>
<font style="color:#DF2A3F;">一般用实现基于两个不同网络分别创建的容器,之间的通信。就是给两个容器添加了一块相同的网卡</font>

更多推荐


所有评论(0)