Linux rootfs

前言

通过《initrd&init进程》我们知道rootfs 是文件系统的根目录,其包含了操作系统所需的所有文件和目录,包括程序、库文件、配置文件、设备文件等,它是系统启动时必须加载的文件系统之一。当系统启动后,内核会首先挂载 rootfs 到 / 目录下,然后开始运行 init 进程,执行各种初始化工作。

制作rootfs

  1. 下载busybox源码
git clone git://git.busybox.net/busybox
  1. 编译busybox
## 使用默认配置
make defconfig

## 或者自定义配置
make menuconfig

make install 
  1. 交叉编译
## 去下载交叉编译环境
wget https://releases.linaro.org/components/toolchain/binaries/6.4-2018.05/arm-linux-gnueabi/gcc-linaro-6.4.1-2018.05-x86_64_arm-linux-gnueabi.tar.xz

## 解压
tar xvf gcc-linaro-6.4.1-2018.05-x86_64_arm-linux-gnueabi.tar.xz -C  /opt/

## 配置动态编译
make menuconfig

Settings  --->
	--- Build Options
	(arm-linux-gnueabi-) Cross compiler prefix 

## 编译
exports ARCH=arm
exports CROSS_COMPILE=arm-linux-gnueabi-	
make
make install	
  1. 配置busybox启动环境
    在这里插入图片描述
## 复制busybox编译好的进 rootfs文件
cp _install/* ../rootfs/

## 查看你新环境命令要支持的库
ldd bin/sh
	linux-vdso.so.1 (0x00007ffd8c19f000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f714889a000)
	libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007f7148680000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f714828f000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f7148f3f000)

## 创建文件,并把库同路径移过来
mkdir lib lib64
cp /lib/x86_64-linux-gnu/*.so.*   lib/x86_64-linux-gnu/
cp /lib64/*.so.*  lib64/

## 如果是交叉编译的话移的是交叉环境里的库
cp /opt/gcc-linaro-6.4.1-2018.05-x86_64_arm-linux-gnueabi/arm-linux-gnueabi/lib ../rootfs  -rap

## 初始化配置
mkdir etc
cp ./examples/bootfloppy/etc/*  etc
mkdir dev  proc sys tmp var
## 修改/etc/init.d/rcS
PATH=/sbin:/bin:/usr/sbin:/usr/bin:$PATH
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib:/usr/lib
export PATH LD_LIBRARY_PATH

mount -a
mkdir /dev/pts
mount -t devpts devpts /dev/pts

echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s

## 修改/etc/fstab 主要是配置一些基本的文件系统挂载信息
proc            /proc           proc    defaults        0       0
tmpfs           /tmp            tmpfs   defaults        0       0
sysfs           /sys            sysfs   defaults        0       0

rootfs的使用

使用rootfs主要有两种方式,chroot 与pivot_root

chroot

chroot 就是可以改变某进程的根目录,使这个进程不能访问目录之外的其他目录。

sudo chroot .
pivot_root隔离

pivot_root把当前进程的root文件系统放在put_old目录,而使new_root成为新的root文件系统
改变当前工作目录的所有进程或线程的工作目录. 这个跟chroot的就有很大的区别,chroot是只改变即将运行的某进程的根目录。pviot_root主要是把整个系统切换到一个新的root目录,然后去掉对之前rootfs的依赖,以便于可以umount 之前的文件系统(pivot_root需要root权限)

unshare --mount --fork /bin/bash #需要有独立的命名空间
mkdir /new-root
mount -t tmpfs mytmpfs  /new-root #new-root是一个独立的挂载点
cd /new-root
mkdir old-root  #注意可以不创建old-root文件夹直接使用tmp文件夹
cp -r /ushare/busybox/* /new-root/ #new_root文件夹里面有完整rootfs的各种文件
cd ..
pivot_root /new-root/ /new-root/old-root
cd /
  1. 必须配合namespace使用
  2. 有了pivot_root,各厂商操作可以制作自己的rootfs(也就是镜像),提供给docker之前的容器商使用

容器中的自定义镜像

构建镜像的前提是必须依赖于基础镜像(是各大厂商提供的),docker中主要有两种方式

  1. 通过docker commit命令,基于一个已存在的容器构建出镜像。
  2. 编写 Dockerfile 文件,并使用docker build命令来构建镜像。

第一种方式,相当于基于基础镜像安装插件,然后再打包个镜像出来
第二种方式,编写配置文件,运行时去解析文件的内容构建出来

Docker 镜像的构建方式使用场景和选型

docker commit这种镜像构建方式通常用在下面两个场景中:

  • 构建临时的测试镜像;
  • 容器被入侵后,使用docker commit,基于被入侵的容器构建镜像,从而保留现场,方便以后追溯。

除了这两种场景,我不建议你使用docker commit来构建生产现网环境的镜像。原因如下:

  1. 使用docker commit构建的镜像包含了编译构建、安装软件,以及程序运行产生的大量无用文件,这会导致镜像体积很大,非常臃肿。
  2. 使用docker commit构建的镜像会丢失掉所有对该镜像的操作历史,无法还原镜像的构建过程,不利于镜像的维护。
  3. Dockerfile 的操作流程可以通过docker image history [镜像名称]查询,方便开发者查看变更记录。

假设一个镜像文件的大小是 500MB,启动 100 个容器的话,就需要下载 500MB*100= 50GB 的文件,并且占用 50GB 的磁盘空间

联合文件系 UnionFS

解决这个问题就要用到 UnionFS – 联合文件系统。其实用下面这张图就能明白它的本质:
在这里插入图片描述
图中上面就是我们说的启动100个容器需要50GB的方式,下面就是使用了联合文件系统 – 即文件共享!

从图中可以看到所有APP都共用"ubuntu:18.04"发行版文件系统,这样如果一个镜像文件的大小是 500MB,操作系统是400M,APP是100M的话,100个容器,就只需要 400MB + 100MB * 100 = 1G400M左右,是远远小于50GB。

UnionFS 有很多种,Docker 目前支持的联合文件系统包括 OverlayFS, AUFS, Btrfs, VFS, ZFS 和 Device Mapper

> docker history golang:1.19.3-alpine
IMAGE          CREATED        CREATED BY                                      SIZE      COMMENT
c50491847fcb   6 months ago   /bin/sh -c #(nop) WORKDIR /go                   0B        
<missing>      6 months ago   /bin/sh -c mkdir -p "$GOPATH/src" "$GOPATH/b…   0B        
<missing>      6 months ago   /bin/sh -c #(nop)  ENV PATH=/go/bin:/usr/loc…   0B        
<missing>      6 months ago   /bin/sh -c #(nop)  ENV GOPATH=/go               0B        
<missing>      6 months ago   /bin/sh -c set -eux;  apk add --no-cache --v…   343MB     
<missing>      6 months ago   /bin/sh -c #(nop)  ENV GOLANG_VERSION=1.19.3    0B        
<missing>      6 months ago   /bin/sh -c #(nop)  ENV PATH=/usr/local/go/bi…   0B        
<missing>      6 months ago   /bin/sh -c set -eux;  if [ -e /etc/nsswitch.…   0B        
<missing>      6 months ago   /bin/sh -c apk add --no-cache ca-certificates   515kB     
<missing>      6 months ago   /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B        
<missing>      6 months ago   /bin/sh -c #(nop) ADD file:57d621536158358b1…   5.29MB   

docker history 是操作顺序是从下往上看的, 如最后一条

<missing>      6 months ago   /bin/sh -c #(nop) ADD file:57d621536158358b1…   5.29MB  

即对就dockerFile的第一条 from alpine

file:57d621536158358b1… 

对应的UnionFS 的文件ID

主要参考

<linux> busybox制作rootfs
Busybox制作基本rootfs
chroot与pivot_root总结 完整的chroot与pivot_root使用例子
关于制作Docker镜像?| Dockerfile快速开始
深入学习docker – 联合文件系 OverlayFS

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值