贵阳百度做网站电话,介绍网络营销的短文,织梦程序如何搭建网站,wordpress导航位置本文为从零开始写 Docker 系列第七篇#xff0c;实现类似 docker commit 的功能#xff0c;把运行状态的容器存储成镜像保存下来。 完整代码见#xff1a;https://github.com/lixd/mydocker 欢迎 Star 推荐阅读以下文章对 docker 基本实现有一个大致认识#xff1a;
核心原…
本文为从零开始写 Docker 系列第七篇实现类似 docker commit 的功能把运行状态的容器存储成镜像保存下来。 完整代码见https://github.com/lixd/mydocker 欢迎 Star 推荐阅读以下文章对 docker 基本实现有一个大致认识
核心原理深入理解 Docker 核心原理Namespace、Cgroups 和 Rootfs基于 namespace 的视图隔离探索 Linux NamespaceDocker 隔离的神奇背后基于 cgroups 的资源限制 初探 Linux Cgroups资源控制的奇妙世界深入剖析 Linux Cgroups 子系统资源精细管理Docker 与 Linux Cgroups资源隔离的魔法之旅 基于 overlayfs 的文件系统Docker 魔法解密探索 UnionFS 与 OverlayFS基于 veth pair、bridge、iptables 等等技术的 Docker 网络揭秘 Docker 网络手动实现 Docker 桥接网络 开发环境如下
rootmydocker:~# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 20.04.2 LTS
Release: 20.04
Codename: focal
rootmydocker:~# uname -r
5.4.0-74-generic注意需要使用 root 用户 1. 概述
由于之前使用 pivotRoot overlayfs 技术 将 /root/merged 目录作为容器的 rootfs因此容器中的所有改动都发生在该目录下。
这里我们的 mydocker commit 命令只需要把该目录保存下来即可因此简单实现为 使用 tar 命令将/root/merged 目录打成 tar 包
2. 实现
具体流程
整个打包流程如下图所示 commitCommand
在 main_ command.go 文件中实现 commitCommand 命令,从用户的输入获取image name。
var commitCommand cli.Command{Name: commit,Usage: commit container to image,Action: func(context *cli.Context) error {if len(context.Args()) 1 {return fmt.Errorf(missing image name)}imageName : context.Args().Get(0)commitContainer(imageName)return nil},
}然后在 main 方法中添加 commit 命令
func main() {app : cli.NewApp()app.Name mydockerapp.Usage usageapp.Commands []cli.Command{initCommand,runCommand,commitCommand,}// 省略其他
}commitContainer
添加 commit.go文件通过 commitContainer 函数实现将容器文件系统打包成$ {imagename}.tar 文件。
func commitContainer(imageName string) {mntPath : /root/mergedimageTar : /root/ imageName .tarfmt.Println(commitContainer imageTar:, imageTar)if _, err : exec.Command(tar, -czf, imageTar, -C, mntPath, .).CombinedOutput(); err ! nil {log.Errorf(tar folder %s error %v, mntPath, err)}
}如果你对云原生技术充满好奇想要深入了解更多相关的文章和资讯欢迎关注微信公众号。
搜索公众号【探索云原生】即可订阅 3. 测试
测试流程如下
1启动容器2创建新文件3新终端中将容器打包为镜像4解压该镜像查看 2 中的内容是否存在
首先启动容器
rootmydocker:~/feat-commit/mydocker# ./mydocker run -it /bin/sh
{level:info,msg:resConf:\u0026{ 0 },time:2024-01-19T16:18:2408:00}
{level:info,msg:busybox:/root/busybox busybox.tar:/root/busybox.tar,time:2024-01-19T16:18:2408:00}
{level:info,msg:mount overlayfs: [/usr/bin/mount -t overlay overlay -o lowerdir/root/busybox,upperdir/root/upper,workdir/root/work /root/merged],time:2024-01-19T16:18:2408:00}
{level:info,msg:command all is /bin/sh,time:2024-01-19T16:18:2408:00}
{level:info,msg:init come on,time:2024-01-19T16:18:2408:00}
{level:info,msg:Current location is /root/merged,time:2024-01-19T16:18:2408:00}
{level:info,msg:Find path /bin/sh,time:2024-01-19T16:18:2408:00}创建一个文件
/ # echo KubeExplorer tmp/hello.txt
/ # cat /tmp/hello.txt
KubeExplorer接着另外打开 terminal 执行 mydocker commit 命令将当前容器提交为镜像
rootmydocker:~/feat-commit/mydocker# ./mydocker commit myimage
commitContainer imageTar: /root/myimage.tar再次查看root 目录的内容多了 myimage.tar 文件这个就是我们的镜像文件了
rootmydocker:~# ls
busybox busybox.tar merged myimage.tar upper volume work查看 myimage.tar 中内容
rootmydocker:~# tar -tf myimage.tar |grep hello.txt
./tmp/hello.txt可以看到前面在容器中创建的 hello.txt 是存在的。
4. 总结
本篇 mydocker commit 比较简单就是使用 tar 命令将 rootfs 直接进行打包没有太多需要注意的地方。
镜像构造部分到此就基本完成了总结一下 1首先使用 busybox 作为基础镜像创建了一个容器理解了什么是 rootfs以及如何使用 rootfs 来打造容器的基本运行环境。 2然后使用 overlayfs 来构建了一个拥有二层模式的镜像对于最上层可写层的修改不会影响到基础层。这里就基本解释了镜像分层存储的原理。 3之后使用 -v 参数做了一个 volume 挂载的例子介绍了如何将容器外部的文件系统挂载到容器中并且让它可以访问。 4最后本文实现了一个简单版本的容器镜像打包。
这一章主要针对镜像的存储及文件系统做了基本的原理性介绍通过这几个例子可以很好地理解镜像是如何构建的后续会基于这些基础做更多的扩展。 **【从零开始写 Docker 系列】**持续更新中搜索公众号【探索云原生】订阅文章。 完整代码见https://github.com/lixd/mydocker 欢迎 Star 相关代码见 feat-volume 分支,测试脚本如下 需要提前在 /root 目录准备好 busybox.tar 文件具体见第四篇第二节。 # 克隆代码
git clone -b feat-commit https://github.com/lixd/mydocker.git
cd mydocker
# 拉取依赖并编译
go mod tidy
go build .
# 测试
./mydocker run -it /bin/ls
./mydocker commit