在《极简,利用Docker仅两行命令就能下载和编译OpenJDK11》一文中,我们用以下命令实现了OpenJDK11源码的下载:

docker run \
--rm \
-it \
-v /usr/local/work/openjdksrc:/output \
bolingcavalry/openjdksrc11:0.0.2

今天我们就来看下Docker镜像bolingcavalry/openjdksrc11:0.0.2的制作过程,看看它做了哪些事情来简化下载过程;

环境信息

  1. 操作系统:Ubuntu 16.04.5 LTS;
  2. Docker:18.06.1-ce;

准备材料

本次镜像用到了以下材料:

  1. Dockerfile:制作Docker镜像的脚本文件;
  2. cmd.sh:容器启动后执行的命令脚本;
  3. OpenJDK11源码压缩包(参考《Ubuntu环境下载OpenJDK11源码》);

您可以选择直接从GitHub下载上述所有内容,地址和链接信息如下表所示:

名称

链接

备注

项目主页

https://github.com/zq2599/openjdksrc11

该项目在GitHub上的主页

git仓库地址(https)

https://github.com/zq2599/openjdksrc11.git

该项目源码的仓库地址,https协议

git仓库地址(ssh)

git@github.com:zq2599/openjdksrc11.git

该项目源码的仓库地址,ssh协议

要注意的问题

制作镜像前有两个问题先考虑好:

  1. 基础镜像尽量小,由于容器启动后要执行一些shell命令,所以选用仅含bash工具的bash:5.0-rc;
  2. OpenJDK11源码包不小(超过1G),因此做成的镜像也很大,用户下载镜像时,一旦网络问题下载失败,docker会自动重试,此时是重新下载,这意味着之前的下载都白做了,为了缓解这个问题,可以把整个源码压缩包分割成多个小文件,这样虽然整体大小不变,但是失败时重新下载的文件是很小的,在linux环境执行以下命令,将整个OpenJDK11源码压缩包分割成多个最大10兆的文件:
split -b 10m jdk11.tar.gz jdk11-

编写Dockerfile

Dockerfile内容如下,可见大部分内容是复制文件的操作,其余部分已有详细的注释,就不多说了:

# Docker image of source for OpenJDK
# VERSION 0.0.2
# Author: bolingcavalry

#基础镜像使用bash:5.0-rc,特点是体积小
FROM bash:5.0-rc

#作者
MAINTAINER BolingCavalry <zq2599@gmail.com>

#定义源码存放目录
ENV SRC_PATH /src

#定义OpenJDK源码文件夹名称
ENV OPENJDK_SRC_PACKAGE_NAME jdk11

#创建目录
RUN mkdir $SRC_PATH

#把分割过的源码复制到工作目录,这么写可以保证每个文件layer都不大,这样下载镜像时如果中途失败,就不用重新下载一个巨大的layer
COPY ./$OPENJDK_SRC_PACKAGE_NAME-af $SRC_PATH/ 
COPY ./$OPENJDK_SRC_PACKAGE_NAME-an $SRC_PATH/ 
COPY ./$OPENJDK_SRC_PACKAGE_NAME-av $SRC_PATH/ 
COPY ./$OPENJDK_SRC_PACKAGE_NAME-bd $SRC_PATH/ 
COPY ./$OPENJDK_SRC_PACKAGE_NAME-bl $SRC_PATH/ 
COPY ./$OPENJDK_SRC_PACKAGE_NAME-bt $SRC_PATH/ 
COPY ./$OPENJDK_SRC_PACKAGE_NAME-cb $SRC_PATH/ 
COPY ./$OPENJDK_SRC_PACKAGE_NAME-cj $SRC_PATH/ 
COPY ./$OPENJDK_SRC_PACKAGE_NAME-cr $SRC_PATH/ 
COPY ./$OPENJDK_SRC_PACKAGE_NAME-cz $SRC_PATH/ 
COPY ./$OPENJDK_SRC_PACKAGE_NAME-dh $SRC_PATH/ 
COPY ./$OPENJDK_SRC_PACKAGE_NAME-dp $SRC_PATH/ 
COPY ./$OPENJDK_SRC_PACKAGE_NAME-dx $SRC_PATH/ 
COPY ./$OPENJDK_SRC_PACKAGE_NAME-ef $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-ag $SRC_PATH/ 
COPY ./$OPENJDK_SRC_PACKAGE_NAME-ao $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-aw $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-be $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-bm $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-bu $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-cc $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-ck $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-cs $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-da $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-di $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-dq $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-dy $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-eg $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-ah $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-ap $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-ax $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-bf $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-bn $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-bv $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-cd $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-cl $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-ct $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-db $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-dj $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-dr $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-dz $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-eh $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-aa $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-ai $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-aq $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-ay $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-bg $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-bo $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-bw $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-ce $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-cm $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-cu $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-dc $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-dk $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-ds $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-ea $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-ei $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-ab $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-aj $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-ar $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-az $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-bh $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-bp $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-bx $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-cf $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-cn $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-cv $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-dd $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-dl $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-dt $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-eb $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-ej $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-ac $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-ak $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-as $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-ba $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-bi $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-bq $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-by $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-cg $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-co $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-cw $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-de $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-dm $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-du $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-ec $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-ek $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-ad $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-al $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-at $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-bb $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-bj $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-br $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-bz $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-ch $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-cp $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-cx $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-df $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-dn $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-dv $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-ed $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-el $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-ae $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-am $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-au $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-bc $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-bk $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-bs $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-ca $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-ci $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-cq $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-cy $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-dg $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-do $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-dw $SRC_PATH/
COPY ./$OPENJDK_SRC_PACKAGE_NAME-ee $SRC_PATH/

#命令行文件复制到工作目录
COPY ./cmd.sh /

RUN chmod a+x /cmd.sh

CMD ["bash", "/cmd.sh"]

看到这里您一定会有疑问:这么多行COPY命令,为什么不用OPENJDK_SRC_PACKAGE_NAME-*,这样岂不是一行命令就够了?
您可以在镜像build成功后,用docker history命令看看文件的layer数量,用多个COPY命令逐个执行,每个命令都对应一个小的layer,这样用户下载镜像时就是在下载多个小文件了;

cmd.sh文件

cmd.sh的内容如下,可见当容器启动后,先将分割后的多个小文件通过cat命令恢复成完整的jdk11.tar.gz文件,再解压,然后删除jdk11.tar.gz文件:

echo "start build gz file"
cat $SRC_PATH/$OPENJDK_SRC_PACKAGE_NAME-* > /output/$OPENJDK_SRC_PACKAGE_NAME.tar.gz
echo "gz file build success, start unzip"
tar -zxvf /output/$OPENJDK_SRC_PACKAGE_NAME.tar.gz -C /output
echo "unzip success, start remove gz file"
rm /output/$OPENJDK_SRC_PACKAGE_NAME.tar.gz
echo "download openjdk11 source successful!"

构建镜像

在Dockerfile文件所在目录执行以下命令即可构建好镜像文件:

docker build -t bolingcavalry/openjdksrc11:0.0.2 .

至此,镜像制作完毕,可以通过Docker来下载完整的OepnJDK11源码了,如果电脑空间紧张,docker run命令执行完毕后,记得用docker rmi bolingcavalry/openjdksrc11:0.0.2删除镜像;