码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 从零开始写 Docker(七)---实现 mydocker commit 打包容器成镜像


    合集 - Docker(14)
    1.深入理解 Docker 核心原理:Namespace、Cgroups 和 Rootfs2023-12-262.探索 Linux Namespace:Docker 隔离的神奇背后01-043.初探 Linux Cgroups:资源控制的奇妙世界01-094.深入剖析 Linux Cgroups 子系统:资源精细管理01-125.Docker 与 Linux Cgroups:资源隔离的魔法之旅01-166.Docker 魔法解密:探索 UnionFS 与 OverlayFS01-197.从零开始写 Docker(一)---实现 mydocker run 命令02-228.从零开始写 Docker(二)---优化:使用匿名管道传递参数02-269.从零开始写 Docker(三)---基于 cgroups 实现资源限制03-0110.从零开始写 Docker(四)---使用 pivotRoot 切换 rootfs 实现文件系统隔离03-0511.从零开始写 Docker(五)---基于 overlayfs 实现写操作隔离03-1212.从零开始写 Docker(六)---实现 mydocker run -v 支持数据卷挂载03-14
    13.从零开始写 Docker(七)---实现 mydocker commit 打包容器成镜像03-19
    14.从零开始写 Docker(八)---实现 mydocker run -d 支持后台运行容器03-21
    收起

    mydocker-commit.png

    本文为从零开始写 Docker 系列第七篇,实现类似 docker commit 的功能,把运行状态的容器存储成镜像保存下来。


    完整代码见:https://github.com/lixd/mydocker
    欢迎 Star

    推荐阅读以下文章对 docker 基本实现有一个大致认识:

    • 核心原理:深入理解 Docker 核心原理:Namespace、Cgroups 和 Rootfs
    • 基于 namespace 的视图隔离:探索 Linux Namespace:Docker 隔离的神奇背后
    • 基于 cgroups 的资源限制
      • 初探 Linux Cgroups:资源控制的奇妙世界
      • 深入剖析 Linux Cgroups 子系统:资源精细管理
      • Docker 与 Linux Cgroups:资源隔离的魔法之旅
    • 基于 overlayfs 的文件系统:Docker 魔法解密:探索 UnionFS 与 OverlayFS
    • 基于 veth pair、bridge、iptables 等等技术的 Docker 网络:揭秘 Docker 网络:手动实现 Docker 桥接网络

    开发环境如下:

    root@mydocker:~# lsb_release -a
    No LSB modules are available.
    Distributor ID:	Ubuntu
    Description:	Ubuntu 20.04.2 LTS
    Release:	20.04
    Codename:	focal
    root@mydocker:~# uname -r
    5.4.0-74-generic
    

    注意:需要使用 root 用户

    1. 概述

    由于之前使用 pivotRoot + overlayfs 技术 将 /root/merged 目录作为容器的 rootfs,因此容器中的所有改动都发生在该目录下。

    这里我们的 mydocker commit 命令只需要把该目录保存下来即可,因此简单实现为 使用 tar 命令将/root/merged 目录打成 tar 包

    2. 实现

    具体流程

    整个打包流程如下图所示:

    mydocker-commit-process.png

    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 = "mydocker"
        app.Usage = usage
    
        app.Commands = []cli.Command{
           initCommand,
           runCommand,
           commitCommand,
        }
        // 省略其他
    }
    

    commitContainer

    添加 commit.go文件,通过 commitContainer 函数实现将容器文件系统打包成$ {imagename}.tar 文件。

    func commitContainer(imageName string) {
    	mntPath := "/root/merged"
    	imageTar := "/root/" + imageName + ".tar"
    	fmt.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 中的内容是否存在

    首先,启动容器

    root@mydocker:~/feat-commit/mydocker# ./mydocker run -it /bin/sh
    {"level":"info","msg":"resConf:\u0026{ 0  }","time":"2024-01-19T16:18:24+08:00"}
    {"level":"info","msg":"busybox:/root/busybox busybox.tar:/root/busybox.tar","time":"2024-01-19T16:18:24+08: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:24+08:00"}
    {"level":"info","msg":"command all is /bin/sh","time":"2024-01-19T16:18:24+08:00"}
    {"level":"info","msg":"init come on","time":"2024-01-19T16:18:24+08:00"}
    {"level":"info","msg":"Current location is /root/merged","time":"2024-01-19T16:18:24+08:00"}
    {"level":"info","msg":"Find path /bin/sh","time":"2024-01-19T16:18:24+08:00"}
    

    创建一个文件

    / # echo KubeExplorer > tmp/hello.txt
    / # cat /tmp/hello.txt
    KubeExplorer
    

    接着另外打开 terminal 执行 mydocker commit 命令,将当前容器提交为镜像

    root@mydocker:~/feat-commit/mydocker# ./mydocker commit myimage
    commitContainer imageTar: /root/myimage.tar
    

    再次查看/root 目录的内容,多了 myimage.tar 文件,这个就是我们的镜像文件了

    root@mydocker:~# ls
    busybox  busybox.tar merged  myimage.tar  upper  volume  work
    

    查看 myimage.tar 中内容:

    root@mydocker:~# 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
    
  • 相关阅读:
    vue自定义组件 事件修饰符 表单修饰符
    园子周边第3季-博客园T恤:设计初稿第2版预览
    【MD5】采用MD5+盐的加密方式完成注册用户和登录账号
    数据结构-leetcode-数组形式的整数加法
    kotlin
    python01- 安装部署
    笔试面试相关记录(10)
    鹰潭实验室设计要素盘点
    JavaScript基础学学习总结
    tiup mirror genkey
  • 原文地址:https://www.cnblogs.com/KubeExplorer/p/18082109
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号