Dokcer
1 简介
前言
容器可以算是当下最流行的技术之一了,那么究竟什么是容器呢?统称来说,容器是一种工具,指的是可以装下其它物品的工具,以方便人类归 纳放置物品、存储和异地运输,具体来说比如人类使用的衣柜、行李箱、背包等都可以成为容器,但今天我们所说的容器是一种 IT 技术。
1.1 docker 简介
1.1.1 docker入门
在前言中提到过容器的概念,接下来要了解的docker技术则是容器的一种实现。Docker 是一个在 2013 年开源的应用程序并且是一个基于 go 语言编写是 一个开源的 PAAS 服务(Platform as a Service,平台即服务的缩写)。用于开发应用、交付(shipping)应用、运行应用。 Docker允许用户将基础设施(Infrastructure)中的应用单独分割出来,形成更小的颗粒(容器),从而提高交付软件的速度。其功能简单点来说就是允许用户将程序及其运行环境打包成镜像,运行在各个版本的操作系统之上。
Docker最早采用 LXC 技术(LinuX Container 的简写,LXC 是 Linux 原生支持的 容器技术,可以提供轻量级的虚拟化,可以说 docker 就是基于 LXC 发展起来 的,提供 LXC 的高级封装,发展标准的配置方法),而虚拟化技术 KVM(Kernelbased Virtual Machine) 基于模块实现,Docker 后改为自己研发并开源的 runc 技 术运行容器。
Docker对比虚拟机
-
资源利用率更高:一台物理机可以运行数百个容器,但是一般只能运行数十个 虚拟机。
-
开销更小:不需要启动单独的虚拟机占用硬件资源(空运行的虚拟机占用物理机 6-8%性能)。
-
启动速度更快:可以在数秒内完成启动。
1.1.2 Docker的架构
- Docker 主机(Host):一个物理机或虚拟机,用于运行 Docker 服务进程和容器。
- Docker 服务端(Server):Docker 守护进程,运行 docker 容器。
- Docker 客户端(Client):客户端使用 docker 命令或其他工具调用docker API。
- Docker 仓库(Registry): 保存镜像的仓库,类似于git或svn这样的版本控制系
- Docker 镜像(Images):镜像可以理解为创建实例使用的模板。
- Docker 容器(Container): 容器是从镜像生成对外提供服务的一个或一组服务。
当一台宿主机运行了多个容器时,也会带来一些问题,例如:
- 怎么样保证每个容器都有不同的文件系统并且能互不影响?
- 一个 docker 主进程内的各个容器都是其子进程,那么实现同一个主进程下不同类型的子进程?各个进程间通信能相互访问(内存数据)吗?
- 每个容器怎么解决 IP及端口分配的问题?
- 多个容器的主机名能一样吗?
- 每个容器都要不要有 root 用户?怎么解决账户重名问题?
可见要想实现容器并不是一件简单的事情,还有很多问题需要考虑到,下面一起来看看docker是如何解决这些问题的
1.1.3 Linux Namespace 技术
Docker使用了一种名叫 namespaces
技术来实现容器(container)的隔离,当运行容器的时候, Docker 会为容器创建一系列 namespaces.
namespace是 Linux 系统的底层概念,在内核层实现,不同类型的命名空间可以实现不通类型的隔离功能。
MNT Namespace
调用clone()的CLONE_NEWNS参数,容器子进程将放置于新的挂载命名空间(使用chroot 技术把容器锁定到一个指定的运行目录里面),这样容器内不能访问到宿主机的资源。
IPC Namespace
一个容器内的进程间通信,允许一个容器内的不同进程的(内存、缓存等)数据访 问,但是不能夸容器访问其他容器的数据。
UTS Namespace
UTS namespace(UNIX Timesharing System 包含了运行内核的名称、版本、底层 体系结构类型等信息)用于系统标识,其中包含了 hostname 和域名 domainname ,它使得一个容器拥有属于自己 hostname 标识,这个主机名标识 独立于宿主机系统和其上的其他容器。
PID Namespace
Linux 系统中,有一个 PID 为 1 的进程(init/systemd)是其他所有进程的父进程,那么在每个 容器内也要有一个父进程来管理其下属的子进程,那么多个容器的进程通 PID namespace 进程 隔离(比如 PID 编号重复、器内的主进程生成与回收子进程等)。
Net Namespace
每一个容器都类似于虚拟机一样有自己的网卡、监听端口、TCP/IP 协议栈等, Docker 使用 network namespace 启动一个 vethX 接口,这样你的容器将拥有它 自己的桥接 ip 地址,通常是 docker0,而 docker0 实质就是 Linux 的虚拟网桥,网 桥是在 OSI 七层模型的数据链路层的网络设备,通过 mac 地址对网络进行划 分,并且在不同网络直接传递数据。
User Namespace
各个容器内可能会出现重名的用户和用户组名称,或重复的用户 UID 或者 GID,那么怎么隔离各个容器内的用户空间呢? User Namespace 允许在各个宿主机的各个容器空间内创建相同的用户名以及相 同的用户 UID 和 GID,只是会把用户的作用范围限制在每个容器内,即 A 容器 和 B 容器可以有相同的用户名称和 ID 的账户,但是此用户的有效范围仅是当前 容器内,不能访问另外一个容器内的文件系统,即相互隔离、互补影响、永不相见。
Linux control groups
在一个容器,如果不对其做任何资源限制,则宿主机会允许其占用无限大的内 存空间,有时候会因为代码 bug 程序会一直申请内存,直到把宿主机内存占 完,为了避免此类的问题出现,宿主机有必要对容器进行资源分配限制,比如 CPU、内存等,Linux Cgroups 的全称是 Linux Control Groups,它最主要的作用, 就是限制一个进程组能够使用的资源上限,包括 CPU、内存、磁盘、网络带宽等等。此外,还能够对进程进行优先级设置,以及将进程挂起和恢复等操作。
1.1.4 docker进阶
当我们在容器内部启动一个watch进程时,在外部宿主机上也能看见这个进程,只不过他们的PID是不同的。
查看进程树会发现宿主机上的watch进程是一个明未containerd-shim开启的子进程
containerd是什么?为什么docker运行的容器是containerd的进程?
为了保证容器生态的标准性和健康可持续发展,包括 Linux 基金会、Docker、微软、红 帽谷歌和、IBM、等公司在 2015 年 6 月共同成立了一个叫 open container(OCI) 的组织,其目的就是制定开放的标准的容器规范。Docker基于OCI规范实现了runc,它是container runtime的实现,不过在1.11版本,docker将runc集成到了containerd中。
container runtime是容器运行的底层环境。它主要负责从容器仓库加载容器镜像,监控本地系统资源,隔离容器和管理容器。值得注意的是,容器引擎是用来管理单个容器的。docker的结构如下图:
从图中可以看出Docker根据OCI规范将与容器相关系统调用封装到CONTAINED中,让程序通过CONTAINED来管理容器,而不是使用clone() 或 mount() 的系统调用。
容器的创建与管理过程
使用strace命令追踪containerd
也证明了通信流程确实如此
而且使用了namespace中的unshare API来实现容器隔离。
1.2 docker安装和命令
1.2.1 通过yum 源安装
centos7.9通过阿里镜像安装docker-ce(docker社区版)
查看service文件
查看socket文件
1.2.2 通过rpm包安装docker
下载rpm包
官方镜像地址:https://download.docker.com/linux/centos/7/x86_64/stable/Packages/
阿里镜像地址:https://mirrors.aliyun.com/docker-ce/linux/static/stable/x86_64/
1.2.3 服务的启动和验证
1.2.4 Docker存储引擎
目前 docker 的默认存储引擎为 overlay2,不同的存储引擎需要相应的系统支 持,如需要磁盘分区的时候传递 d-type 文件分层功能,即需要传递内核参数开 启格式化磁盘的时候的指定功能。
存储驱动类型:
- AUFS(AnotherUnionFS)是一种 Union FS,是文件级的存储驱动。所谓 UnionFS 就是把不同物理位置的目录合并 mount 到同一个目录中。简单来说就是支持将 不同目录挂载到同一个虚拟文件系统下的文件系统。这种文件系统可以一层一 层地叠加修改文件。无论底下有多少层都是只读的,只有最上层的文件系统是 可写的。当需要修改一个文件时,AUFS 创建该文件的一个副本,使用 CoW 将 文件从只读层复制到可写层进行修改,结果也保存在可写层。在 Docker 中,底 下的只读层就是 image,可写层就是 Container,是 Docker 18.06 及更早版本的 首选存储驱动程序,在内核 3.13 上运行 Ubuntu 14.04 时不支持 overlay2。
- Overlay:一种 Union FS 文件系统,Linux 内核 3.18 后支持。
- overlay2: Overlay 的升级版,到目前为止,所有 Linux 发行版推荐使用的存储类型。
- devicemapper:是 CentOS 和 RHEL 的推荐存储驱动程序,因为之前的内核版本不支持 overlay2,但是当前较新版本的 CentOS 和 RHEL 现在已经支持 overlay2, 因此推荐使用 overlay2。
- ZFS(Sun-2005)/btrfs(Oracle-2007):目前没有广泛使用。
- vfs:用于测试环境,适用于无法使用 copy-on-write 文件系统的情况。 此存储 驱动程序的性能很差,通常不建议用于生产。
1.3 Docker 镜像管理
Docker 镜像含里面是一层层文件系统,叫做 Union File System(Union FS 联合 文件系统),2004 年由纽约州立大学石溪分校开发,联合文件系统可以将多个目录挂载到一起从而形成一整个虚拟文件系统,该虚拟文件系统的目录结构就 像普通 linux 的目录结构一样,docker 通过这些文件再加上宿主机的内核提供 了一个 linux 的虚拟环境,每一层文件系统我们叫做一层 layer,联合文件系统 可以对每一层文件系统设置三种权限,只读(readonly)、读写(readwrite)和 写出(whiteout-able),但是 docker 镜像中每一层文件系统都是只读的,构建镜像的时候,从一个最基本的操作系统开始,每个构建的操作都相当于做一层的修改,增加了一层文件系统,一层层往上叠加,上层的修改会覆盖底层该位置的可见 性,这也很容易理解,就像上层把底层遮住了一样,当使用镜像的时候,我们只 会看到一个完全的整体,不知道里面有几层也不需要知道里面有几层,结构如下:
docker 命令是最常使用的 docker 客户端命令,其后面可以加不同的参数以实 现相应的功能,常用的命令如下:
1.3.1 docker镜像命令
搜索镜像
下载镜像
查看本地镜像
镜像导出
镜像导入
删除镜像
1.4 容器常用命令
1.4.1 Docker run
用于运行容器,其格式如下:
范例:
1.4.2 查看容器命令
1.4.3 容器的管理
1.4.4 进入正在运行的容器
attach命令
显示,所有使用此方式进入容器的操作都是同步显示的且 exit 后容器将被关 闭,且使用 exit 退出后容器关闭,不推荐使用
exec命令
执行单次命令与进入容器,虽然 exit 退出容器还在运行
nsenter 命令
nsenter 命令需要通过 PID 进入到容器内部,不过可以使用docker inspect 获取到容器的 PID
2 Docker镜像制作
从镜像大小上面来说,一个比较小的镜像只有十几 MB,而内核文件需要一百 多兆, 因此镜像里面是没有内核的,镜像在被启动为容器后将直接使用宿主机 的内核,而镜像本身则只提供相应的 rootfs,即系统正常运行所必须的用户空间 的文件系统,比如/dev/,/proc,/bin,/etc 等目录,所以容器当中基本是没有/boot 目录的,而/boot 当中保存的就是与内核相关的文件和目录。
镜像的制作分为下面两种方式
- 交互式:进入容器内部部署相关软件
- 非交互式:利用dockerfile文件制作镜像
2.1 交互式制作编译版本Nginx1.16.1版本镜像
在centos基础镜像之上手动编译安装 nginx,然后再提交为镜像。
2.1.1 下载镜像
2.1.2 编译安装Nginx
2.1.3 配置Nginx
2.1.4 在宿主机提交镜像
注意:在提交镜像完成之前容器不能退出
2.1.5 测试访问
2.2 DockerFile 制作编译版 nginx 1.16.1 镜像
DockerFile可以说是一种可以被Docker程序解释的脚本,和shell脚本非常类似,DockerFile也是由一条条命令组成的,每条命令对应Linux下面的一条命令,Dokcer程序将这些DockerFile指令翻译成真正的Linux命令,这样的好处就是实现了自动化生成镜像,当后续有额外的需求时,只要在之前的DockerFile文件中添加或者修改相应的操作即可重新生成新的Dokcer镜像。DockerFile常用指令如下:
更多说明可以参考官方文档:https://docs.docker.com/engine/reference/builder/
2.2.1 环境准备
2.2.2 编写 Dockerfile
2.2.3 执行镜像构建
2.2.4 从镜像启动容器
2.2.5 测试访问界面
5 Docker单机仓库Docker Registry
Docker Registry作为Docker 的核心组件之一负责镜像内容的存储与分发,客户端的docker pull 以及push命令都将直接与registry进行交互,最初版本的 registry 由Python实现,由于设计初期在安全性,性能以及API 的设计上有着诸多的缺陷, 该版本在 0.9 之后停止了开发,由新的项目distribution(新的 docker register 被 称为 Distribution)来重新设计并开发下一代 registry。另外,Registry 2.4 版本之后支持了回收站机制,也就是可以删除镜像了,所以使用时最好是大于 Registry 2.4 版本的。
接下来将通过docker registry镜像来搭建一套本地私有仓库环境
5.1 下载 docker registry镜像
5.2 搭建单机仓库
镜像仓库配置参考:https://docs.docker.com/registry/configuration/
验证镜像仓库是否启动成功
测试能否登录仓库
解决报错
尝试上传镜像到仓库中
值得注意的是当使用docker login
登录过仓库镜像之后,会在用户家目录下生成一个文件用于存储认证的用户信息,因此,我们可以将该认证文件传输到其他宿主机对应目录下,从而实现跳过登录使用镜像仓库
6 docker 分布式仓库 Harbor
Harbor是一个用于存储和分发Docker镜像的企业级Registry 服务器,由vmware 开源,其通过添加一些企业必需的功能特性,例如安全、标识和管理等,扩展了开源 Docker Distribution。作为一个企业级私有 Registry 服务器,Harbor 提供了更 好的性能和安全。提升用户使用 Registry 构建和运行环境传输镜像的效率。Harbor 支持安装在多个Registry 节点的镜像资源复制,镜像全部保存在私有 Registry 中, 确保数据和知识产权在公司内部网络中管控,另外,Harbor也提供了高级的安全特性,诸如用户管理,访问控制和活动审计等。
6.1 官方站点和介绍
harbor 官方 github 地址:https://github.com/vmware/harbor
harbor 官方网址:https://goharbor.io/
6.2 安装 Harbor
6.2.1 安装环境要求
下载地址:https://github.com/vmware/harbor/releases
官方文档地址:https://goharbor.io/docs/2.0.0/install-config/installation-prereqs/
Docker引擎版本:17.06.0-ce+
Docker Compose:Version 1.18.0+
Openssl:Latest is preferred
下载Harbor 安装包
6.2.2 配置 Harbor
测试登录
这里登录的用户名为admin,密码则是先前在配置文件中设置的密码,也就是12345
如果 harbor 运行一段时间之后需要更改配置,则步骤如下:
登录后界面
6.3 harbor 仓库上传下载镜像
6.3.1 编辑 docker 配置文件
注意:如果我们配置的是 https 的话,则可以跳过此步
6.3.2 镜像的上传
在web管理界面创建项目
上传打完标签的镜像
在web管理界面查看上传的镜像
6.4 实现高可用
Harbor 支持基于策略的 Docker 镜像复制功能,这类似于 MySQL 的主从同步, 其可以实现不同的数据中心、不同的运行环境之间同步镜像,并提供友好的管理 界面,大大简化了实际运维中的镜像管理工作,已经有用很多互联网公司使用 harbor 搭建内网 docker 仓库的案例,并且还有实现了双向复制的案列,本文将 实现单向复制的部署
6.4.1 配置另一个harbor仓库
具体安装过程可以参考之前文档内容,在新仓库上创建一个与主 harbor 项目名称保持一致的项目
接着要在这个仓库新建管理对象
创建完成后测试连接
配置复制规则
6.4.2 配置原有harbor仓库
配置仓库对象
配置复制规则
6.4.3 测试同步效果
在208服务器上上传镜像
查看镜像是否上传成功
在209查看是否将镜像复制过来
查看复制日志
这样就实现了harbor仓库双向同步,如果只想实现单向同步,那只需要在主harbor仓库上配置复制规则,随后主harbor仓库会自动将更新推送到配置规则中添加的从仓库当中。
文档参考链接
官方文档链接:https://docs.docker.com/
Namespace介绍:https://www.youtube.com/watch?v=-YnMr1lj4Z8
Redhat容器介绍:https://developers.redhat.com/blog/2018/02/22/container-terminology-practical-introduction#container
docker-blog:https://www.docker.com/blog/what-is-containerd-runtime/
docker-blog:https://www.docker.com/blog/oci-release-of-v1-0-runtime-and-image-format-specifications/
container-shim:https://iximiuz.com/en/posts/implementing-container-runtime-shim/
namespace:https://man7.org/linux/man-pages/man7/namespaces.7.html
unshare:https://man7.org/linux/man-pages/man2/unshare.2.html
__EOF__

本文链接:https://www.cnblogs.com/bestvae/p/15884357.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
2021-02-11 11.网络管理和配置