极客时间运维进阶训练营第一周作业

极客时间|训练营 X 马哥教育

 

第一周作业要求:
梳理各 Namespace 的作用。
使用 apt/yum/ 二进制安装指定版本的 Docker。
熟练使用 Docker 数据卷。
熟练使用 Docker 的 bridge 和 container 模式网络。
 
 
课程主讲简介:张Sir/杰哥
    十年以上业务运维与架构工作;曾主导过大数据、支付、电商等业务的云生态建设;
    规划并落地了多个企业项目的私有云平台规划与落地、业务容器化、日志收集、监控与告警平台、异地多活、CI/CD及弹性伸缩;
    对于业务上云、云上服务维护、服务编排、海量数据监控、分布式存储、云原生等领域有着丰富的企业案例;
    目前担任某一线大厂云原生架构师。
 
 
Linux容器技术基础、CGroups及Namespaces是docker运行容器的核心技术。
容器就是直接脱离操作系统直接承载服务启动的“软件集装箱”(装载各种服务器的服务项目的容器)。
目前主流的容器技术是下列几项:
docker截止2022年为止最主流的容器技术-https://www.docker.com
docker开源的子项目containerd,将其贡献给了CNCF基金会;以后非常有可能替换docker而成为主流的容器技术-https://containerd.io
谷歌开源的gvisor(目前使用者比较少)-https://gvisor.dev
RedHat开源的podman(到现在为止使用依然很少)-https://podman.io
目前主流主要还是在使用docker,此次主讲老师的课程主要围绕着docker的容器技术展开讲解。
 
容器的优势:
一次构建镜像,通过镜像仓库共享,在相同的容器软件中到处可运行。即:把代码/服务打包到静态的镜像中,再将镜像上传到仓库;(保存镜像和分发进程的地方)
目前主要是使用Harbor,容器运行需要镜像(它是人为使用docker file构建的);
在内网/公司内部的主机/虚拟机通过网络可以访问镜像仓库,就可以把镜像下载到本地主机,通过容器技术把这个服务运行起来;
容器数量太多无法通过手动创建就需要容器编排技术kubernetes(k8s)进行自动化构建容器;(此前提需要有镜像提供给k8s,因为在k8s中镜像至关重要,如果没有镜像就没法将业务容器化)
docker是构建镜像的工具——在一个企业内部需要有人去打包镜像,要么开发人员,要么是运维工程师去做……有了镜像之后再通过k8s进行编排,这个过程是有相互依赖关系的。
 
创建容器服务以及对容器进行资源限制,都是通过k8s调度实现。这个流程是单向的,先构建镜像;镜像构建成功后上传到镜像仓库;再运行容器的创建、更新。
 
构建任意应用程序的镜像(build)--->基于镜像仓库实现镜像分发(share)--->基于k8s实现容易统一编排(run)。
 
 
Cloud Native技术的演进——云原生使用开源软件实现如下企业需求:
 将应用程序细分为微服务;
 将每个微服务封装装到独自的容器环境运行;
 动态编排业务容器并提高资源利用率;
 实现业务容器动态弹性伸缩。
 
在docker之前主流是使用虚拟化技术,路径演进如下图:
 1979年,Unix v7系统支持chroot,为应用构建一个独立的虚拟文件系统环境;
 1999年,FreeBSD 4.0支持jail,是第一个商用化的OS虚拟化技术;
 2004年,Solaris 10支持Solaris Zone,第二个商用化的OS虚拟化技术;
 2004~2007年,Google 内部大规模使用Cgroups等OS虚拟化技术;
 2006年,Google开源内部使用的process container技术,后续更名为cgroup;
 2008年,Cgroups进入了Linux内核主线;
 2008年,LXC(Linux Container)项目具备了Linux容器的雏型;
 2013年,Docker项目正式发布,让Linux容器技术逐步席卷天下;
 2014年,Kubernetes项目正式发布,容器技术开始和编排系统起头并进;
 2015年,由Google,Redhat、Microsoft及一些大型云厂商共同创立了CNCF(Cloud Native Computing Foundation);
 2016~2017年,容器生态开始模块化、规范化,CNCF接受Containerd、rkt项目,OCI发布1.0,CRI/CNI得到广泛支持;
 2017~2018年,容器服务商业化,AWS、Google云、阿里云、华为云、VMware,Redhat和Rancher等公司开始提供基于Kubernetes的商业服务产品;
 2019~2021年,容器引擎技术飞速发展,新技术不断涌现,CNCF日益庞大;
 截止2022年,CNCF聚集的贡献者超过17万、有130+项目、涉及全球187个国家。
 
  • OCI 1.0 定义了镜像标准,容器运行时标准等等:
    • CRI-容器运行接口(设计容器环境,例如containerd、rkt需要执行此标准);
    • CNI-容器网络接口(在k8s中运行容器且需要为容器提供网路支持的情况下要符合CNI标准)。
 
到目前为止(2022年)一线大厂的业务几乎100%将服务容器化,例如,京东、快手、腾讯、阿里等。使用容器可以调度的服务包括,如:nginx、java服务及数据库都是基于容器运行的。
使用容器技术主要目的是解决上一代虚拟技术的瓶颈问题,在之前的虚拟机环境中,当服务越来越多时在虚拟机部署服务会变得越来越麻烦,例如,环境隔离、代码回滚在虚拟机上每做一次横向扩容,都需要以虚拟机为单位,创建新的虚拟机,在虚拟机中做环境的标准化,通过这一系列操作至加载后才能将代码部署至服务中去运行(如需负载均衡还要手动配置);这会导致人员和时间成本急剧增高!
例如,当开始一个运维项目时,如果是在容器技术之前的虚拟机环境任务中需要做扩容,即:首先在openstack中去创建虚拟机,虚拟机创建完成后再远程登陆上去,做环境标准化、配JDK、优化系统(内核参数调整、资源限制等)后再把服务和代码都部署到虚拟机中去。并且还需要做测试,测试完成后再去配置负载均衡。通过一些列猛如虎的操作再快也需要30分钟左右。这在业务高峰期手工部署运维确实很难完成。需要快速扩容、弹性伸缩,秒级扩容,减少人为操作带来可能产生的错误;所以在此容器和容器编排技术应运而生。在容器中的配置完成的服务都是通过同一个镜像部署的,配置好的环境都是直接打包至镜像的,所以只要在完成的第一镜像可以正常运行,后续只要在硬件资源充足的条件下,通过同一个的镜像提供的多少服务都不会有问题。
 
Docker发展的历史进程:
Docker是一个在2013年开源的应用程序并且是一个基于go语言编写是一个开源的PAAS项目,Docker公司最早叫dotCloud,后由于Docker开源后大受欢迎就将公司改名为 Docker Inc,总部位于美国加州的旧金山,Docker是基于linux 内核实现,Docker最早采用LXC技术(LinuX Container的简写,LXC是Linux 原生支持的容器技术,可以提供轻量级的虚拟化。2016年04月,Docker后改为自己研发并开源的runc技术运行容器(1.11.0),在2016年12月捐献了container项目。
 Docker 相比虚拟机的交付速度更快、资源消耗更低,Docker 采用客户端(docker-client)/服务端(docker-server)架构,使用远程API来创建docker和管理容器,其可以轻松的创建一个轻量级的、可移植的、自给自足的容器环境,Docker 的三大理念是build(构建)、Share(分享)、run(运行),Docker遵从apache 2.0协议,并通过(namespace及cgroup等)来提供容器的资源隔离与安全保障等,所以Docker容器在运行时不需要类似虚拟机(空运行的虚拟机占用物理机的一定性能开销)的额外资源开销,因此可以大幅提高资源利用率,总而言之Docker是一种用了新颖方式实现的轻量级虚拟机,类似于VM但是在原理和应用上和VM的差别还是很大的。
 
Docker的组成:
 Docker 主机(Host):一个物理机或虚拟机,用于运行Docker服务进程和容器;
 
 Docker 服务端(Server):Docker守护进程,运行docker容器;
 Docker 客户端(Client):客户端使用docker 命令或其他工具调用docker API;
 
 Docker 仓库(Registry): 保存镜像的仓库,类似于git或svn这样的版本控制系;
 
 Docker 镜像(Images):镜像可以理解为创建实例使用的模板;
 
 Docker 容器(Container): 容器是从镜像生成对外提供服务的一个或一组服务。
 
 
 
容器相对于虚拟机的优势:
 资源利用率更高:一台物理机可以运行数百个容器,但是一般只能运行数十个虚拟机;
 开销更小:不需要启动单独的虚拟机占用硬件资源;
 启动速度更快:可以在数秒内完成启动;
     在一个宿主机上通过多个虚拟机的形式运行多个APP服务,也可以通过在单独每个容器运行一个APP的方式实现;
     目的是为了实现环境隔离的同时运行多个APP。
 
 
 
 
容器的优缺点对比:
 优点)
 快速部署:短时间内可以部署成百上千个应用,更快速交付到线上;
 高效虚拟化:不需要额外的hypervisor支持,直接基于linux 实现应用虚拟化,相比虚拟机大幅提高性能和效率;
 节省开支:提高服务器利用率,降低IT支出;
 简化配置:将运行环境打包保存至容器,使用时直接启动即可;
 快速迁移和扩展:可夸平台运行在物理机、虚拟机、公有云等环境,良好的兼容性可以方便将应用从A宿主机迁移到B宿主机,甚至是A平台迁移到B平台。
 
 缺点)
 隔离性,容器底层无内核,靠主进程隔离;
 为了解决原虚拟机引申的主机的套接字和主机名及root用户的问题,发展了Namespace技术;
 因隔离性问题会随之带来安全问题。
 
 
梳理各Namespace的作用:
 Namespace是Linux系统的底层概念,在内核层实现。(https://zh.m.wikipedia.org/zh/%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4
有一些不同类型的命名空间被部署在核内,每个Docker容器运行在同一个Docker主进程并且共用同一个宿主机的操作系统内核,每个Docker容器运行在宿主机的用户空间,同时每个容器都要有类似于虚拟机一样的相互隔离的运行空间,但是容器技术是在一个进程内实现运行指定服务的运行环境,并且还可以保护宿主机内核不受其他进程的干扰和影响;如文件系统空间、网络空间、进程空间等的相互隔离。
 
        隔离类型
        功能
        系统调用参数
        内核版本
MNT Namespace(mount)
提供磁盘挂载点和文件系统的隔离能力
CLONE_NEWNS
Linux 2.4.19
IPC Namespace(Inter-Process Communication)
提供进程间通信的隔离能力
CLONE_NEWIPC
Linux 2.6.19
UTS Namespace(UNIX Timesharing System)
提供主机名隔离能力
CLONE_NEWUTS
Linux 2.6.19
PID Namespace(Process Identification)
提供进程隔离能力
CLONE_NEWPID
Linux 2.6.24
Net Namespace(network)
提供网络隔离能力
CLONE_NEWNET
Linux 2.6.29
User Namespace(user)
提供用户隔离能力
CLONE_NEWUSER
Linux 3.8
Time Namespace
提供时间隔离能力
CLONE_NEWTIME
Linux 5.6
Syslog Namespace
提供syslog隔离能力
syslog namespace首先是由华为的工程师RuiXiang(瑞翔)提出的,但没有合并到Linux内核,之后systemd在2020年2月实现了一个名为journal namespace的类似功能
Control group(cgroup)Namespace
提供进程所属的控制组的身份隔离
Linux 4.6
使用容器技术使用Linux内核版要大于3.8以上,也是使用CentOS的版本不能低于7。文件系统类型为ext的不能低于4,也就是ext2和ext3对于容器的支持有限,不适合使用。
 
Cgroups在内核层默认已经开启,从centos和ubuntu 对比结果来看,内核较新的ubuntu 支持的功能更多。
root@docker-server1:~#cat /boot/config-5.15.0-43-generic | grep CGROUP | grep -v "^#" | wc -l
22
root@docker-server1:~#cat /boot/config-5.15.0-43-generic | grep MEM | grep CG | grep -v "^#"
CONFIG_MEMCG=y 
CONFIG_MEMCG_SWAP=y 
CONFIG_MEMCG_KMEM=y

 

 容器技术除了的docker之外,还有其它不同的容器技术,为了保证容器生态的标准性和健康可持续发展,包括Linux基金会、Docker、微软、红帽谷歌和IBM、华为等公司在2015年6月共同成立了一个叫open container(OCI)的组织,其目的就是制定开放的标准的容器规范,目前OCI发布了runtime spec(运行时规范)、image format spec(镜像格式规范)、distribution-spec(镜像分发规范),这样不同的容器公司开发的容器只要兼容以上规范,就可以保证容器的可移植性和相互可操作性。 
容器runtime(runtime spec): 
  • 常见的runtime:
    • runc:目前Docker和containerd默认的runtime,基于go语言开发,遵循OCI规范;
    • crun:redhat推出的运行时,基于c语言开发,集成在podman内部,遵循OCI规范;
    • gVisor:google推出的运行时,基于go语言开发,遵循OCI规范。
低级容器运行时与高级容器运行时:
 High-Level:高级运行时提供基于API的远程管理操作,客户端可以通过高级别运行时管理容器的整个生命周期(创建、删除、重启、 停止),高级别运行时并不真正直接运行容器,而是调用低级别运行时运行,比如dockerd、containerd都是高级别运行时;
 Low-Level :接受高级别运行时的指令,按照响应的指令运行容器,因此低级别运行时真是运行容器的地方,例如runc。
 
OCI(Open Container Initiative):2015年Google、docker、Redhat、IBM共同成立,定义了运行标准和镜像标准。 CRI(Container Runtime Interface):2016 年12月Kubernetes 发布 CRI(容器运行时接口), 可以支持rkt等不同的运行时。
CRI-O:由redhat发起并开源,用于替代docker成为kubernetes的运行时,2016年开发,2019年4月8号进入 CNCF孵化。
unix:///var/run/dockershim.sock( k8s version ≤1.23 default)---> unix:///var/run/docker.sock
unix:///var/run/cri-dockerd.sock( k8s version ≥1.24)------------>unix:///var/run/docker.sock
unix:///run/containerd/containerd.sock
unix:///run/crio/crio.sock
 
验证docker 信息: 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
~#docker info
Containers: 2 #当前主机运行的容器总数
Running: 1 #有几个容器是正在运行的
Paused: 0 #有几个容器是暂停的
Stopped: 1 #有几个容器是停止的
Images: 3 #当前服务器的镜像数
Server Version: 20.10.18 #服务端版本
Storage Driver: overlay2 #当前使用的存储引擎
Backing Filesystem: xfs #后端文件系统,即服务器的磁盘文件系统
Supports d_type: true #是否支持d_type
Native Overlay Diff: true #是否支持差异数据存储
userxattr: false #是否在挂载文件系统启用对扩展用户属性的支持(如文件的 mime 类型、字符集或编码)
Logging Driver: json-file #日志类型
Cgroup Driver: systemd #Cgroups类型,19.03及之前为Cgroups
Cgroup Version: 2 #Cgroup 版本
Plugins: #插件
Volume: local #支持的卷插件
Network: bridge host macvlan null overlay # overlay夸主机通信
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog #日志类型
Swarm: inactive #是否支持swarm
Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc #已安装的容器运行时
Default Runtime: runc #默认使用的容器运行时
Init Binary: docker-init #初始化容器的守护进程,即pid为1的进程
containerd version: 9cd3357b7fd7218e4aec3eae239db1f68a5a6ec6 #版本
runc version: v1.1.4-0-g5fd4c4d # runc版本
init version: de40ad0 #init版

 

Docker存储引擎:

 Overlay:UnionFS文件系统,Linux内核3.18后支持;

 overlay2: Overlay的升级版,到目前为止,所有Linux发行版推荐使用的存储类型;

 devicemapper:是CentOS和RHEL的早期使用的存储驱动程序,因为之前的内核版本较低不支持overlay2,但是当前较新版本的CentOS和RHEL现在已经支持overlay2,因此推荐使用overlay2;

 ZFS(Sun-2005)/btrfs(Oracle-2007):目前没有广泛使用;

 vfs: 用于测试环境,适用于无法使用copy-on-write文件系统的情况。 此存储驱动程序的性能很差,通常不建议用于生产环境;

 AUFS(Another UnionFS): 是早期的一种UnionFS文件系统的实现,是Docker 18.06及更早版本使用的存储引擎。

 

 https://docs.docker.com/storage/storagedriver/select-storage-driver/

 

以下是Docker配置参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
~# cat /etc/docker/daemon.json
{ "graph": "/var/lib/docker" ,
"storage-driver": "overlay2" ,
"insecure-registries": ["harbor.magedu.com" , "harbor.myserver.com" , "192.168.1.16"],
"registry-mirrors": ["https://9916w1ow.mirror.aliyuncs.com"],
"exec-opts": ["native.cgroupdriver=systemd"],
"live-restore": false,
"log-opts": {
    "max-file": "5" ,
    "max-size": "100m"
  }
}
~# systemctl restart docker

 注意:centos 7.2及之前的版本默认使用devicemapper存储引擎,不能直接使用overlay存储引擎,除非新添加一快磁盘作为docker的数据盘, 并在格式化的时候指定格式化参数-n ftype=1,否则报错。但是,Centos 7.3版本开始修复此问题。

镜像管理操作步骤:

1、制作镜像;

2、上传镜像;

3、下载镜像;

4、查找镜像;

5、导出镜像/导入镜像;

6、删除镜像;

7、查询镜像。

命令如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
~# docker image --help
Usage: docker image COMMAND
Manage images
Commands:
build #从Docker文件构建新的镜像
history #查询镜像的构建历史
import #从本地或远程的压缩包等导入镜像,可以指定导入后的镜像名称
inspect #显示一个或多个镜像的详细信息
load #从一个tar包或标准输入导入镜像
ls #列出本地的所有镜像
prune #删除本地未使用的镜像
pull #从镜像仓库下载镜像到本地
push #从本地上传镜像到镜像仓库
rmi #删除一个或者多个本地镜像
save #保存一个或者多个镜像到一个tar包(默认保存到当前终端的标准输出)
tag #对镜像打一个新的标签
 
~# docker search centos #搜索镜像

Docker命令详解:  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# docker run -it centos:7.9.2009 # docker attach 63fbc2d5a3ec #attach进入容器后操作会在多窗口同步且退出后其它终端也会一起退出。
# docker build #从dockerfile构建镜像
# docker commit -a "jack jack@magedu.com" -m "v2" --change="EXPOSE 80 443" 8ddf4ce923ef new-nginx-image #将容器提交为一个本地镜像
# docker cp 源 目的 #从容器和宿主机相互拷贝文件或目录
# docker create -it --name test1 nginx:1.20.2 #创建一个新的容器且创建后的容器处于退出状态
# docker diff 8ddf4ce923ef #对比容器和镜像有差异的文件或目录
# docker events #获取dockerd的实时事件,创建删除容器等操作
# docker exec -it 40e6379cf371 sh/bash #推进入到容器执行命令操作,推荐使用此方式
# docker export 8ddf4ce923ef -o new-nginx-image.tar.gz #将容器的文件系统导出为一个本地压缩包,非镜像格式
# docker history centos:7.9.2009 #查看的镜像的构建历史
# docker images #查看本地所有镜像
# docker import new-nginx-image.tar.gz #导入export导出的压缩包,导入后的镜像不完整,不能用于创建容器
# docker info #显示系统信息
# docker inspect 50fe74b50e0d #显示docker对象(镜像、网络、容器等)的详细信息
# docker kill $(docker ps -a -q) 强制关闭所有运行中的容器
# docker load -i nginx-1.20.2.tar.gz #从一个tar包或标准输入导入镜像
# docker login #登录镜像仓库
# docker logout #登出镜像仓库
# docker logs -f nginx-container-test1 #持续查看容器标准输出和错误输出的日志
# docker pause 81b344cff55d #暂停一个或者多个容器
# docker port 81b344cff55d #列出一个容器端口映射关系
# docker ps #列出容器,加上-a是列出包含为运行的所有容器
# docker pull nginx:1.20.2 #从镜像仓库下载镜
# docker push nginx:1.20.2 #从本地上传镜像到镜像仓库(需要登录认证)
# docker rename awesome_cerf nginx-container1 #重命名容器
# docker restart ID/容器名称 #重启容器
# docker rm -f 11445b3a84d3 #强制删除运行中的容器
# docker rm -f `docker ps -aq -f status=exited` #批量删除已退出容器
# docker rm -f $(docker ps -a -q) #批量删除所有容器
# docker rmi -f 53ec353d8dc4 90a4cd9dfe4c #删除一个或多个镜像
# docker run -it docker.io/centos bash #创建并进入容器,ctrl+p+q退出容器不注销
# docker run -it --name nginx-test1 nginx:1.20.2 #自定义容器名称
# docker run -p 80:80/tcp -p 443:443/tcp -p 53:53/udp --name nginx-container-test1 nginx:1.20.2 #创建容器并指定多端口映射
# docker run -d -p 80:80 --name nginx-container-test1 nginx:1.20.2 #后台运行容器
# docker run -it --rm --name nginx-delete-test nginx:1.20.2 bash #单次运行容器
# docker run -it -d centos:7.9.2009 /usr/bin/tail -f '/etc/hosts' #创建容器的时候传递命令及参数
# docker save 50fe74b50e0d > nginx-1.20.2.tar.gz #保存一个或多个镜像到一个压缩文件(默认是标准输出)
# docker search nginx #搜索镜像
# docker start ID/容器名称 #启动一个或多个容器
# docker stats #显示容器资源的实时统计信息
# docker stop ID/容器名称 #停止一个或多个容器
# docker tag nginx:1.20.2 harbor.magedu.net/myserver/nginx:1.20.2 #为镜像添加一个新的tag
# docker unpause 81b344cff55d #取消一个或多个容器的暂停
# docker update 容器 --cpus 2 #更新容器配置信息,比如资源限制的值
# docker version #显示docker client和docker server的版本信息
# docker wait #一直等待容器退出并显示容器的退出状态码 

Docker数据管理:

如果正在运行中的容器修如果生成了新的数据或者修改了现有的一个已经存在的文件内容,那么新产生的数据将会被复制到读写层进行持久化保存,这个读写层也就是容器的工作目录,此即“写时复制(COW) copy on write”机制。

 如下图是将对根的数据写入到了容器的可写层,但是把/data中的数据写入到了一个另外的volume中用于数据持久化。

 

 Lower Dir:image镜像层(镜像本身,只读);

 Upper Dir:容器的上层(读写);

 Merged Dir:容器的文件系统,使用Union FS(联合文件系统)将lowerdir和upper Dir:合并给容器使用;

 Work Dir:容器在宿主机的工作。

 

 Docker的镜像是分层设计的,镜像层是只读的,通过镜像启动的容器添加了一层可读写的文件系统,用户写入的数据都保存在这一层当中;

 如果要将写入到容器的数据永久保存,则需要将容器中的数据保存到宿主机的指定目录,目前Docker的数据类型分为两种:

  一是数据卷(data volume),数据卷实际上就是宿主机上的目录或者是文件,可以被直接mount到容器当中作为容器的本地文件系统使用,实际生产环境中,需要针对不同类型的服务、不同类型的数据存储要求做相应的规划,最终保证服务的可扩展性、稳定性以及数据的安全性;

    (基于数据卷通过将宿主机的文件或目录挂载到容器的指定目录,当容器中的挂载目录产生的新数据即可间接的保存到宿主机以实现持久化的目的)

  二是数据卷容器(Data volume container), 数据卷容器是将宿主机的目录挂载至一个专用的数据卷容器,然后让其他容器通过数据卷容器继承挂载的目录或文件,以实现将新产生的数据持久化到宿主机的目的。

 

创建数据卷:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# docker volume create nginx-data
# docker volume ls
DRIVER VOLUME NAME
local nginx-data
 
# docker run -it -d -p 80:80 -v nginx-data:/data nginx:1.20.2
4445e4640c74e1c503a7f8c704270abd58c5bc70aacf600e39945f7fd74ac810
 
# docker exec -it 4445e4640c74 bash
root@4445e4640c74:/# echo "nginx web" > /data/index.html
root@4445e4640c74:/# exit
exit
 
root@docker-server1:~# ls /var/lib/docker/volumes/nginx-data/_data/index.html
/var/lib/docker/volumes/nginx-data/_data/index.htm

数据目录挂载:

以数据卷的方式,将自定义的宿主机目录或文件提供给容器使用,比如容器可以直接挂载宿主机本地的数据目录(如mysql容器的数据持久化)、 配置文件(如nginx的配置文件)、静态文件(如web服务的图片或js文件)等,只需要在创建容器的时候指定挂载即可。

1
2
3
4
5
6
7
8
9
# mkdir /data/testapp –p
# echo "testapp web page" > /data/testapp/index.html
# cat /data/testapp/index.html
testapp web page
 
/*启动两个测试容器,web1容器和web2容器,分别测试能否访问到宿主机的数据,注意使用-v参数,将宿主机目录映射到容器内部,web2的ro表示在容器内对该目录只读,默认的权限是可读写的:*/
 
# docker run -d --name web1 -v /data/testapp:/usr/share/nginx/html/testapp -p 80:80 nginx:1.20.2
# docker run -d --name web2 -v /data/testapp:/usr/share/nginx/html/testapp:ro -p 81:80

数据目录及配置多卷挂载:  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//nginx多卷挂载:
# mkdir /data/nginx/conf -p
# docker cp web1:/etc/nginx/nginx.conf /data/nginx/conf/
# docker run -d --name web3 -v /data/testapp:/usr/share/nginx/html/testapp -v
/data/nginx/conf/nginx.conf:/etc/nginx/nginx.conf:ro -p 83:80 nginx:1.20.2
 
//mysql容器:
# docker pull mysql:5.7.38
# docker run -it -d -p 3306:3306 -v /data/mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7.38
48e88061e80b9983d0d735f29a176efb810de32f0bd30e12893def798783b9d9
 
# mysql -uroot -p123456 -h172.31.6.201
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
 
mysql>

删除容器:  

1
2
3
4
5
创建容器的时候指定参数会删除/var/lib/docker/containers/的容器数据目录,但是不会删除数据卷的内容,如下:
 
# docker rm -f web3
# ls /data/testapp/index.html
/data/testapp/index.html #挂载的数据卷不会被删除

数据卷的特点及使用:
   数据卷是宿主机的目录或者文件,并且可以在多个容器之间共同使用;
   在宿主机对数据卷更改数据后会在所有容器里面会立即更新;
   数据卷的数据可以持久保存,即使删除使用使用该容器卷的容器也不影响;
   在容器里面的写入数据不会影响到镜像本身。
数据卷使用场景:
   容器数据持久化(mysql数据、nginx日志等类型);
   静态web页面挂载;
   应用配置文件挂载;
   多容器间的目录或文件共享。

数据卷容器:

 数据卷容器功能是可以让数据在多个docker容器之间共享,即先要创建一个后台运行的A容器作为Server,之后创建的B容器、C容器等都可以同时访问A容器的内容,因此数据卷容器用于为其它容器提供卷的挂载继承服务,数据卷为其它容器提供数据读写服务, A容器称为server端、其它容器成为client端:

1
2
3
4
5
6
7
8
9
// 卷容器Server:
# docker run -d --name volume-server -v /data/testapp:/usr/share/nginx/html/testapp -v
/data/nginx/conf/nginx.conf:/etc/nginx/nginx.conf:ro registry.cn-hangzhou.aliyuncs.com/zhangshijie/pause:3.8
 
// client1:
# docker run -d --name web1 --volumes-from volume-server -p80:80 nginx:1.20.2
 
// client2:
# docker run -d --name web2 --volumes-from volume-server -p81:80 nginx:1.20.2

特点:

 适用于同类服务的数据卷共享;

 client会继承卷server挂载和挂载权限;

 停止卷server,也不影响已经运行的容器、甚至也不影响新建容器;

 删除卷server,不影响已经运行的容器,但是不能新建容器。

 

  

Docker网络:

 Docker服务安装完成之后,默认在每个宿主机会生成一个名称为docker0的网卡其IP地址都是172.17.0.1/16,并且会生成三种不同类型的网络:

1
2
3
4
5
6
7
8
9
root@docker-server1:~# ifconfig docker0
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
    inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
    inet6 fe80::42:d9ff:fe20:16d9 prefixlen 64 scopeid 0x20<link>
    ether 02:42:d9:20:16:d9 txqueuelen 0 (Ethernet)
    RX packets 1920 bytes 101778 (101.7 KB)
    RX errors 0 dropped 0 overruns 0 frame 0
    TX packets 2203 bytes 16910412 (16.9 MB)
    TX errors 0 dropped 0 overruns 0 carrier 0 collisions

 另外会额外创建三个默认网络,用于不同的使用场景:

1
2
3
4
5
root@docker-server1:~# docker network list
NETWORK ID   NAME   DRIVER   SCOPE
438a9be14ef8  bridge   bridge  local   #桥接网络,默认使用的模式,容器基于SNAT进行地址转换访问宿主机以外的环境;
4c026356e4d1  host     host   local   #host网络,直接使用宿主机的网络( 不创建net namespace),性能最好,但是容器端口不能冲突;
8d70da095b8e  none     null   local   #空网络,容器不会分配有效的IP地址(只有一个回环网卡用于内部通信),用于离线数据处理等场景。

bridge模式:

 docker的默认模式即不指定任何模式就是bridge模式,也是目前使用比较多的网络模式,此模式创建的容器会为每一个容器分配自己的网络IP等信息,并将容器连接到一个虚拟网桥与外界通信。

1
2
# docker network inspect bridge
# docker run -it -d --name nginx-web1-bridge-test-container -p 80:80 --net=bridge nginx:1.2

 

host模式:

 host模式就是直接使用宿主机的IP地址,创建的容器如果指定了使用host模式,那么新创建的容器不会创建自己的虚拟网卡,而是直接使用宿主机的网卡和IP地址,因此在容器里面查看到的IP信息就是宿主机的信息,访问容器的时候直接使用宿主机IP+容器端口即可,而且某一个端口一旦被其中一个容器占用那么其它容器就不能再监听此端口,不过容器的其它资源比如容器的文件系统、容器系统进程等还是基于namespace相互隔离。

此模式的网络性能最高,但是各容器之间端口不能相同,适用于运行容器端口比较固定的业务。

1
2
3
4
5
# docker run -it -d --name nginx-web1-host-test-container -p 80:80 --net=host nginx:1.20.2
root@docker-server1:~# docker exec -it 0092ca554f bash
root@docker-server1:/# apt update && apt install net-tools
root@docker-server1:/# ifconfig
root@docker-server1:/# netstat -tanlp

none模式:

 none模式就是无IP模式,在使用none模式后,docker容器不会进行任何网络配置,其没有网卡、没有IP也没有路由,因此默认无法与外界通信,需要手动添加网卡配置IP等,所以极少使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
# docker run -it -d --name nginx-web1-none-test-container -p 80:80 --net=none busybox sleep 10000000
# docker exec -it 3c54e90c209a sh
/ # ifconfig
    lo Link encap:Local Loopback
    inet addr:127.0.0.1 Mask:255.0.0.0
    UP LOOPBACK RUNNING MTU:65536 Metric:1
    RX packets:0 errors:0 dropped:0 overruns:0 frame:0
    TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
    collisions:0 txqueuelen:1000
    RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
/ # ping 223.6.6.6
PING 223.6.6.6 (223.6.6.6): 56 data bytes
ping: sendto: Network is unreachable

container模式:

 Container模式即容器模式,使用参数--net=container:目标容器名称/ID指定,使用此模式创建的容器需指定和一个已经存在的容器共享一个网络namespace,而不会创建独立的namespace,即新创建的容器不会创建自己的网卡也不会配置自己的IP,而是和一个已经存在的被指定的目标容器共享对方的IP和端口范围,因此这个容器的端口不能和被指定的目标容器端口冲突,除了网络之外的文件系统、用户信息、进程信息等仍然保持相互隔离,两个容器的进程可以通过loopback网卡及容器IP进行通信。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# docker run -it -d --name nginx-container -p 80:80 --net=bridge nginx:1.22.0-alpine
# docker run -it -d --name php-container --net=container:nginx-container php:7.4.30-fpm-alpine
 
//分别进入容器验证IP地址信息——验证net namesapce:
# ls /var/run/netns/netns
# ln -s /var/run/docker/netns/* /var/run/netns/
 
# ip netns list
default
 
# ip netns exec 10844980eee7 ip a
72: eth0@if73: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netns default
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
    valid_lft forever preferred_lft forever 

   第一课总结:

      容器基于namespace实现资源隔离;

      容器基于cgroup实现资源限制;

      kubernetes环境中由kubelet接受指令通过CRI等标准调用运行时实现容器的生命周期管理;

      Docker的存储引擎推荐使用overlay2;

      Docker中的重要数据通过-v选项挂载数据卷实现持久化;

      Docker的网络有多种模式,但在单机docker环境下主要使用bridge模式。

 
 
 
posted @   sunif1043  阅读(164)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示