菜单
本页目录

[TOC]

制作方法

  • 通过 tar 打包已有的 CentOS 系统,然后导入 Docker 镜像仓库
  • 通过 mkimage-yum.sh 脚本,使用 yum 下载和安装必要的软件包,然后导入 Docker 镜像仓库

通过 tar 打包构建基础镜像

  • 卸载不必要的软件包
    • CentOS 6.9系统(虚拟机-1):
    	yum remove -y iwl* ql* xorg* ipw* *firmware* --exclude=kernel-firmware
    
    • CentOS 7.4.1708系统(虚拟机-2):
    	yum remove -y iwl* *firmware* --exclude=kernel-firmware
    
  • 清除 yum 缓存
    • CentOS 6.9系统(虚拟机-1):
    	yum clean all
    
    • CentOS 7.4.1708系统(虚拟机-2):
    	yum clean all
    	rm -rf /var/cache/yum
    
  • 打包文件系统
    • CentOS 6.9系统(虚拟机-1):
    	tar --numeric-owner --exclude=/proc --exclude=/sys --exclude=/mnt --exclude=/var/cache --exclude=/usr/share/{foomatic,backgrounds,perl5,fonts,cups,qt4,groff,kde4,icons,pixmaps,emacs,gnome-background-properties,sounds,gnome,games,desktop-directories} --exclude=/var/log -zcvf /mnt/CentOS-6.9-BaseImage.tar.gz /
    
    • CentOS 7.4.1708系统(虚拟机-2):
    	tar --numeric-owner --exclude=/proc --exclude=/sys --exclude=/mnt --exclude=/var/cache --exclude=/usr/share/{foomatic,backgrounds,perl5,fonts,cups,qt4,groff,kde4,icons,pixmaps,emacs,gnome-background-properties,sounds,gnome,games,desktop-directories} --exclude=/var/log -zcvf /mnt/CentOS-7.4-BaseImage.tar.gz /
    
  • 安装和启动 Docker
    • CentOS 6.9系统(虚拟机-1):
    	# 安装EPEL源和REMI源
    	rpm -Uvh https://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
    	rpm -Uvh https://rpms.remirepo.net/enterprise/remi-release-6.rpm
    
    	# 安装Docker软件包
    	yum install -y docker-io
    	# 启动Docker服务
    	service docker start
    
    • CentOS 7.4.1708系统(虚拟机-2):
    	# 安装EPEL源和REMI源
    	rpm -Uvh https://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-10.noarch.rpm
    	rpm -Uvh https://rpms.remirepo.net/enterprise/remi-release-7.rpm
    
    	# 安装Docker软件包
    	yum install -y docker-io
    
    	# 启动Docker服务
    	systemctl start docker.service
    
  • 导入镜像仓库
    • CentOS 6.9系统(虚拟机-1):
    	cat /mnt/CentOS-6.9-BaseImage.tar.gz | docker import - centos-tar:6.9
    
    • CentOS 7.4.1708系统(虚拟机-2):
    	cat /mnt/CentOS-7.4-BaseImage.tar.gz | docker import - centos-tar:7.4.1708
    
  • 验证

通过 mkimage-yum.sh 脚本构建基础镜像

  • 安装第三方源
    • CentOS 6.9系统(虚拟机-1):
    	rpm -Uvh https://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
    	rpm -Uvh https://rpms.remirepo.net/enterprise/remi-release-6.rpm
    
    • CentOS 7.4.1708系统(虚拟机-2):
    	rpm -Uvh https://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-release-7-13.noarch.rpm
    	rpm -Uvh https://rpms.remirepo.net/enterprise/remi-release-7.rpm
    
  • 安装和启动 Docker
    • CentOS 6.9 系统(虚拟机-1):
    	yum install -y docker-io
    	service docker start
    
    • CentOS 7.4.1708 系统(虚拟机-2):
    	yum install -y docker-io
    	systemctl start docker.service
    
  • 创建脚本文件
    • 新建mkimage-yum.sh脚本,这个文件就是 Docker 官方的创建镜像的脚本文件,URL 为
    	https://github.com/moby/moby/blob/master/contrib/mkimage-yum.sh
    
    • 在 Shell 中运行以下命令:
    	vi mkimage-yum.sh
    
    • CentOS 6.9 和 CentOS 7.4 的脚本内容相同,如下所示:
    	#!/usr/bin/env bash
    	#
    	# Create a base CentOS Docker image.
    	#
    	# This script is useful on systems with yum installed (e.g., building
    	# a CentOS image on CentOS).  See contrib/mkimage-rinse.sh for a way
    	# to build CentOS images on other systems.
    
    	set -e
    
    	usage() {
    		cat << EOOPTS
    	$(basename $0) [OPTIONS] <name>
    	OPTIONS:
    	  -p "<packages>"  The list of packages to install in the container.
    	                   The default is blank. Can use multiple times.
    	  -g "<groups>"    The groups of packages to install in the container.
    	                   The default is "Core". Can use multiple times.
    	  -y <yumconf>     The path to the yum config to install packages from. The
    	                   default is /etc/yum.conf for Centos/RHEL and /etc/dnf/dnf.conf for Fedora
    	  -t <tag>         Specify Tag information.
    	                   default is reffered at /etc/{redhat,system}-release
    	EOOPTS
    		exit 1
    	}
    
    	# option defaults
    	yum_config=/etc/yum.conf
    	if [ -f /etc/dnf/dnf.conf ] && command -v dnf &> /dev/null; then
    		yum_config=/etc/dnf/dnf.conf
    		alias yum=dnf
    	fi
    	# for names with spaces, use double quotes (") as install_groups=('Core' '"Compute Node"')
    	install_groups=()
    	install_packages=()
    	version=
    	while getopts ":y:p:g:t:h" opt; do
    		case $opt in
    			y)
    				yum_config=$OPTARG
    				;;
    			h)
    				usage
    				;;
    			p)
    				install_packages+=("$OPTARG")
    				;;
    			g)
    				install_groups+=("$OPTARG")
    				;;
    			t)
    				version="$OPTARG"
    				;;
    			\?)
    				echo "Invalid option: -$OPTARG"
    				usage
    				;;
    		esac
    	done
    	shift $((OPTIND - 1))
    	name=$1
    
    	if [[ -z $name ]]; then
    		usage
    	fi
    
    	# default to Core group if not specified otherwise
    	if [ ${#install_groups[*]} -eq 0 ]; then
    		install_groups=('Core')
    	fi
    
    	target=$(mktemp -d --tmpdir $(basename $0).XXXXXX)
    
    	set -x
    
    	mkdir -m 755 "$target"/dev
    	mknod -m 600 "$target"/dev/console c 5 1
    	mknod -m 600 "$target"/dev/initctl p
    	mknod -m 666 "$target"/dev/full c 1 7
    	mknod -m 666 "$target"/dev/null c 1 3
    	mknod -m 666 "$target"/dev/ptmx c 5 2
    	mknod -m 666 "$target"/dev/random c 1 8
    	mknod -m 666 "$target"/dev/tty c 5 0
    	mknod -m 666 "$target"/dev/tty0 c 4 0
    	mknod -m 666 "$target"/dev/urandom c 1 9
    	mknod -m 666 "$target"/dev/zero c 1 5
    
    	# amazon linux yum will fail without vars set
    	if [ -d /etc/yum/vars ]; then
    		mkdir -p -m 755 "$target"/etc/yum
    		cp -a /etc/yum/vars "$target"/etc/yum/
    	fi
    
    	if [[ -n "$install_groups" ]]; then
    		yum -c "$yum_config" --installroot="$target" --releasever=/ --setopt=tsflags=nodocs \
    			--setopt=group_package_types=mandatory -y groupinstall "${install_groups[@]}"
    	fi
    
    	if [[ -n "$install_packages" ]]; then
    		yum -c "$yum_config" --installroot="$target" --releasever=/ --setopt=tsflags=nodocs \
    			--setopt=group_package_types=mandatory -y install "${install_packages[@]}"
    	fi
    
    	yum -c "$yum_config" --installroot="$target" -y clean all
    
    	cat > "$target"/etc/sysconfig/network << EOF
    	NETWORKING=yes
    	HOSTNAME=localhost.localdomain
    	EOF
    
    	# effectively: febootstrap-minimize --keep-zoneinfo --keep-rpmdb --keep-services "$target".
    	#  locales
    	rm -rf "$target"/usr/{{lib,share}/locale,{lib,lib64}/gconv,bin/localedef,sbin/build-locale-archive}
    	#  docs and man pages
    	rm -rf "$target"/usr/share/{man,doc,info,gnome/help}
    	#  cracklib
    	rm -rf "$target"/usr/share/cracklib
    	#  i18n
    	rm -rf "$target"/usr/share/i18n
    	#  yum cache
    	rm -rf "$target"/var/cache/yum
    	mkdir -p --mode=0755 "$target"/var/cache/yum
    	#  sln
    	rm -rf "$target"/sbin/sln
    	#  ldconfig
    	rm -rf "$target"/etc/ld.so.cache "$target"/var/cache/ldconfig
    	mkdir -p --mode=0755 "$target"/var/cache/ldconfig
    
    	if [ -z "$version" ]; then
    		for file in "$target"/etc/{redhat,system}-release; do
    			if [ -r "$file" ]; then
    				version="$(sed 's/^[^0-9\]*\([0-9.]\+\).*$/\1/' "$file")"
    				break
    			fi
    		done
    	fi
    
    	if [ -z "$version" ]; then
    		echo >&2 "warning: cannot autodetect OS version, using '$name' as tag"
    		version=$name
    	fi
    
    	tar --numeric-owner -c -C "$target" . | docker import - $name:$version
    
    	docker run -i -t --rm $name:$version /bin/bash -c 'echo success'
    
    	rm -rf "$target"
    
  • 导入镜像
    	chmod 755 mkimage-yum.sh
    	./mkimage-yum.sh centos-mkimage
    

两种方法比较

由上述两图可知,通过 tar 打包创建的基础镜像的体积大约是通过mkimage-yum.sh脚本创建的基础镜像的3倍左右。这是由于前者是基于最小化安装的 CentOS 系统而创建的,而后者是从 CentOS 官方源安装必要的软件包而创建的,前者比后者多安装了很多软件包,包括邮件工具、设备驱动程序,等等。这两种方法各有特点:

  • 通过 tar 打包创建:基础镜像体积较大,但可以按照需求自由定制,适用于各种版本的CentOS系统,灵活度较高
  • 通过 mkimage-yum.sh 脚本创建:基础镜像体积较小,但只能安装官方源支持的软件包,并且只适用于最新版本的 CentOS 系统