博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
自己动手写docker-4
阅读量:6588 次
发布时间:2019-06-24

本文共 2727 字,大约阅读时间需要 9 分钟。

4.构造镜像

4.1 使用busybox基本镜像构造容器

  • docker export -o busybox.tar c5a45bda498e(容器id) 可以起一个busybox的后台运行容器,通过export导出文件系统,查看下结构
  • pivot_root系统调用,用于改变root文件系统
    • int pivot_root(const char *new_root, const char *put_old); 会将原先的root文件系统move到put_old,然后以new_root作为调用进程的新的root文件系统
  • pivot_rootchroot的区别:
    • pivot_root把进程切换到一个新的root目录,对之前root文件系统的不再有依赖,这样你就能够umount原先的root文件系统。
    • chroot只是更改了root目录,还会依赖老的文件系统,主要使用的目的一般是为了限制用户的访问。
  • pivot_root相关代码:
func pivotRoot(root string) error {	//这个root目录在之前通过cmd.Dir='/path/busybox'设置好了	// new_root 和put_old 必须不能同时存在当前root 的同一个文件系统中,需要通过--bind重新挂载一下	if err := syscall.Mount(root, root, "bind", syscall.MS_BIND|syscall.MS_REC, ""); err != nil {		return fmt.Errorf("mount --bind PWD PWD error ")	}	pivotDir := filepath.Join(root, old_root)	if err := os.Mkdir(pivotDir, 0777); err != nil {		return err	}	if err := syscall.PivotRoot(root, pivotDir); err != nil {		return fmt.Errorf("privot_root error %v", err)	}	log.Infof("now change dir to root")	if err := syscall.Chdir("/"); err != nil {		return fmt.Errorf("chdir / %v", err)	}	// 更新下文件路径	pivotDir = filepath.Join("/", old_root)	if err := syscall.Unmount(pivotDir, syscall.MNT_DETACH); err != nil {		return fmt.Errorf("umount pivot_root dir %v", err)	}	return os.Remove(pivotDir)}复制代码

4.2 使用AUFS包装busybox

  • 上一步构建好之后其实所有的操作都会影响busybox目录,需要将镜像和容器做隔离
  • 大致的思路是在进入init进程进行pivotRoot之前,需要加上以下操作
    • 启动容器时,将两个目录AUFS挂载到(ex:path/mnt),一个是read-wirte一个是read-only(一般是镜像文件,ex:busybox的文件系统)
    • 退出时卸载并且删除read-write文件系统
  • 流程如下

比较关键的就一步挂载AUFS

func CreateMountPoint(rootUrl string, mntUrl string) {	if err := os.Mkdir(mntUrl, 0777); err != nil {		log.Errorf("Mkdir dir %s error. %v", mntUrl, err)	}	dirs := "dirs=" + rootUrl + "writeLayer:" + rootUrl + "busybox"	cmd := exec.Command("mount", "-t", "aufs", "-o", dirs, "none", mntUrl)	cmd.Stdout = os.Stdout	cmd.Stderr = os.Stderr	if err := cmd.Run(); err != nil {		log.Errorf("%v", err)	}}复制代码

4.3实现volumn数据卷

就是实现docker run -v xxx:yyy,支持挂载外部文件到容器中去

  • 相较于4.2的实现,在启动容器时在mnt挂载完成后多了一步挂载volumn
func MountVolume(rootURL string, mntURL string, volumeURLs []string)  {	parentUrl := volumeURLs[0]	if err := os.Mkdir(parentUrl, 0777); err != nil {		log.Infof("Mkdir parent dir %s error. %v", parentUrl, err)	}	containerUrl := volumeURLs[1]	containerVolumeURL := mntURL + containerUrl	if err := os.Mkdir(containerVolumeURL, 0777); err != nil {		log.Infof("Mkdir container dir %s error. %v", containerVolumeURL, err)	}	dirs := "dirs=" + parentUrl	cmd := exec.Command("mount", "-t", "aufs", "-o", dirs, "none", containerVolumeURL)	cmd.Stdout = os.Stdout	cmd.Stderr = os.Stderr	if err := cmd.Run(); err != nil {		log.Errorf("Mount volume failed. %v", err)	}}复制代码
  • 在退出时加一步umount操作,和挂载顺序相反。
  • 大致流程

4.4 实现简单镜像打包(略)

实现类似docker commit xxx的功能

  • 比较简单就是在容器运行时 tar 压缩下 path/mnt的文件

转载地址:http://eehno.baihongyu.com/

你可能感兴趣的文章
C# 线程手册 第三章 使用线程 Monitor.TryEnter()
查看>>
分享11个超棒的移动应用(mobile apps)开发解决方案
查看>>
mysql5.5.17源代码安装
查看>>
关于【cocos2dx-3.0beta-制作flappybird】教程在3.2project中出现找不到CCMenuItem.h的解决方法...
查看>>
7z格式、LZMA压缩算法和7-Zip详细介绍
查看>>
imx6 uboot splash image
查看>>
转:全栈工程师的知识栈列表
查看>>
C/C++获取文件大小
查看>>
深入理解Java内存模型(五)——锁
查看>>
Chalubo僵尸网络来袭 IOT设备或将受到DDoS攻击
查看>>
实用功能一手玩转!复合机操控面板一览
查看>>
乌鲁木齐大雾弥漫 局地能见度不足200米
查看>>
骚年,还在为歌荒发愁吗?python教你爬取网易云热门歌单
查看>>
如何实现百万TPS?详解JMQ4的存储设计
查看>>
Play! Framework 系列(一):初探 play 框架
查看>>
Shiro【授权、整合Spirng、Shiro过滤器】
查看>>
MarkDown语法
查看>>
这么说吧,NIO很简单,其实就是个牛逼IO
查看>>
七、【应用的主要框架】
查看>>
使用Python快速获取公众号文章定制电子书(二)
查看>>