当前位置: 首页 > news >正文

Docker镜像--镜像分层、UnionFS、镜像发布、私有库Registry

目录

一、前言

二、Docker镜像

分层的镜像

UnionFS(联合文件系统)

Docker镜像加载原理

引导文件系统 boot file system

根文件系统 root file system

宿主机启动后流程

镜像扩展

镜像分层优势

深入理解容器层

三、Docker镜像commit操作案例演示

1、查看当前ubuntu的vim命令

2、安装vim

3、commit我们自己的新镜像,且使用

四、本地镜像发布到阿里云

创建仓库镜像

推送镜像到阿里云

将阿里云上的镜像下载到本地

五、 私有库 Docker Registry 的使用

将本地镜像推送到私有库

下载Docker Registry

运行私有库Registry

registry :要运行的镜像名称 这是 Docker 官方提供的 Registry 镜像,用于搭建私有镜像仓库。如果本地没有该镜像,Docker 会自动从 Docker Hub 拉取。

案例演示

创建新镜像

curl验证私服库上有什么镜像

将新镜像zzyyubuntu:1.2修改符合私服规范的Tag

修改配置文件使之支持http

push推送到私服库并再次查看私有库

从registry中pull到本地并运行


一、前言

上篇文章中已经了解到了Docker生产中所需要用到的一些常用的命令,包括基本的命令、关于镜像和容器的操作命令等等。本文中我们再深入了解一下Docker的镜像。

二、Docker镜像

镜像是一种轻量级、可执行的独立软件包,它包含运行某个软件所需的所有内容,我们把应用程序和配置依赖打包好行程一个可交付的运行环境(包括代码、运行时需要的库、环境变量和配置文件等),这个打包好的运行环境就是image镜像文件。

只有通过这个镜像文件才能生成Docker容器实例(类似C++中new出来一个对象)。

分层的镜像

首先,在上篇文章中,我们在下载镜像的时候会发现它不是一下子下载一个,而是一层一层地在下载

UnionFS(联合文件系统)

Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录

举个例子来说 UnionFS 的核心就像 “透明胶片叠加” 

  • 分层叠加 (Layered):
    • 想象有多张透明的胶片,每一张上都画了一些图案(文件或目录)。
    • 你把它们一张张叠在一起。
    • 在 Docker 中,每一层(Layer)代表对文件系统的一次修改,比如:
      • 第1层:一个干净的 Ubuntu 系统。
      • 第2层:在 Ubuntu 上  install nginx,这一层只记录了新增的 Nginx 相关文件和修改。
      • 第3层:将你的网站代码 COPY 到 /var/www/html。
  • 统一视图 (Union):
    • 当你从最上面看这个叠加起来的胶片堆,你看到的是所有图案的总和,就像一个完整的画面。
    • 在 Docker 中,当你启动一个容器时,UnionFS 会把镜像的所有只读层和容器的可写层联合挂载到一个目录(比如 /),对外呈现出一个完整的、包含所有文件和目录的文件系统。你感觉不到这是由多层组成的。

怎么工作的?

联合文件系统(UnionFS)就是让这些多层文件系统“合并”成一个看起来完整的文件系统,但每一层本身是独立的、可以复用的。

在 Docker 中:镜像的每一层都是只读的

比如:

  • 第1层:基础操作系统(如 Ubuntu)
  • 第2层:安装了 Java
  • 第3层:安装了 Tomcat

这些层可以被多个镜像或容器共享。比如,10 个不同的 Java 应用镜像都可以基于“Ubuntu + Java”这一层,不需要重复存储。

  1. 容器启动时,会在最上面加一个“可写层”
    这个层是容器独有的。你在容器里创建文件、修改配置,都发生在这个最顶层。

    • 如果你修改了一个只读层里的文件,UnionFS 会使用一种叫 “写时复制”(Copy-on-Write) 的机制:
      • 先把那个文件从只读层“复制”到可写层,
      • 然后再在可写层修改。
    • 外面看起来文件被改了,但实际上只读层没变,变的是最上面的可写层。

Docker镜像加载原理

docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。

引导文件系统 boot file system

bootfs(boot file system)主要包含bootloader和kernel

  • Bootloader:负责在系统启动时,找到并加载 Linux 内核(Kernel)到内存中。
  • Kernel:操作系统的核心。它管理硬件、内存、进程、文件系统等。

 当宿主机(运行 Docker 的机器)启动时,它的 BIOS/UEFI 会加载宿主机的 bootfs,进而启动宿主机的内核。

需要注意的是 Docker 镜像中的 bootfs 并不会被容器使用!容器不启动自己的内核。容器共享的是宿主机的内核

  • 在宿主机启动时,bootfs 被加载,内核被启动。
  • 一旦内核完全加载到内存并开始运行,bootfs 就会被卸载(unmounted),因为它已经完成了引导使命。
  • 在容器运行时,bootfs 是不可见且不活动的。

根文件系统 root file system

根文件系统 root file system在 bootfs 之上,是 Docker 镜像的核心部分。
包含标准的 Linux 目录结构和文件:

  • /bin, /sbin:基本命令(如 ls, cp, bash)
  • /etc:配置文件
  • /lib, /lib64:系统库
  • /usr:用户程序和库
  • /dev:设备文件(由内核在运行时提供)
  • /proc, /sys:虚拟文件系统,提供内核和进程信息(由内核在运行时挂载)
  • /tmp, /var:临时和可变数据

它提供了容器运行所需的所有用户空间(userspace)程序、库和工具。
当内核启动后,它会挂载 rootfs 作为根目录 /,然后启动第一个进程(通常是 init 或 bash)。

宿主机启动后流程

  • 宿主机启动:
    • 宿主机 BIOS/UEFI → 加载宿主机 bootfs → 启动宿主机内核 → 卸载 bootfs。
    • 宿主机内核完全运行起来。
  • 运行 Docker 容器:
    • 假设执行 docker run ubuntu:20.04 /bin/bash。
    • 此时Docker Daemon 向宿主机内核发起请求,创建一个新容器。
    • 宿主机内核使用 Namespace 和 Cgroups 技术为容器创建隔离的环境。
    • Docker 使用 UnionFS 将 ubuntu:20.04 镜像的 rootfs 层(以及你可能添加的应用层)联合挂载为容器的根文件系统 /。
    • 宿主机内核在容器的隔离环境中启动 /bin/bash 进程。

✅ 核心:容器进程是由宿主机内核调度的,它看到的文件系统是镜像提供的 rootfs。

对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接使用Host的Kernel,自己只需要提供rootfs就可以。所以,对于不同的Linux发行版,bootfs基本是一致的,rootfs会有差别,不同的发行版可以共用bootfs。

有差别的rootfs:

这就是为什么平时我们安装进虚拟机的CentOS都是好几个G,在docker这里只有几百兆的原因。

镜像扩展

Docker支持扩展现有镜像,创建新的镜像。新镜像是从base镜像一层一层叠加生成的。

# Version: 0.0.1
FROM debian  # 直接在debain base镜像上构建
MAINTAINER mylinux
RUN apt-get update && apt-get install -y emacs # 安装emacs
RUN apt-get install -y apache2 # 安装apache2
CMD ["/bin/bash"] # 容器启动时运行bash

镜像分层优势

镜像分层最大的一个好处就是共享资源,方便复制迁移,就是为了复用。

比如说有多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份 base 镜像;

同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。

深入理解容器层

Docker镜像层都是只读的,容器层是可写的。当容器启动时,一个新的可写层被加载到镜像的顶部。 这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。

所有对容器的改动 - 无论添加、删除、还是修改文件都只会发生在容器层中。只有容器层是可写的,容器层下面的所有镜像层都是只读的。

三、Docker镜像commit操作案例演示

docker commit 提交容器副本使之成为一个新的镜像

docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[标签名]

案例演示说明:我们从官网仓库上下载的Ubuntu是没有vim命令的,接下来要做的就是,在这个Ubuntu上增加vim命令功能,然后将他作为一个新的镜像commit构建出来。

1、查看当前ubuntu的vim命令

2、安装vim

安装完成

3、commit我们自己的新镜像,且使用

四、本地镜像发布到阿里云

首先阿里云开发者平台

创建仓库镜像

选择控制台,进入容器镜像服务

选择个人实例

命名空间

仓库名称

进入管理界面获得脚本

推送镜像到阿里云

管理界面脚本,这里就会出现如何推送和下载的命令,我们只需要按要求填好,在docker运行就可以

我们下来是要推送所以选择这三条

$ docker login --username=lyric77 crpi-q587ns4a9hlk0gyh.cn-beijing.personal.cr.aliyuncs.com
$ docker tag [ImageId] crpi-q587ns4a9hlk0gyh.cn-beijing.personal.cr.aliyuncs.com/lyric77/myubuntu:[镜像版本号]
$ docker push crpi-q587ns4a9hlk0gyh.cn-beijing.personal.cr.aliyuncs.com/lyric77/myubuntu:[镜像版本号]

如果使用 docker login 阿里云镜像仓库时,在输入密码后,报错:

Error response from daemon: Get https://registry.cn-hangzhou.aliyuncs.com/v2/: unauthorized: authentication required

这里是因为使用了阿里云账户的登录密码,而不是Registry的独立登录密码”,这是导致 docker login 阿里云镜像仓库失败的原因。docker login 阿里云镜像仓库输入的密码,应该独立设置。

推送成功之后我们在阿里云上查看就会出现

将阿里云上的镜像下载到本地

五、 私有库 Docker Registry 的使用

由于

  1. 官方Docker Hub地址:https://hub.docker.com/,中国大陆访问太慢了且准备被阿里云取代的趋势,不太主流。
  2. Dockerhub、阿里云这样的公共镜像仓库可能不太方便,涉及机密的公司不可能提供镜像给公网,所以需要创建一个本地私人仓库供给团队使用,基于公司内部项目构建镜像。

而Docker Registry是官方提供的工具,可以用于构建私有镜像仓库。

将本地镜像推送到私有库

下载Docker Registry

运行私有库Registry

运行后,相当于本地有个私有Docker hub

docker run -d -p 5000:5000  -v /zzyyuse/myregistry/:/tmp/registry --privileged=true registry
  • -p 5000:5000 :端口映射(Port Mapping)。将宿主机(Host)的 5000 端口映射到容器内部的 5000 端口。Docker Registry 默认在容器内的 5000 端口上提供 HTTP 服务。映射后,您可以通过访问 http://<宿主机IP>:5000 来与 Registry 交互。
  • -v /zzyyuse/myregistry/:/tmp/registry : 卷挂载(Volume Mount)。将宿主机上的目录 /zzyyuse/myregistry/ 挂载到容器内的 /tmp/registry 目录。Docker Registry 会将镜像数据存储在这个目录中。
  • --privileged=true :赋予容器“特权模式”(Privileged Mode)。容器将拥有几乎与宿主机相同的权限,可以访问宿主机的所有设备。允许容器执行一些通常被限制的操作,如挂载文件系统、修改网络配置等。
  • registry :要运行的镜像名称 这是 Docker 官方提供的 Registry 镜像,用于搭建私有镜像仓库。如果本地没有该镜像,Docker 会自动从 Docker Hub 拉取。

默认情况,仓库被创建在容器的/var/lib/registry目录下,建议自行用容器卷映射,方便于宿主机联调。

案例演示

创建新镜像

下面我们演示创建一个新镜像,ubuntu安装ifconfig命令,并将这个新镜像推送到我们创建的私有库Registry

commit构建的新镜像并且验证可以使用

curl验证私服库上有什么镜像

wget -qO- http://49.233.157.103:5000/v2/_catalog

将新镜像zzyyubuntu:1.2修改符合私服规范的Tag

docker tag lyric_ubuntu:1.2 49.233.157.103:5000/lyric_ubuntu:1.2

修改配置文件使之支持http

docker默认不允许http方式推送镜像,通过配置选项来取消这个限制。====> 修改完后如果不生效,建议重启docker。

重启docker之后,别忘记重新启动一下registry容器

docker run -d -p 5000:5000  -v /zzyyuse/myregistry/:/tmp/registry --privileged=true registry

push推送到私服库并再次查看私有库

从registry中pull到本地并运行

可以看到成功运行。


感谢阅读!

http://www.dtcms.com/a/339598.html

相关文章:

  • Java -- 用户线程和守护线程--线程同步机制
  • 大模型问题:幻觉分类+原因+各个训练阶段产生幻觉+幻觉的检测和评估基准
  • OpenSCA开源社区每日安全漏洞及投毒情报资讯|18th Aug. , 2025
  • 【GNSS定位原理及算法杂记6】​​​​​​PPP(精密单点定位)原理,RTK/PPK/PPP区别讨论
  • usb通信中工作模式:主机模式和设备模式
  • 2025年渗透测试面试题总结-21(题目+回答)
  • 水闸安全监测的主要核心内容
  • Java NIO 核心精讲(上):Channel、Buffer、Selector 详解与 ByteBuffer 完全指南
  • 数字政务安全实战:等保2.0下OA系统的身份认证与数据防护
  • 微软AD国产化替换倒计时——不是选择题,而是生存题
  • 三次握手四次挥手
  • 决策树算法详解
  • Orange的运维学习日记--47.Ansible进阶之异步处理
  • ESP32应用——HTTP client(ESP-IDF框架)
  • STM32之MCU和GPIO
  • AT_abc397_f [ABC397F] Variety Split Hard
  • 高速传输的关键:8B/10B编码学习记录
  • 应用控制技术与内容审计技术
  • 系统架构设计师-操作系统-避免死锁最小资源数原理模拟题
  • 寻找旋转排序数组中的最小值
  • 黄金本周想法
  • 给类或实例打上标识即类的元数据标签方便程序在运行时对其进行分类、识别、筛选
  • 32K上下文开源语音理解、40分钟深度交互——Voxtral-Small-24B-2507本地部署教程
  • GCC编译输出中text,data,bss和dec的含义
  • 构建自主企业:AgenticOps 的技术蓝图
  • 基于 STM32 单片机的远程老人监测系统设计
  • 科大讯飞语音服务之:BNF文件
  • 基于用户画像的个性化匹配模型
  • 【Proteus仿真】【51单片机】基于51单片机自动售货机12864屏幕
  • 这是关于Oracle碎片的文章