Docker
- 一:Docker简介
-
- 1.Docker是什么?
- 2.为什么需要Docker?
- [3.Docker 解决了什么问题?](#3.Docker 解决了什么问题?)
- 二:Docker版本
- 三:Docker的官方网站
- 四:容器基础命令详解
-
- 1.dd
-
- /dev/zero
- dd参数简单说明
- dd常用参数
-
- 1)if=:input fileif=:input file)
- [2)of=:output file](#2)of=:output file)
- [3)bs=:block size](#3)bs=:block size)
- 4)count=:读多少块
- 5)skip=:输入端跳过多少块
- 6)seek=:输出端跳过多少块
- 7)conv=:转换动作
- 2.mkfs
-
- [为什么一定要有 mkfs](#为什么一定要有 mkfs)
- mkfs的用处
- 3.mount
-
- [Linux 的文件系统](#Linux 的文件系统)
- [mount 命令结构](#mount 命令结构)
- 4.unshare
-
- [什么是 namespace?](#什么是 namespace?)
- unshare的作用
- 一个有关unshare的命令
- [unshare 常用参数](#unshare 常用参数)
- 5.虚拟机和容器的区别
一:Docker简介
1.Docker是什么?
Docker 是一个容器化平台 ,用于将应用及其依赖打包成一个独立的运行单元,以此来实现通过一次的构建,到处运行。
2.为什么需要Docker?
在Docker出现之前,程序员在自己的电脑配置完环境之后,上线到服务器的时候,由于环境的不同,通常会出现一系列大大小小的问题。
例如:
- 开发环境 ≠ 测试环境 ≠ 生产环境
- 依赖版本不同
- 系统配置不同
- 安装流程复杂
3.Docker 解决了什么问题?
(1)环境一致性
- 把应用 + 依赖 + 环境全部打包进镜像
- 不再依赖宿主机环境
(2)快速部署 - 通常启动一个容器只需几秒,相比虚拟机就快衡多了
- 不需要安装一堆环境,大大节省了时间和精力
(3)资源利用率高
| 对比项 | 虚拟机 | Docker |
|---|---|---|
| 启动速度 | 分钟级 | 秒级 |
| 资源占用 | 高 | 低 |
| 结构 | 操作系统级 | 进程级 |
(4)方便扩展和迁移
- 可以快速复制多个实例
- 云环境部署非常方便
总之。。
Docker 本质是:对进程进行隔离和封装,让应用运行环境标准化
二:Docker版本
Docker 主要分为社区版(Docker CE)和企业版(Docker EE),其中社区版免费且更新频繁,是开发者最常用的版本。Docker 底层依赖 containerd 和 runc 来完成容器的创建与运行。
(1)Docker CE(Community Edition)社区版
特点:1.免费2.更新快3.适合个人学习、开发环境
(2)Docker EE(Enterprise Edition) 企业版)
特点:1.收费2.提供企业支持3.安全、稳定、合规
(3)Moby(底层项目)Docker 的开源基础项目
三:Docker的官方网站
四:容器基础命令详解
1.dd
dd命令可以想象成一个数据搬运工
它的工作流程就三步:输入源 → 按块读取 → 可选转换 → 输出目标
在终端的命令就是
bash
dd if=输入源 of=输出目标 [其他参数]
注意:
1.在这里要说明的是,这个和cp很像,但是cp是文件层面的复制,而dd则是字节流/块设备层面的复制
2.它复制的对象不一定是普通文件,输入源可以是 设备文件,输出目标也可以是 设备文件,它是按"块"处理数据,不是按"文本行"处理。
/dev/zero
这里要讲解一下/dev/zero是什么?
/dev/zero 是一个特殊设备,会持续不断地产生空白字符流。于是你把它作为输入源,dd 就能不断读取"0 字节流",再写到目标文件里,于是就得到一个指定大小的空白文件。
命令:
bash
dd if=/dev/zero of=test.img bs=1M count=64
意思就是:
- 从 /dev/zero 读
- 写到 test.img
- 每次读写 1M
- 一共写 64 块
dd参数简单说明
参数说明:
if:输入文件
of:输出文件
ibs:一次读多少字节
obs:一次写多少字节
bs:同时设置读和写的块大小
count:读多少块
skip:输入跳过多少块
seek:输出跳过多少块
conv:转换动作
dd常用参数
1)if=:input file
bash
if=/dev/zero
表示输入源。
它不一定是真文件,可以是:
- 普通文件
- 分区
- 整块磁盘
- 特殊设备
常见场景:
从普通文件读取
从 /dev/zero 读取生成空白内容
从磁盘设备读取做备份
2)of=:output file
bash
of=fdimage.img
表示输出目标。
也不一定是真文件,也可以是:
- 普通文件
- 磁盘设备
- 分区设备
3)bs=:block size
bash
bs=8k
表示一次读写多少字节。
你怎么理解它
它像"水管口径"。
小块:操作次数多,可能慢
大块:操作次数少,通常更快
4)count=:读多少块
bash
count=10240
表示只处理这么多块。
真正的大小公式
总大小 = bs × count
比如:
bash
dd if=/dev/zero of=test.img bs=1M count=64
就是创建一个 64MB 文件。
5)skip=:输入端跳过多少块
定义是:从输入文件开头跳过若干 block 再读取。
场景
你不想从头读,只想从中间某个位置开始读。
比如:
dd if=file.bin of=part.bin bs=1M skip=10 count=5
意思是:
输入文件前 10MB 不读
从第 11MB 开始读
连续读 5MB
像切一段原始二进制数据。
6)seek=:输出端跳过多少块
定义是:从输出文件开头跳过若干 block,再开始写。
场景
你想把数据写到目标文件的某个偏移位置,而不是从头覆盖。
比如:
bash
dd if=patch.bin of=image.bin bs=1M seek=20 count=2
表示把 patch.bin 的内容写到 image.bin 的第 20MB 处。
这个思路本质上就是"按偏移打补丁"。
7)conv=:转换动作
这里列了多个转换选项,都是最常见的:
lcase:大写转小写
ucase:小写转大写
noerror:读错不停止
notrunc:不截断输出文件
sync:块不足时补齐
例如:
bash
dd if=testfile_2 of=testfile_1 conv=ucase
2.mkfs
mkfs 本质不是"格式化",而是"在一块空间里建立文件系统结构"
可以酱紫理解~
bash
dd:给你一块"空白空间"
mkfs:在这块空间里"建立文件系统规则"
没有 mkfs,这块空间只是"字节容器",不能当磁盘用。
为什么一定要有 mkfs
刚才我们已经通过命令dd创建出来了test.img,,
但是有以下问题:
此时 test.img:
bash
1.没有目录结构
2.没有 inode
3.没有文件系统元数据
4.不能 mount
本质上:
它只是一个 64MB 的"0数组"。
mkfs的用处
bash
mkfs -t ext4 test.img
本质是在这个文件里写入:
bash
superblock(超级块)
inode 表
block bitmap
数据区布局
文件系统元数据
其实就是:
原始空间 → 变成 ext4 文件系统
进一步理解:
| 概念 | 类比 |
|---|---|
| dd | 买了一块空硬盘 |
| mkfs | 给硬盘分区+格式化 |
| mount | 插上电脑并分配盘符 |
至于mount是什么后面再讲~
总之!
在容器与 Linux 文件系统实验中,dd 与 mkfs 通常组合使用:前者用于创建一块指定大小的原始存储空间(如镜像文件),后者则在该空间中初始化文件系统结构(如 ext4)。
dd 仅提供"字节级存储容器",而 mkfs 则为其赋予"文件系统语义"。只有在完成 mkfs 之后,该空间才能被 mount 挂载并以目录结构形式访问。
因此,mkfs 的本质并不是简单的"格式化",而是构建文件系统元数据结构,使原始存储具备文件管理能力。
3.mount
dd 是造空间,mkfs是造文件系统
现在:mount = 把这个文件系统接入 Linux 的世界
更加细致的理解就是
mount = 把"磁盘内容"映射到"目录树中的某个路径"
Linux 的文件系统
在Linux 的系统里面,它的文件系统是一棵统一的目录树 ,所有磁盘,都要"挂载"到这棵树上!!
| 概念 | 类比 |
|---|---|
| 磁盘 | 一个仓库 |
| mount | 给仓库开一个门 |
| 挂载点目录 | 门的位置 |
mount 命令结构
bash
mount [设备] [挂载点]
//例子
mount test.img /mnt/test
参数:
- -t(类型)
bash
mount -t ext4 test.img /mnt/test
指定文件系统类型(一般可以不写)
- -o loop(重点)
bash
mount -o loop test.img /mnt/test
这个是关键:
把"文件"当成"磁盘设备"
loop 是把文件当成硬盘分区挂载。
总之:
1.mount 命令用于将一个文件系统映射到 Linux 的目录树中,使其可以通过路径访问。
2.与传统认知不同,mount 并不会复制数据,而是建立"访问入口"。在容器技术中,mount namespace 可以让不同进程拥有独立的文件系统视图,从而实现文件系统级别的隔离。
3.在实际实验中,通常结合 dd 创建镜像文件,使用 mkfs 初始化文件系统,再通过 mount 将其挂载到目录中,从而模拟一个完整的磁盘环境。
4.unshare
unshare = 造"隔离环境"(容器雏形)
bash
unshare [选项] 程序
直接的理解就是:让子进程不和父进程共享 namespace(命名空间)
什么是 namespace?
namespace就是资源隔离机制
比如可以隔离:
- 进程(PID)
- 文件系统(mount)
- 网络(net)
- 主机名(UTS)
- 用户(user)
- IPC
unshare的作用
它不是"创建容器",而是:给你一个"新的世界视角"
就比如:同一个房子,给你戴上一个VR眼睛,你看到的是另一个世界
实际上:同一个内核,不同 namespace,看到不同资源
一个有关unshare的命令
UTS(主机名隔离)
bash
//表示进入一个新环境
unshare -u /bin/bash
此时我们再输入命令:
bash
hostname test1
hostname

然后再开一个新的终端~


其实还是原来的名字。
解释:
这里发生了什么?
bash
两个进程在同一台机器
但看到不同主机名
这就是:
bash
namespace = 视图隔离
unshare 常用参数
1.-u(UTS)
bash
unshare -u bash
隔离主机名
2.-p(PID)
bash
unshare -p bash
隔离进程空间
但必须配:
bash
--fork
否则会报错:
bash
Cannot allocate memory
因为:
子进程找不到父进程(PID 不在同一 namespace)
正确写法:
bash
unshare --fork --pid bash
- --mount
bash
unshare --mount bash
隔离文件系统挂载
- --mount-proc(非常关键)
如果不挂 /proc
ps 看到的还是宿主机进程
正确组合:
bash
unshare --fork --pid --mount-proc bash

才是"真正隔离进程空间"
总之:unshare 命令用于在 Linux 中创建新的命名空间,使得运行的程序与父进程在某些资源上不再共享。通过组合不同的 namespace(如 PID、Mount、UTS 等),可以让进程拥有独立的进程视图、文件系统视图和系统标识,从而模拟出类似独立操作系统的运行环境。
在容器技术中,unshare 所体现的 namespace 机制是实现隔离的核心基础,它使得多个进程在同一内核上运行,却彼此"不可见"。
5.虚拟机和容器的区别
容器不是虚拟机
bash
虚拟机:虚拟硬件 + 虚拟内核
容器:共享内核 + namespace 隔离