容器基础(四): 自定义简单容器镜像

为什么需要容器镜像

1. Mount Namespace一定是伴随着挂载操作(mount)才能生效。即使开启了 Mount Namespace,在执行挂载操作前, 新创建的容器也会直接继承宿主机的各个挂载点, 容器进程看到的文件系统跟宿主机完全一样。
2. 为了能让容器启动后看到的文件系统是独立的,和宿主机不同, 借助chroot/pivot_root, 可以把程序的根目录挂载到一个目录(rootfs)上,从而让程序看到一个和宿主机"不一样"的文件系统。

 

如何自定义一个文件系统

简单的方法就是参考一个Linux目录结构,生成对应目录,然后把需要的命令和动态库拷贝到自定义文件系统。或者可以把busybox放到自定义文件系统,这样可以不用拷贝命令。

 

使用脚本生成一个根文件系统rootfs如下所示(脚本会生成必要的目录并且拷贝常用的一些命令到rootfs):

 1 #!/bin/sh
 2 # 不同机器命令的路径可能不同, 只是一个简单脚本, 根据需要手动改
 3 rootfs_path=/var/lib/sdocker/rootfs
 4 rootfs_command=("/bin/bash"  "/bin/ls"       "/bin/ps" \
 5                 "/bin/ss"    "/bin/hostname" "/bin/ip" \
 6                 "/bin/mount" "/bin/cat"      "/usr/bin/vim")
 7 
 8 function create_directory()
 9 {
10   if [ ! -z "${1}" -a ! -d "${1}" ]; then
11     mkdir -p "${1}"
12   fi
13 }
14 
15 function create_rootfs_directory()
16 {
17   # create sub-directory of rootfs
18   local rootfs_dirs=(bin dev etc lib64 media opt root sbin sys usr boot env home lib mnt proc run srv tmp var)
19   for dirs in ${rootfs_dirs[@]}; do
20     create_directory $rootfs_path/$dirs
21   done
22 }
23 
24 function copy_command()
25 {
26   # copy all files needed by command
27   for cmd in ${rootfs_command[@]}; do
28     echo "[+] copy command $cmd"
29     local cmd_dir=${rootfs_path}$(dirname $cmd)
30     create_directory $cmd_dir
31     cp $cmd $cmd_dir
32     echo "  -> copy file: $cmd"
33 
34     dependence_list="$(ldd $cmd | egrep -o '/.*lib.*\.[0-9]+')"
35     for deps in ${dependence_list}; do
36       deps_dir=${rootfs_path}$(dirname $deps)
37       create_directory $deps_dir
38       cp $deps $deps_dir
39       echo "  -> copy file: $deps"
40     done
41   done
42 }
43 
44 function main()
45 {
46   create_directory $rootfs_path
47   create_rootfs_directory
48   copy_command
49 }
50 
51 main
namespace  ./gen_rootfs.sh 
[+] copy command /bin/bash
  -> copy file: /bin/bash
  -> copy file: /lib/x86_64-linux-gnu/libncurses.so.5
  -> copy file: /lib/x86_64-linux-gnu/libtinfo.so.5
  -> copy file: /lib/x86_64-linux-gnu/libdl.so.2
  -> copy file: /lib/x86_64-linux-gnu/libc.so.6
  -> copy file: /lib64/ld-linux-x86-64.so.2
[+] copy command /bin/ls
  -> copy file: /bin/ls
  -> copy file: /lib/x86_64-linux-gnu/libselinux.so.1
  -> copy file: /lib/x86_64-linux-gnu/libacl.so.1
  -> copy file: /lib/x86_64-linux-gnu/libc.so.6
  -> copy file: /lib/x86_64-linux-gnu/libpcre.so.3
  -> copy file: /lib/x86_64-linux-gnu/libdl.so.2
  -> copy file: /lib64/ld-linux-x86-64.so.2
  -> copy file: /lib/x86_64-linux-gnu/libattr.so.1
  -> copy file: /lib/x86_64-linux-gnu/libpthread.so.0
[+] copy command /bin/ps
  -> copy file: /bin/ps
  -> copy file: /lib/x86_64-linux-gnu/libprocps.so.3
  -> copy file: /lib/x86_64-linux-gnu/libdl.so.2
  -> copy file: /lib/x86_64-linux-gnu/libc.so.6
  -> copy file: /lib64/ld-linux-x86-64.so.2
[+] copy command /bin/ss
  -> copy file: /bin/ss
  -> copy file: /lib/x86_64-linux-gnu/libselinux.so.1
  -> copy file: /lib/x86_64-linux-gnu/libc.so.6
  -> copy file: /lib/x86_64-linux-gnu/libpcre.so.3
  -> copy file: /lib/x86_64-linux-gnu/libdl.so.2
  -> copy file: /lib64/ld-linux-x86-64.so.2
  -> copy file: /lib/x86_64-linux-gnu/libpthread.so.0
[+] copy command /bin/hostname
  -> copy file: /bin/hostname
  -> copy file: /lib/x86_64-linux-gnu/libnsl.so.1
  -> copy file: /lib/x86_64-linux-gnu/libc.so.6
  -> copy file: /lib64/ld-linux-x86-64.so.2
[+] copy command /bin/ip
  -> copy file: /bin/ip
  -> copy file: /lib/x86_64-linux-gnu/libdl.so.2
  -> copy file: /lib/x86_64-linux-gnu/libc.so.6
  -> copy file: /lib64/ld-linux-x86-64.so.2
[+] copy command /bin/mount
  -> copy file: /bin/mount
  -> copy file: /lib/x86_64-linux-gnu/libmount.so.1
  -> copy file: /lib/x86_64-linux-gnu/libselinux.so.1
  -> copy file: /lib/x86_64-linux-gnu/libc.so.6
  -> copy file: /lib/x86_64-linux-gnu/libblkid.so.1
  -> copy file: /lib64/ld-linux-x86-64.so.2
  -> copy file: /lib/x86_64-linux-gnu/libpcre.so.3
  -> copy file: /lib/x86_64-linux-gnu/libdl.so.2
  -> copy file: /lib/x86_64-linux-gnu/libuuid.so.1
  -> copy file: /lib/x86_64-linux-gnu/libpthread.so.0
[+] copy command /bin/cat
  -> copy file: /bin/cat
  -> copy file: /lib/x86_64-linux-gnu/libc.so.6
  -> copy file: /lib64/ld-linux-x86-64.so.2
[+] copy command /usr/bin/vim
  -> copy file: /usr/bin/vim
  -> copy file: /lib/x86_64-linux-gnu/libm.so.6
  -> copy file: /lib/x86_64-linux-gnu/libtinfo.so.5
  -> copy file: /lib/x86_64-linux-gnu/libselinux.so.1
  -> copy file: /lib/x86_64-linux-gnu/libacl.so.1
  -> copy file: /usr/lib/x86_64-linux-gnu/libgpm.so.2
  -> copy file: /lib/x86_64-linux-gnu/libdl.so.2
  -> copy file: /lib/x86_64-linux-gnu/libc.so.6
  -> copy file: /lib/x86_64-linux-gnu/libpcre.so.3
  -> copy file: /lib64/ld-linux-x86-64.so.2
  -> copy file: /lib/x86_64-linux-gnu/libattr.so.1
  -> copy file: /lib/x86_64-linux-gnu/libpthread.so.0namespace

 

总结

1. 文件系统只包括操作系统对应的文件, 配置和目录, 并不包括内核; 所以对于容器而言, 同一台机器上的所有容器, 都共享宿主机操作系统的内核;
2. 对应用而言, 除了一些第三方依赖, 操作系统本身也可以算作是应用的一个最大依赖。由于rootfs 里打包的不只是应用,还包括了整个操作系统的文件和目录,这也就意味着,应用以及它运行所需要的所有依赖,都被封装在了一起, 从而得到了容器被反复宣传至今的一个重要特性: 一致性。
3. 容器的一致性仅限于文件系统,若容器中应用依赖于kernel或cpu等的一些特性,那么一致性就不能满足。

 

posted @ 2018-12-04 16:48  子厚。  阅读(458)  评论(0编辑  收藏  举报