故事
程序员小张: 刚毕业,参加作业1年左右,日常作业是CRUD
架构师老李: 多个大型项目经验,通晓各种屠龙宝术;
有一天,小张碰到了老李,他想向老李讨教有关Docker的知识。于是,小张走向老李并问道:“老李,我听说你懂得许多关于Docker的知识,请问你能否给我讲讲Docker的根本结构和组件?”
老李微笑着点了允许,开端向小张介绍Docker的根本结构和组件。他告知小张,Docker由三个首要概念构成:镜像、容器和库房。其中,镜像是一个只读的模板,容器则是根据这个模板创立的可运转实例,而库房则是用于存储镜像的当地。
随后,老李具体地介绍了Docker的各个组件,包含Docker客户端、Docker守护进程、Docker镜像以及Docker容器。他为小张讲解了每个组件的作用以及它们之间怎么彼此配合来完结Docker的功用。
在老李的深入讲解下,小张逐渐理解了Docker的根本结构和组件,并感到非常振奋。他决定在未来的作业中深入研究Docker,并将其运用于项目中,以进步团队的功率和质量。
Docker是一个开源渠道,用于快速开发、布置和运转运用程序。它由多个组件组成,以下是Docker的首要组件:
-
Docker Daemon:它是Docker的中心组件,负责办理镜像、容器、网络和卷等资源,并将Docker API露出给客户端。
-
Docker Client:它是与Docker Daemon通讯的首要接口,能够经过指令行或API向Daemon发送请求。
-
Docker镜像(Docker Image):它是一个只读的模板,它包含了一切用于运转运用程序所需求的代码、库文件、环境变量和装备文件等内容。
-
Docker容器(Docker Container):它是根据Docker镜像创立的可运转实例。每个容器都是一个独立的、轻量级的操作体系,它们之间彼此阻隔并且能够共享主机的内核。
-
Docker Registry:它是用于存储和分发Docker镜像的公共或私有库房。Docker Hub是最流行的公共Registry,而Docker Trusted Registry则是一种常见的私有Registry处理方案。
-
Docker Compose:它是一个东西,用于界说和运转多个容器的运用程序。运用Docker Compose,能够经过一个简单的装备文件来描绘运用程序的各个组件,然后使它们能够在一个一致的环境中运转。
-
Docker Swarm:它是Docker的原生集群办理东西,用于协谐和办理多个Docker节点。运用Docker Swarm,能够将多个Docker节点组成一个大型的虚拟集群,并在其中布置、办理和扩展Docker容器。
这些组件一起构成了Docker的中心功用,使得开发人员和体系办理员能够更加快捷地开发、布置和办理运用程序。
接下来,我们深入到docker内部,分析和学习一下它的底层完结中心技能,并对常见的操作进行实践操作。
容器vs虚拟机
容器是一种沙盒技能,能够当作集装箱,这样运用之间就有了鸿沟而不至于相互干扰,便利搬动;
程序运转起来的计算机履行环境的总和 便是进程;
容器的中心功用: 经过束缚和修正进程的动态表现,创造出一个鸿沟;
制作束缚: Cgroups技能 修正进程视图: Namespace技能
容器的本质:
int pid = clone(main_function, stack_size,CLONE_NEWPID|SIGCHLD,NULL);
多次调用clone方法能够创立多个pid的进程NameSpace ,每个namespace中都会人为自己是第一号进程,看不到宿主机的进程空间也看不到其它的pid的进程空间;
除了PID Namespace ,linux还供给了Mount (挂载点信息), UTS , IPC , Network (网络设备和装备), User这些namespace,来对各种不同的进程上下文进行障眼法操作;
只能看到namespace所约束的资源,文件,设备,状态,装备 ;对宿主机和其它的不相关程序完全看不到;
所以,容器是一种约束了namespace的进程而已;
旁路式的辅佐和办理作业;
对比项目 | 虚拟机 | docker容器 |
---|---|---|
实在存在 | 实在存在,并运转一个完好的GuestOs | 不实在存在,仅仅辅佐作用 |
会带来额定的资源耗费和占用 | 100-200M内存,经过虚拟化软件的阻拦和处理 | 无耗费 |
内核 | 多个虚拟机能够运用不同的内核 | 共享操作体系内核 |
敏捷和高性能 是容器比较于虚拟机最大的优势;
缺陷: 容器阻隔的不完全
-
多个容器之间运用的仍是同一个宿主机的操作体系内核;
-
linux内核中许多资源和目标不能被namespace化,比方时间;(根据虚拟化和独立内核技能的容器完结阻隔)
容器的底层完结基础
cgroups
容器对宿主机操作体系来说是一个普通进程,普通进程的资源约束假如设置,会挤占别的进程的资源。
Linux Control Groups : 约束一个进程组运用的资源上限,包含: CPU, 内存,磁盘,网络带宽。对进程进行优先级设置,审计,对进程挂起和康复操作。
/sys/fs/cgoup
能够对资源进行共同的约束:
blkio | 块设备设定io约束 |
---|---|
cpuset | 进程分配独自的cpu和对应的内存节点 |
memory | 设定内存运用约束 |
在docker run发动的时分能够传递这些资源约束参数:
--cpu-period=100000 --cpu-quota=20000
缺陷: 容器中 linux的 /proc top 显示的是宿主机的信息 lxcfs
namespace
进程看到的经过特殊处理的视图。
nt 设备挂载点
network 网络
user 用户目录
UTS host
IPC 进程通讯
rootfs
进入容器之后,看到的文件体系,即容器镜像,它保持了运用在不同环境下的一致性。
首要运用了下面两种技能来完结。
技能 | 操作效果 |
---|---|
mount Namespace | 对容器进程视图的改动,伴随着挂载操作才干生效; |
容器中看到的是一个独立的阻隔环境,而不是承继宿主机的文件体系; | |
chroot/pivot_root | 改动进程的根目录 |
rootfs只包含了操作体系的文件,可是不包含操作体系的内核。
这个便是容器镜像: 挂载在容器的根目录上,用来为容器进程供给阻隔后的履行环境的文件体系,便是所谓的容器镜像。
一致性: 运用+操作体系的文件和目录; 镜像是打包操作体系的才能;打通了运用在本地开发和远端履行环境之间难以逾越的鸿沟;
容器镜像将会成为未来软件的主流发布方法。
分层+联合文件体系 union file system ; AUFS ;
目录:
/var/lib/docker/aufs/diff/layerid /var/lib/docker/aufs/mnt
层分成三个部分:
- 可读写层;(修正层)
- init层;(装备层) /etc/hosts /etc/resolv.conf等装备信息 只针对当时容器有用,不能提交
- 只读层;(操作体系自身)
docker根本操作
1 购买一个cvm
为了学习和实验的意图,先购买一个长途的linux机器。
条目 | 挑选 |
---|---|
1.进入购买页面 腾讯云的轻量级别cvm | console.cloud.tencent.com/cvm/overvie… |
2.新建实例, | 挑选 竞价实例 最便宜 |
3.挑选区域 | 挑选离你最近的区域 |
4.挑选最低的装备 | S6.MEDIUM2 2C4G 哪个最便宜买哪个 |
5.镜像挑选 | TencentOS,最新版本 |
6.带宽 | 挑选依照运用流量计费 , 带宽能够挑选10Mbps |
7.安全组 | 默许放行一切的请求和呼应 这里是测验意图 |
8.设置root账号和密码 | 自己设置 |
9.其他的免费的注册即可 | 总价格大概是0.1元/小时 流量 0.8元/GB 流量根本用不上 |
购买成功页面如下:
然后运用一个ssh东西,比方xshell或许finalshell 登录上去;
登录进去之后,先承认一下cpu和内存是否对得上。
top
然后按 1
2 装置最新版本docker
指令:
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install docker-ce docker-ce-cli containerd.io
#发动docker
sudo systemctl start docker.service
#承认docker能够运用
docker search redis
3 docker helloworld
一个简单的python程序。
from flask import Flask
import socket
import os
app = Flask(__name__)
@app.route('/')
def hello():
html = "<h3>Hello {name}!</h3>" \
"<b>Hostname:</b> {hostname}<br/>"
return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname())
if __name__ == "__main__":
app.run(host='0.0.0.0', port=80)
Flask
# 运用官方供给的Python开发镜像作为基础镜像
FROM python:2.7-slim
# 将作业目录切换为/app
WORKDIR /app
# 将当时目录下的一切内容复制到/app下
ADD . /app
# 运用pip指令装置这个运用所需求的依靠
RUN pip install --trusted-host pypi.python.org -r requirements.txt
# 允许外界拜访容器的80端口
EXPOSE 80
# 设置环境变量
ENV NAME World
# 设置容器进程为:python app.py,即:这个Python运用的发动指令
CMD ["python", "app.py"]
代码放在我的gitlhub上。
制作镜像:
# cd 到Dcokerfile地点的目录
docker build -t p1:v1 .
# 运转
docker run --name p1 -p 80:80 -it p1:v1
运转效果:
Dockerfile的每个语句履行后,都会生成一个对应的镜像层。
检查本地镜像指令:
docker images
4 保存镜像到库房
docker tag p:v1 carter880522hn/app:pythondemo
docker login
#输入你的docker hub的账号密码,即可推送到你的私有库房 当然你也能够运用其他公有云厂商的镜像库房
docker push carter880522hn/app:pythondemo
5 docker commit 原理
也能够进到正在运转的镜像,做一些修正,然后提交之后,推送到基础镜像。
docker ps
# 能够找到运转的容器id
docker commit ContainerId 长途tag
依照分层逻辑。
镜像分为三层:
- 只读层,操作体系;
- init层, hosts, sysctl.conf文件;
- 读写层,程序相关的层;
docker commit实践上是在容器运转之后,把最上层的可读写层,加上本来容器的只读层,打包成了一个新的镜像,只读层是宿主机共享,不占用额定空间。
6 docker exec 原理
这个指令是怎么进入到容器内部的呢?
容器本质上是宿主机创立的进程,进程的namespace在机器上是实实在在文件。
检查容器在宿主机上的进程编号:
docker inspect --format '{{.State.Pid}}' bc917451cee1
检查宿主机上的namespace文件。
ls -lh /proc/容器PID/ns
容器内部的namespace实践上在宿主机上有对应的文件进行对应。 所以,我们能够运用 exec 去操控容器的文件。
linux中一个进程是能够挑选加入到某个进程已有的namespace,然后达到进入进程地点容器的意图。
下面的参数,发动容器的时分,能够进入另外一个容器的network namesapce;
--net container:4ddf4638572d
7 volume原理
容器内部的新建的文件,怎么让宿主机获取到? 宿主机上的文件,容器内部怎么拜访?
答案便是Volume,即数据卷。
语法如下:
docker run -v /local:/container ...
rootfs的挂载进程:
- 容器被创立,敞开Mount Namespace ;
- 履行chroot或许 pivot_root ;
volume,是在 1,2之间的机遇,把volune指定的宿主机和容器目录对应联系进行绑定,然后完结挂载; 做这个挂载的时分,容器进程现已创立了,Mount Namespace现已敞开了,这个挂载信息只在容器可见,在宿主机是看不见这个挂载点的,确保了容器的阻隔性不被Volume打破。
利用的是linux的 bind mount机制。linux的文件体系节点叫做inode, 文件指针叫做dentry , bind mount实践修正的是dentry , 这样容器内部和宿主机对应的目录修正,就指向了同一个inode .
volume中的文件,不会写到镜像,可是假如你这个时分进行docker commit 操作, 这个volume对应的容器目录会被提交。
docker 镜像结构图:
容器运转环境
在宿主机上,
运用的静态表现即
运用的动态表现即容器,是一个运用cgroups和namesace 约束阻隔的进程组。
维度 | 说明 |
---|---|
运用静态表现 | 各种镜像,镜像即坐落 /var/lib/docker/aufs/mnt上的 rootfs ; |
运用的动态表现 | 容器,是一个运用cgroups和namesace 约束阻隔的进程组。 |
容器编列 | 把用户提交的镜像运转起来 |
扩展生态 | CI/CD、监控、安全、网络、存储 |
k8s
k8s: google和redhat公司联合推出的开源项目
价值: 根据容器构建分布式体系的基础依靠;
k8s的架构:
处理的问题: 编列,办理,调度用户提交的作业。 大规模集群中的各种使命,实践上存在各种联系,对这些联系的处理才是作业编列和办理体系最困难的当地。
docker仅仅CRI的一种完结方法。
物理布置/虚机布置 | k8s布置 |
---|---|
运用 | pod |
拜访联系 直接维护装备文件 | service |
装备信息办理 经过文件 | configmap/secret |
daemon 做日志搜集,灾难康复,数据备份 每台主机只运转一个 | daemonset |
守时使命 | cronjob |
一次性使命 | job |
两台nginx做负载均衡 | |
keepalive做一个vip | |
布置两个nginx | 一个deployment,一个service |
处理思路: 1.经过pod,job来描绘你办理的运用; 2.界说一些渠道级的服务目标来编列: service,secret,autoscaler ;
小结
本文从一个了解docker的故事动身,具体分析了docker的三大底层中心技能,cgroups,namesapce,rootfs ; 并从实践动身,购买一个长途的linux机器,装置docker, 运转一个简单的python运用,并结合底层中心技能,叙述了docker exec , docker commit ,volume的完结原理,然后简单介绍了k8s的架构和处理的问题,一些中心概念的引出;
原创不易,关注诚可贵,转发价更高!转载请注明出处,让我们互通有无,一起进步,欢迎沟通交流。