
本文前面的知识点介绍容器命令的时候说过一个cp命令可以把宿主机和容器的文件相互拷贝但是这种偏向于比较独立完整的单一文件有没有想过遇到成体系的数据怎么办比如整个数据库的数据base路径要落盘此时直接cp命令移动一定会出现问题那怎么办就算不出现问题一个数据库的数据就靠cp命令现实吗此时就用到了数据卷。它可以让宿主机的一个路径以共享文件夹的方式开发给多个容器因此数据卷的特点如下1数据卷可在容器之间共享或重用数据2卷中的更改可以直接生效且持久化的生效不会由于容器的断开而消失3数据卷中的更改不会包含在镜像的更新中也就是不会被commit打包进去因为它也属于运行数据的一种本质上是宿主机的文件4数据卷的生命周期一直持续到没有容器使用它为止但是当没有容器使用时也不会消失只是再次的成为了宿主机的一个普通路径容器添加数据卷有两种方式方式一在创建容器的时候你可以用-v参数添加容器卷dockerrun-it-v宿主机路径:容器路径 镜像名比如把安装Oracle的包共享到容器去[roothdp3 opt]cdwy/[roothdp3 wy]ll 总用量2295604drwxr-xr-x.8root root40968月212009database -rw-r--r--.1root root123926927010月619:05 linux.x64_11gR2_database_1of2.zip -rw-r--r--.1root root111141613110月620:27 linux.x64_11gR2_database_2of2.zip[roothdp3 wy]dockerrun-it-v/opt/wy:/opt/wy centos[root6f1543b2044e /]ls-ltotal48lrwxrwxrwx1root root7Nov32020bin -usr/bin drwxr-xr-x5root root360Dec610:31 dev drwxr-xr-x1root root4096Dec610:31 etc drwxr-xr-x2root root4096Nov32020home lrwxrwxrwx1root root7Nov32020lib -usr/lib lrwxrwxrwx1root root9Nov32020lib64 -usr/lib64 drwx------2root root4096Sep152021lostfound drwxr-xr-x2root root4096Nov32020media drwxr-xr-x2root root4096Nov32020mnt drwxr-xr-x1root root4096Dec610:31 opt dr-xr-xr-x142root root0Dec610:31 proc dr-xr-x---2root root4096Sep152021root drwxr-xr-x11root root4096Sep152021run lrwxrwxrwx1root root8Nov32020sbin -usr/sbin drwxr-xr-x2root root4096Nov32020srv dr-xr-xr-x13root root0Dec610:31 sys drwxrwxrwt7root root4096Sep152021tmp drwxr-xr-x12root root4096Sep152021usr drwxr-xr-x20root root4096Sep152021var[root6f1543b2044e /]cd/opt/[root6f1543b2044e opt]lswy[root6f1543b2044e opt]cdwy/[root6f1543b2044e wy]lsdatabase linux.x64_11gR2_database_2of2.zip linux.x64_11gR2_database_1of2.zip添加共享卷的时候并不一定需要容器内部和宿主机两者存在对应的路径其实就和插进去一块盘一样且默认对数据卷拥有读写权限你还可以通过查看容器结构来确定数据卷。这里说一个注意点老版本的docker中容器拥有数据卷的写权限时容器对数据卷的主路径是可以删除的就比如本例中的/opt/wy这个文件夹在容器里是可以删除的但是在新版本的docker中最多只能删除其内部的所有文件而不能删除主路径本身[root6f1543b2044e opt]cdwy/[root6f1543b2044e wy]lsdatabase linux.x64_11gR2_database_2of2.zip linux.x64_11gR2_database_1of2.zip[root6f1543b2044e wy]cd/opt/[root6f1543b2044e opt]lswy[root6f1543b2044e opt]rm-rf* rm: cannot removewy:Device or resource busy###不让你删除主路径###[root6f1543b2044e opt]lswy[root6f1543b2044e opt]cdwy/[root6f1543b2044e wy]ls-ltotal0言归正传有的时候数据卷对应的宿主机路径不会让你有写的权限因此可以运行如下命令:ro表示只读默认:rwdockerrun-it-v宿主机路径:容器路径:ro 镜像名如果你需要挂载多个数据卷则要输入多个-v而不是在一个-v后写此时要注意老版本docker这一步有个bug极端的时候run命令-v挂载数据卷后访问会报错cannot open directory:Permission denied这就需要加上--privilegedtrue这个参数但新版本我还没有遇到出现这个问题方式二DockerFile方式添加数据卷[roothdp3 wy]vimyfile FROM centos VOLUME[/opt/myfile/test01,/opt/myfile/test02]CMDechoOK!!!!CMD /bin/bash ~myfile[New]4L, 95C written[roothdp3 wy]ll 总用量4-rw-r--r--1root root9512月621:02 myfile[roothdp3 wy]dockerbuild-f/opt/wy/myfile-twy/centos.Sending build context to Docker daemon2.048kB Step1/4:FROM centos ---5d0da3dc9764 Step2/4:VOLUME[/opt/myfile/test01,/opt/myfile/test02]---Runningin4b6880c91d0f Removing intermediate container 4b6880c91d0f ---4bffb4a9ad2c Step3/4:CMDechoOK!!!!---Runningin44edd9f7322e Removing intermediate container 44edd9f7322e ---51a76bdc475f Step4/4:CMD /bin/bash ---Runningin8295fe0b4243 Removing intermediate container 8295fe0b4243 ---f605952bf91a Successfully built f605952bf91a Successfully tagged wy/centos:latest[roothdp3 wy]dockerimages REPOSITORY TAG IMAGE ID CREATED SIZE wy/centos latest f605952bf91a34seconds ago 231MB atguigu/mytomcat1.24f6fc450f49c4hours ago 680MB tomcat latest fb5657adc89211months ago 680MB centos latest 5d0da3dc976414months ago 231MB特别说明DockerFile方式添加数据卷有个很鬼畜的事情老版本你在dockerfile中写的都会是容器内部会生成的路径至于宿主机上的路径docker会给一个默认路径需要通过查看容器的结构信息才知道挂载哪里了。而新版本中当在容器中进入数据卷路径时会提示你该目录打不开这是因为新版本docker中已经不再是去生成数据卷路径然后挂载一个宿主机默认路径了而是只生成一个挂载点你想用它只能是在run的时候-v。同时拥有数据卷的容器通常被称作是数据卷容器此时一定有人在想run是新生成一个容器那怎么给已有的容器添加数据卷很抱歉的告诉你截至本文目前操作的最新版通通不支持给已有容器添加数据卷。已有的容器添加数据卷本文尝试去改容器的配置文件发现行不通随着容器的重启配置文件的相关内容就复原了说完了数据卷本章的下一个知识点叫容器直连。前面已经介绍过如何安装docker以及docker如何使用但各位读者在跟随知识点学习时一定发现一个小问题无论在KVM中还是VMware默认的网络NAT模式对于宿主机来讲虚拟化结果物是可见的当然需要是直接归属的宿主机Windows-》VMware-》KVM 这种最外层的Windows任然是访问不了虚拟化结果物的。外部想要发现结果物需要虚拟化技术的配置支持也就是桥接VMware内置了桥接基础页面点一点选中后就可以去配置相应的ip了到了KVM要自己创建一个桥接用的网卡路由后面的操作流程和VMware差不多。但是到了docker上各位读者想一想大家实际操作过网络模式吗除了前面知识点零星点点的遇到相关问题提到过网络相关的配置其实这是因为docker本身的立意是容器的即用即插从最开始老版本的默认只有回环网卡路由到后来宿主机内部局域网视容器为一个消耗品所以在网络策略上几乎可以说是没有自带的其他模式。但是它给开发者预留了自定义网络策略的能力此外给各位读者分享一个网络策略的技术经验。由于docker这种网络策略现状因此在其他架构以它为基础做容器平台时就能同时看出一家公司的技术实力怎么样就以K8s来讲原生版本下的k8s配合docker的效果是访问任何服务客户端都要去访问服务在k8s主节点上映射的端口K8s内部负责服务发现、负载均衡、灾难修复(就是极短时间内重启一个容器)这一套东西。但是在大体量的公司内部这种访问方式是不能满足使用的因此像百度、阿里这种企业都是通过二次开发K8s插件使得底层的容器能够像一个正常的服务器实例那样连接使用。此时肯定有人说K8s不是弃用Docker了吗不要被误导K8s只是从15版本开始不在默认内置对Docker的对接协议而是和对待其他虚拟化技术一样需要开发者自行安装协议插件到了18版本才实际删除了内置的Docker-CRI协议回归正题在各位读者学习Docker阶段因当知道如何通过自定义网络策略来实现容器可以让外部当做普通的服务器实例来连接。但本文在此强调一点有看过前面KVM的读者不要把下面的操作和kvm知识点中的桥接混淆docker严格意义上来讲就没有桥接、nat等等的分别它只是预定义一个网络IP策略如同操作一台物理机把IP改成其他的不合理网段就无法上网一样只是IP策略不同而不是网络底层实现的不同。至于KVM甚至是VMware想正常使用桥接必须整个链路都是桥接既各自的宿主机可在网络中被其他主机直接发现。甚至IP上在实际使用中也会在指定网络模式时给定一个IP而不是让容易默认自动获取首先docker容器的网络配置自带了三类但其实相当于没有。自带的bridge相当于VMware的NAT但注意由于该模式采用的网络模块是一个老版本docker的内置模块并沿用至今底层实现的缺陷导致它创建出来的容器没有DNS功能。host模式很少使用它是指容器完全没有自己的网络配置直接使用宿主机的网卡这种网络模式相当于让容器默认走了IP映射但还需创建容器时显示配置IP映射考虑到灵活的使用方式通常根本不考虑这种网络模式。最后一个nono是预留的空网络无法使用。[roothdp3 ~]# docker network lsNETWORK ID NAME DRIVER SCOPE e8e4f692235d bridge bridgelocal4d563e307658hosthostlocal7bfee5177ee6 none nulllocal自定义网络模式的时候用的是docker自带的macvlan模块(DRIVER)这是docker后期版本中提出的一种新型的网络模块可以提供更加灵活的网络。配置的时候先运行下面的命令创建一个网络模式。由于本文的目的时容器直连所以网络策略和宿主机相同做一个桥接效果的网络模式。从实现上来说完全可以使用自定义网络模式配置其他网段这个就看实际需求了dockernetwork create clu--drivermacvlan--subnet192.168.88.0/24--gateway192.168.88.2-omacvlan_modebridge-oparentens33clu创建的网络模式名字自定义--driver macvlan使用macvlan网络模块这个通常不变--gateway该网络模式使用的网关--subnetCIDR格式的IP范围表达书下面会介绍怎么写这个配置。这里如果各位读者和本文书写时操作的环境同样时基于Vmware的一个虚拟机则改动前三位符合你的网关即可-o其他详情配置上面命令中是指基于bridge模式并继承宿主机的网卡ens33是宿主机的网卡名创建好后查询一下重点关注 DRIVER 采用的网络模块现在创建的和自带的不一样[roothdp3 ~]dockernetworklsNETWORK ID NAME DRIVER SCOPE e8e4f692235d bridge bridgelocal2cd5c6656669 clu macvlanlocal4d563e307658hosthostlocal7bfee5177ee6 none nulllocal随后当创建容器的时候就可使用--net参数使用这个新的网络模式dockerrun-it--netclu--ip192.168.88.191 centos:7.8.2003--net指定网络模式--ip是给容器一个IP其实可以不指定用随机的还可以在创建网络模式的时候用--ip-range参数限制随机的ip范围但是正式使用都是静态IP上面这种命令创建容器之后该容器就和你的宿主机所在同一网段并且可以被其他的设备直接发现比如我在本地Windows上ping一下此时容器存在了并且可以外部网络发现但无法外部连接因为结合前面做镜像的知识点应该不难明白现在这个容器没有SSH软件毕竟本来就是即插即用的容器考虑到SSH软件不必要所以就没自带至少centos的docker镜像是这样的只有最基本的rootfs文件。并且前面介绍docker命令知识点时留下一个特权模式的小尾巴就在这里统一介绍。因为要安装服务并且启动等等要用到系统管理命令所以直连的容器自身必然是一个特权容器#新建一个特权容器dockerrun-d--netclu--ip192.168.88.190--privilegedtrue centos:7.8.2003 /usr/sbin/init#进入容器dockerexec-itf063be0bd990 /bin/bash进入容器后你需要保证有正常且可用的用户身份和资源这里通过passwd命令重置root密码并自动生成对应的资源这里要明白一个问题你进入容器其实是进入了一个shell命令行终端终端这两个字非常重要 在终端中passwd命令后的井号部分 意思是你当前是就是root用户你要对自己的密码进行重置这就可以不用经过输入旧密码的那一套 这个涉及到系统层面的东西比较复杂这里不要多想无脑用就行[rootf063be0bd990 /]passwd# add rootChanging passwordforuser root. New password: BAD PASSWORD: The password is shorter than8characters Retype new password: passwd: all authentication tokens updated successfully.调整yum源这里不展示了自己网上搜一下随后安装SSH并启动它yuminstall-yopenssh-* initscripts[roottest01 /]/etc/init.d/sshd start Starting sshd(via systemctl):[OK][roottest01 /]/etc/init.d/sshd status ● sshd.service - OpenSSH server daemon Loaded: loaded(/usr/lib/systemd/system/sshd.service;enabled;vendor preset: enabled)Active: active(running)since Sat2022-12-10 09:25:10 UTC;20s ago Docs: man:sshd(8)man:sshd_config(5)Main PID:368(sshd)CGroup: /system.slice/docker-2441cd39fce5d3de267a18ff2076c970eb7e61505db88c4bcf9b72e9ab5b17e0.scope/system.slice/sshd.service └─368 /usr/sbin/sshd-D‣368/usr/sbin/sshd-DDec1009:25:10 test01 systemd[1]: Starting OpenSSH server daemon... Dec1009:25:10 test01 sshd[368]: Server listening on0.0.0.0 port22. Dec1009:25:10 test01 sshd[368]: Server listening on :: port22. Dec1009:25:10 test01 systemd[1]: Started OpenSSH server daemon.此时就可以用SSH连接工具直接连接了。要说明的是之所以上面日志中计算机名称位置叫test01是因为本文把容器的主机名也改了看的更像一个单独的系统如果需要像本文中这样改已有容器的主机名部分需要关闭容器、关闭 docker 服务!!!!一定要把服务也关闭之后进入容器在宿主机上的配置文件中就在本地docker仓库的containers文件夹下根据容器id进入对应的文件夹找到搜索含有你要修改的容器id的配置文件注意在新创建容器时可以指定--hostname参数改变容器的主机名称[roothdp3 2441cd39fce5d3de267a18ff2076c970eb7e61505db88c4bcf9b72e9ab5b17e0]# pwd/opt/docker/containers/2441cd39fce5d3de267a18ff2076c970eb7e61505db88c4bcf9b72e9ab5b17e0[roothdp3 2441cd39fce5d3de267a18ff2076c970eb7e61505db88c4bcf9b72e9ab5b17e0]# ll总用量32-rw-r-----1root root012月1016:55 2441cd39fce5d3de267a18ff2076c970eb7e61505db88c4bcf9b72e9ab5b17e0-json.log drwx------2root root409612月1016:55 checkpoints -rw-------1root root295912月1016:59 config.v2.json -rw-r--r--1root root120112月1016:59 hostconfig.json -rw-r--r--1root root1312月1016:55hostname-rw-r--r--1root root15012月1016:59 hosts drwx------3root root409612月1016:55 mounts -rw-r--r--1root root5312月1016:55 resolv.conf -rw-r--r--1root root7112月1016:55 resolv.conf.hash修改两个文件分别是config.v2.json、hostname比如本例中要修改的容器id是2441cd39fce5就在配置文件中用id搜下面的内容config.v2.jsonhostname最后重启docker服务和容器进入容器你就会发现主机名成功修改[roothdp3 2441cd39fce5d3de267a18ff2076c970eb7e61505db88c4bcf9b72e9ab5b17e0]dockerexec-it2441cd39fce5 /bin/bash[roottest01 /]#最后说一下创建网络模式时的CIDR取值问题。CIDR的格式是IP/网络ID前面的IP是一个网络IP段的表达式重点是网络ID这个ID是让人迷糊的罪魁祸首。如果使用的网络是IPV4的时候它最大有效值是32本质作用是用来表示网络策略所用的IP类型传统的意义上网络IPV4类型分为三类ABC总共是四组二进制但用十进制展示的数字来表示A类网络的默认起始掩码是255.0.0.0B类默认起始是255.255.0.0C类默认起始是255.255.255.0。翻译成二进制来看也就是说整个传统网络IPV4策略中从a到c类的子网默认掩码的范围是11111111.00000000.00000000.00000000到11111111.11111111.11111111.11111111而这里面网络ID就是所处网段所用掩码翻译成二进制后有几个1理论上来讲id值的大小决定了该IP策略所处的网段类型A类所能容纳的IP最多所能配置的网络也就越因此灵活反之C类最次所以一般公司里面使用的都是A类地址所以子网掩码会遇到10开头甚至更靠前的ip。有很多人看到这里很可能会以为子网掩码可以从四个1开始一直往后枚举到四个255打住这个想法因为并不是所有的子网掩码都是有效的子网掩码一个有效的子网掩码它的二进制一定是一串1开头并以一串0结尾或者反过来如果中间出现混杂则此掩码无效当然这只是为了让大家明白这里用到的网络ID是什么真正的要说了解网络掩码的原理是一个很复杂庞大的东西大家如非需要则没必要了解太深。上文中因为用的是vmware虚拟机做宿主机网络策略是192的一个c类地址所以子网掩码应该是255.255.255.0换算成CIDR网络ID就是24