docker基础

dockers为什么会出现

开发-----运维。问题:我在我电脑上可以运行!版本更新,导致服务不可用!所以对运维来说考验就十分大。

环境配置时十分麻烦的,每一个机器都要部署环境(集群Redis,ES,Hadoop…)费时费力。

所以发布一个项目能不能都带上环境安装打包! windows的东西到Linux上也能用。

传统:开发jar,运维来给电脑配置环境。

现在:开发打包部署上线,一套流程做完。

例如:手机的应用游戏

java ------做成apk—然后发布到(应用商店)—张三使用apk----安装即可用。

那么: 举个docker的例子

Java —jar(环境)----打包项目带上环境(镜像)----(然后放到Docker仓库:商店)—别人下载我们发布的镜像-------直接运行即可

docker的核心思想:
![](https://i-blog.csdnimg.cn/img_convert/0fe7e2d269d9539d0a6859f0aca4db2a.png)docker的思想来自于集装箱。

隔离:docker的核心思想!打包装箱!每个箱子(容器)是互相隔离的。

docker通过隔离机制,可以将服务器利用到机制!

docker的历史:
dotcloud公司开发感觉虚拟机笨重,所以开发了docker,后来因为没有引起行业注意,就活不下去!所以开放源代码。docker越来越多的人发现了docker的优点!火了!
docekr为什么会这么火呢?
![](https://i-blog.csdnimg.cn/img_convert/2e03f8474e870947ec929d390ef76afc.png)

虚拟机:在Windows中装一个VMware, 隔离,需要开启多个虚拟机! 占用内存至少几个G。启动要几分钟

docker:隔离,镜像(最核心的环境 4m+jdk+mysql)十分小巧,只运行镜像就可以了, 占用内存几个M,多说也就是几百M。秒及启动。

docker是什么语言开发的,docker官网
docker是基于GO语言开发的。

docker官方网址:https://www.docker.com/

docker仓库网址:https://hub.docker.com/

docker能做什么

虚拟机: 模拟的一个完整的操作系统。
![](https://i-blog.csdnimg.cn/img_convert/428702c40ae2efc1b913aca0413c1752.png)

虚拟机技术缺点:

1,资源占用十分多

2.启动很慢

3.一个地方出错,可能导致全盘出错。

容器化技术
容器化技术不是模拟的一个完整的操作系统

比较docker和虚拟机技术的不同:
传统虚拟机,虚拟出一条硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件。

容器内的应用直接运行在宿主机,容器没有自己的内核,也没有虚拟硬件,所以就轻便了。

每个容器间是互相隔离,每个容器内都有一个属于自己的文件系统,互不影响。

DevOps(开发、运维) ,(docker相比于虚拟机的优点)
**1.应用更快速的交付和部署**

传统:一堆帮助文档,安装程序

Docker:打包镜像发布测试,一键运行

2.更快捷的升级和扩缩容

使用docker,将应用打包成镜像后,服务器A坏掉了,所以服务器B要接替运行,此时直接将镜像,放到服务器B上,直接运行就行了

项目要升级了,需要升级环境(redis5 romcat 8 …),学docker之前需要一个一个的将环境升级。学docker之后,只要将这些环境打包,然后整体升级。

3.更简单的系统运维

在容器化之后,docker把应用程序和它所需要的环境锁死在一起。然后运维人员就不用管环境配置了。所以系统变得简单和高效。

4.更高效的计算资源利用

docker是内核级别的虚拟化,可以在一个物理机上运行很多的容器实例!服务器的性能可以被压缩到极致。

docker的基本组成

![](https://i-blog.csdnimg.cn/img_convert/104d2dbaf1aebfb0e91ae798cf080568.png)

镜像(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的流程图:

![](https://i-blog.csdnimg.cn/img_convert/badf12df4cb9798bf77cd08847c3edd7.png)

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>
下载镜像的时候,可以看到是一层一层的在下载。

![](https://cdn.nlark.com/yuque/0/2025/png/50435661/1757129191073-e5a6d96d-f79c-496d-b9fc-c83b23f9549a.png)

思考: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/bash

2.发现官方默认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上面。反而言之一样,因为挂载是双向映射)

![](https://cdn.nlark.com/yuque/0/2025/png/50435661/1757154501885-bf5ea220-80a1-4c80-9f01-c415a3d463b4.png)

为什么要用容器卷技术?  总结:为了容器的持久化和同步操作。容器间也可以数据共享。

<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发布自己的镜像
![](https://i-blog.csdnimg.cn/img_convert/fe2c85c894829d4dd16b9f90698fd515.png)

docker所有流程小结

![](https://i-blog.csdnimg.cn/img_convert/51d69c86c99780a7031e6a13fc8b45b8.png)

使用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网络模型图:
![](https://i-blog.csdnimg.cn/img_convert/1a6be6c6e58f154f411314f01961b4ff.png)

结论: 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>

![](https://i-blog.csdnimg.cn/img_convert/0baeb714ebc1854ac39de209768a9c7f.png)



Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐