初稿日期:2017-01-17
更新日期:2022-04-12
环境:CentOS Linux release 7.9.2009 (Core)
Docker 版本:20.10.14

刚开始使用 Docker 时感兴趣于如何手动创建一个系统的镜像,于是找到 mkimage-yum.sh 脚本测试了下。

本文在 CentOS 7 下制作 CentOS 7 的 Docker 镜像。

获取镜像:https://mirror.tuna.tsinghua.edu.cn/centos/7/isos/x86_64/
镜像文件:CentOS-7-x86_64-Minimal-2009.iso

获取 mkimage-yum.sh 脚本

  1. wget https://raw.githubusercontent.com/moby/moby/master/contrib/mkimage-yum.sh
  2. chmod +x mkimage-yum.sh

稍微看了下脚本

  • 使用 mktemp 命令创建临时目录
  • 使用 mknod 创建 /dev 相关节点
  • 执行 yum 安装命令
    • 参数 -g 指定额外安装的 Group,默认安装 Core
    • 参数 -p 指定额外安装的 Package
    • 通过 --installroot 参数将文件安装到先前创建的临时目录
    • 执行 clean all 清除 yum 缓存
  • 删除一些文件:locales,docs,man pages,i18n 等等
  • 使用 tar 打包文件,导入 docker,删除临时目录

配置 yum 源

脚本使用 yum 命令安装软件,如果网络环境不好可以选择挂载 ISO 镜像文件,否则可以跳过此步骤。

  1. wget https://mirror.tuna.tsinghua.edu.cn/centos/7/isos/x86_64/CentOS-7-x86_64-Minimal-2009.iso
  2. mkdir /media/CentOS
  3. mount -o loop,ro CentOS-7-x86_64-Minimal-2009.iso /media/CentOS

为了屏蔽系统默认配置的源,还需要将 /etc/yum.repos.d/ 目录下的 repo 文件改名或移动到其他目录下

  1. cd /etc/yum.repos.d/
  2. mkdir bak && mv *.repo bak

配置 yum 镜像源

  1. cat > /etc/yum.repos.d/media.repo << EOF
  2. [media]
  3. name=media
  4. baseurl=file:///media/CentOS
  5. gpgcheck=0
  6. EOF
  7. yum clean all
  8. yum makecache

创建 Docker 镜像

  1. ./mkimage-yum.sh centos

参数指定的 centos 即是生成的 docker 镜像的名称,默认仅仅安装最核心的包,也可以指定安装额外的包到 docker 容器中,例如:

  1. ./mkimage-yum.sh -p "zip unzip" centos

脚本在创建完镜像后直接导入到 docker 中,因此运行该脚本的环境中需要已安装 Docker,可以查看:

  1. # docker images
  2. REPOSITORY TAG IMAGE ID CREATED SIZE
  3. centos 7.9.2009 e77700230d99 19 seconds ago 283MB

脚本修改

mkimage-yum.sh 在制作过程删除了很多文件,在使用中可能导致出现很多平时不会遇到的问题,比如:

  • 无法为新建帐号设置密码(因为删除了 /usr/share/cracklib/ 目录)
  • 无法设置 locale,容器内将使用 POSIX 作为默认的 locale

因为删除相关文件给重新设置 locale 增加很多麻烦(需重新安装 glibc-common),而如果使用默认的 POSIX 可能导致如 MySQL 在导入 UTF8 的中文数据时出现“Data too long for column”的错误。

因此,我对脚本做了一些修改(因为需要全功能的测试环境)

  • 保留 /usr/share/cracklib/ 目录,方便需要时支持创建用户
  • locales 精简掉大部分,只保留 en_US.utf8, zh_CN.utf8
  • 设置时区为 Asia/Shanghai
  • 设置默认使用编码 en_US.UTF-8
  • 默认不导入镜像到 Docker 中

修改后的代码上传到 Gist,查看:https://gist.github.com/pysense/82cdc84b4ce2203325a481c3cf40ffd1

重新创建镜像,创建完成后将在当前目录生成 $name-$version.tar 文件。

  1. ./new-mkimage-yum.sh centos

需手动导入镜像

  1. docker import centos-7.9.2009.tar 1057/centos:7.9.2009

查看导入的镜像

  1. # docker images
  2. REPOSITORY TAG IMAGE ID CREATED SIZE
  3. 1057/centos 7.9.2009 0175896b716d 1 minutes ago 295MB

比之前的包稍微大了点,启动一个实例看下:

  1. # docker run -it --rm 1057/centos:7.9.2009 /bin/bash
  2. [root@407039097bf2 /]# locale -a
  3. C
  4. en_US.utf8
  5. POSIX
  6. zh_CN.utf8
  7. [root@407039097bf2 /]# locale
  8. LANG=en_US.UTF-8
  9. LC_CTYPE="en_US.UTF-8"
  10. LC_NUMERIC="en_US.UTF-8"
  11. LC_TIME="en_US.UTF-8"
  12. LC_COLLATE="en_US.UTF-8"
  13. LC_MONETARY="en_US.UTF-8"
  14. LC_MESSAGES="en_US.UTF-8"
  15. LC_PAPER="en_US.UTF-8"
  16. LC_NAME="en_US.UTF-8"
  17. LC_ADDRESS="en_US.UTF-8"
  18. LC_TELEPHONE="en_US.UTF-8"
  19. LC_MEASUREMENT="en_US.UTF-8"
  20. LC_IDENTIFICATION="en_US.UTF-8"
  21. LC_ALL=
  22. [root@407039097bf2 /]# date
  23. Tue Apr 12 15:46:33 CST 2022