Docker 的出现为开发人员和运维人员带来了极大的便利,在使用Docker容器时,有没有想过docker镜像是怎么来的呢,虽然现在可以从网上的镜像仓库下载镜像,但是第三方提供的镜像有时候并不符合我们的要求,我们有必要创建自己的基础镜像,然后在这个基础镜像上面,去构建各种应用镜像。本文将介绍创建Docker基础镜像的两种方法,分别是:1、通过tar打包现有的操作系统,然后导入Docker镜像仓库;2、使用mkimage-yum.sh脚本制作;
基础环境:
1、两种方式我都是在同一台虚拟机上操作的完成的,首先我们要准备好基础的操作系统,此次我通过虚拟机安装的rhel7.4的操作系统,安装方式是最小化安装,因为我们需要将建出来的基础镜像尽可能的小。
2、安装好docker。
方式一:本地直接打包导入方式
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源里面支持的包,不能自定义,但是体积小。