Docker 的出現爲開發人員和運維人員帶來了極大的便利,在使用Docker容器時,有沒有想過docker鏡像是怎麼來的呢,雖然現在可以從網上的鏡像倉庫下載鏡像,但是第三方提供的鏡像有時候並不符合我們的要求,我們有必要創建自己的基礎鏡像,然後在這個基礎鏡像上面,去構建各種應用鏡像。本文將介紹創建Docker基礎鏡像的兩種方法,分別是:1、通過tar打包現有的操作系統,然後導入Docker鏡像倉庫;2、使用mkimage-yum.sh腳本製作;
基礎環境:
1、兩種方式我都是在同一臺虛擬機上操作的完成的,首先我們要準備好基礎的操作系統,此次我通過虛擬機安裝的rhel7.4的操作系統,安裝方式是最小化安裝,因爲我們需要將建出來的基礎鏡像儘可能的小。
2、安裝好docker(參考之前的文章https://blog.csdn.net/bjywxc/article/details/103373730)。
方式一:本地直接打包導入方式
1、安裝好最小化系統之後,使用tar進行打包,排除一些不必要的目錄。
tar --numeric-owner --exclude=/proc --exclude=/sys --exclude=/mnt --exclude=/tmp --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 /tmp/rhel7.4-Base.tar.gz /
2、導入到docker鏡像
[root@localhost /]# cat /tmp/rhel7.4-Base.tar.gz| docker import - rhel7.4-tar
sha256:33b316e0e89c08462ef93affa55ed1768045bc73e33d0c6ded6cd837f0da1af8
[root@localhost /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
rhel7.4-tar latest 33b316e0e89c 7 seconds ago 978MB
3、運行容器
[root@localhost /]# docker run -it rhel7.4-tar /bin/bash
[root@0a56c30bbf0a /]# df -h
文件系統 容量 已用 可用 已用% 掛載點
overlay 39G 2.8G 36G 8% /
tmpfs 64M 0 64M 0% /dev
tmpfs 997M 0 997M 0% /sys/fs/cgroup
shm 64M 0 64M 0% /dev/shm
/dev/mapper/rhel-root 39G 2.8G 36G 8% /etc/hosts
tmpfs 997M 0 997M 0% /proc/acpi
tmpfs 997M 0 997M 0% /proc/scsi
tmpfs 997M 0 997M 0% /sys/firmware
[root@0a56c30bbf0a /]# more /etc/redhat-release
Red Hat Enterprise Linux Server release 7.4 (Maipo)
方式二:mkimage-yum.sh腳本方式
1、腳本地址:https://raw.githubusercontent.com/docker/docker/master/contrib/mkimage-yum.sh或者https://github.com/moby/moby/blob/master/contrib/mkimage-yum.sh
2、腳本內容
#!/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"
3、運行腳本創建
[root@localhost /]# chmod 777 mkimage-yum.sh
[root@localhost /]#./mkimage-yum.sh -y /etc/yum.conf rhel7.4-mk
4、等待執行完成,查看是否創建成功。
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
rhel7.4-mk 7.7.1908 2e4f95289f64 18 minutes ago 281MB
rhel7.4-tar latest 33b316e0e89c 41 minutes ago 978MB
[root@localhost /]# docker run -it rhel7.4-mk:7.7.1908 /bin/bash
[root@c9b2fa5d5e50 /]# df -h
Filesystem Size Used Avail Use% Mounted on
overlay 39G 3.1G 36G 8% /
tmpfs 64M 0 64M 0% /dev
tmpfs 997M 0 997M 0% /sys/fs/cgroup
shm 64M 0 64M 0% /dev/shm
/dev/mapper/rhel-root 39G 3.1G 36G 8% /etc/hosts
tmpfs 997M 0 997M 0% /proc/acpi
tmpfs 997M 0 997M 0% /proc/scsi
tmpfs 997M 0 997M 0% /sys/firmware
[root@c9b2fa5d5e50 /]# more /etc/redhat-release
CentOS Linux release 7.7.1908 (Core)
總結:
1、兩種方式都能實現,通過比對可以發現通過tar打包創建的基礎鏡像的體積大約是通過mkimage-yum.sh腳本創建的基礎鏡像的3倍左右,
2、兩個鏡像的版本不一致,tar打包的方式生成的鏡像版本和虛擬機一致rhel7.4,而腳本方式的鏡像版本是centos7.7,猜測是以yum源的版本生成的。
3、兩種方式各有特點,tar方式可以自定義安裝軟件和版本等,體積大;而腳本方式只能安裝官方yum源裏面支持的包,不能自定義,但是體積小。