基于alpine 3.16 和 openjdk 18 制作JRE镜像,构建Springboot项目镜像

760 阅读5分钟

1、起因 eclipse-temurin:18-jre-alpine 镜像有安全漏洞

1664537272344.png

2、相关的版本信息

  • alpine 3.16
  • openjdk 18
  • centos 7.9
  • docker 20.10.18
  • harbor 2.6.0
  • trivy 0.29.2

3、拉取镜像 alpine:3.16

[root@jason ~]# docker pull alpine:3.16

4、下载 openjdk-18 并在 alpine 容器中制作 JRE:openjre-18-alpine-musl

  • JDK 9开始就没有JRE,JDK 9和更高版本提供了jlink命令,以将一组模块及其依赖项组装和优化到自定义JRE Runtime中。
[root@jason ~]# cd /opt
[root@jason opt]# wget https://download.java.net/java/early_access/alpine/11/binaries/openjdk-18-ea+11_linux-x64-musl_bin.tar.gz
[root@jason opt]# docker run -it -v /opt/:/opt/ harbor.demo/os/alpine:3.16 /bin/sh
/ # cd /opt
/opt # tar zxvf openjdk-18-ea+11_linux-x64-musl_bin.tar.gz
/opt # cd jdk-18
/opt/jdk-18 # ./bin/jlink --module-path ./jmods --no-header-files --no-man-pages --add-modules java.base,java.sql,java.naming,java.desktop,java.management,java.security.jgss,java.instrument,java.rmi,java.xml --output /opt/jre-18
/opt/jdk-18 # du -sh .
306.5M    .
/opt/jdk-18 # cd ../jre-18
/opt/jre-18 # du -sh .
87.3M    .
/opt/jre-18 # tar zcvf ../openjre-18-alpine-musl.tar.gz ./*
/opt/jre-18 # exit
[root@jason opt]# ll openjre-18-alpine-musl.tar.gz
-rw-r--r-- 1 root root  33285587 10月 20 15:10 openjre-18-alpine-musl.tar.gz
[root@jason opt]# 
  • 可以根据项目具体需求增加和删除 module
  • JDK 306.5M 自定义 JRE 87.3M
  • 查看应用程序依赖的 module jdeps --list-deps xxxxx.jar

5、编写 Dockerfile,准备构建 JRE 镜像 openjre-alpine:18

[root@jason ~]# cd /opt
[root@jason opt]# vi openjre-18-alpine.dockerfile
FROM harbor.demo/os/alpine:3.16

MAINTAINER jason@vip.qq.com

WORKDIR /opt
ADD openjre-18-alpine-musl.tar.gz /usr/java/jre
ENV JAVA_VERSION=18
ENV JAVA_HOME=/usr/java/jre
ENV PATH=${JAVA_HOME}/bin:${PATH}:.
ENV SHELL=/bin/bash
ENV LANG=C.UTF-8 LC_ALL=C.UTF-8
ENV TZ Asia/Shanghai

RUN echo http://mirrors.aliyun.com/alpine/v3.16/main/ > /etc/apk/repositories && \
    echo http://mirrors.aliyun.com/alpine/v3.16/community/ >> /etc/apk/repositories && \
    apk add --no-cache bash ca-certificates java-cacerts && \
    rm -rf "$JAVA_HOME/lib/security/cacerts" && \
    ln -sT /etc/ssl/certs/java/cacerts "$JAVA_HOME/lib/security/cacerts" && \
    wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub && \
    wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.32-r0/glibc-2.32-r0.apk && \
    apk --no-cache add glibc-2.32-r0.apk  && \
    rm -rf glibc-2.32-r0.apk && \
    wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.32-r0/glibc-bin-2.32-r0.apk && \
    apk --no-cache add glibc-bin-2.32-r0.apk  && \
    rm -rf glibc-bin-2.32-r0.apk && \
    wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.32-r0/glibc-i18n-2.32-r0.apk && \
    apk --no-cache add glibc-i18n-2.32-r0.apk  && \
    rm -rf glibc-i18n-2.32-r0.apk && \
    /usr/glibc-compat/bin/localedef -i en_US -f UTF-8 en_US.UTF-8
[root@jason opt]# 

6、构建镜像 openjre-alpine:18 并测试

[root@jason ~]# docker build -f openjre-18-alpine.dockerfile -t harbor.demo/os/openjre-alpine:18 ./
... ... ... ... 此处省略若干行
Step 8/8 : RUN echo http://mirrors.aliyun.com/alpine/v3.16/main/ > /etc/apk/repositories &&     echo http://mirrors.aliyun.com/alpine/v3.16/community/ >> /etc/apk/repositories &&     apk add --no-cache bash ca-certificates java-cacerts &&     rm -rf "$JAVA_HOME/lib/security/cacerts" &&     ln -sT /etc/ssl/certs/java/cacerts "$JAVA_HOME/lib/security/cacerts" &&     wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub &&     wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.32-r0/glibc-2.32-r0.apk &&     apk --no-cache add glibc-2.32-r0.apk  &&     rm -rf glibc-2.32-r0.apk &&     wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.32-r0/glibc-bin-2.32-r0.apk &&     apk --no-cache add glibc-bin-2.32-r0.apk  &&     rm -rf glibc-bin-2.32-r0.apk &&     wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.32-r0/glibc-i18n-2.32-r0.apk &&     apk --no-cache add glibc-i18n-2.32-r0.apk  &&     rm -rf glibc-i18n-2.32-r0.apk &&     /usr/glibc-compat/bin/localedef -i en_US -f UTF-8 en_US.UTF-8
 ---> Running in 2ef227c81eff
fetch http://mirrors.aliyun.com/alpine/v3.16/main/x86_64/APKINDEX.tar.gz
fetch http://mirrors.aliyun.com/alpine/v3.16/community/x86_64/APKINDEX.tar.gz
(1/10) Installing ncurses-terminfo-base (6.3_p20220521-r0)
(2/10) Installing ncurses-libs (6.3_p20220521-r0)
(3/10) Installing readline (8.1.2-r0)
(4/10) Installing bash (5.1.16-r2)
Executing bash-5.1.16-r2.post-install
(5/10) Installing ca-certificates (20220614-r0)
(6/10) Installing libffi (3.4.2-r1)
(7/10) Installing p11-kit (0.24.1-r0)
(8/10) Installing libtasn1 (4.18.0-r0)
(9/10) Installing p11-kit-trust (0.24.1-r0)
(10/10) Installing java-cacerts (1.0-r1)
Executing busybox-1.35.0-r17.trigger
Executing ca-certificates-20220614-r0.trigger
OK: 10 MiB in 24 packages
Connecting to github.com (20.205.243.166:443)
Connecting to objects.githubusercontent.com (185.199.111.133:443)
saving to 'glibc-2.32-r0.apk'
glibc-2.32-r0.apk      2% |                                | 97492  0:00:44 ETA
glibc-2.32-r0.apk     67% |*********************           | 2931k  0:00:00 ETA
glibc-2.32-r0.apk     70% |**********************          | 3043k  0:00:01 ETA
glibc-2.32-r0.apk     85% |***************************     | 3721k  0:00:00 ETA
glibc-2.32-r0.apk     92% |*****************************   | 4004k  0:00:00 ETA
glibc-2.32-r0.apk    100% |********************************| 4331k  0:00:00 ETA
'glibc-2.32-r0.apk' saved
fetch http://mirrors.aliyun.com/alpine/v3.16/main/x86_64/APKINDEX.tar.gz
fetch http://mirrors.aliyun.com/alpine/v3.16/community/x86_64/APKINDEX.tar.gz
(1/1) Installing glibc (2.32-r0)
OK: 19 MiB in 25 packages
Connecting to github.com (20.205.243.166:443)
Connecting to objects.githubusercontent.com (185.199.110.133:443)
saving to 'glibc-bin-2.32-r0.apk'
glibc-bin-2.32-r0.ap  19% |******                          |  191k  0:00:04 ETA
glibc-bin-2.32-r0.ap 100% |********************************| 1001k  0:00:00 ETA
'glibc-bin-2.32-r0.apk' saved
fetch http://mirrors.aliyun.com/alpine/v3.16/main/x86_64/APKINDEX.tar.gz
fetch http://mirrors.aliyun.com/alpine/v3.16/community/x86_64/APKINDEX.tar.gz
(1/2) Installing libgcc (11.2.1_git20220219-r2)
(2/2) Installing glibc-bin (2.32-r0)
Executing glibc-bin-2.32-r0.trigger
/usr/glibc-compat/sbin/ldconfig: /usr/glibc-compat/lib/ld-linux-x86-64.so.2 is not a symbolic link

OK: 22 MiB in 27 packages
Connecting to github.com (20.205.243.166:443)
Connecting to objects.githubusercontent.com (185.199.109.133:443)
saving to 'glibc-i18n-2.32-r0.apk'
glibc-i18n-2.32-r0.a   0% |                                | 48335  0:02:38 ETA
glibc-i18n-2.32-r0.a  31% |*********                       | 2335k  0:00:04 ETA
glibc-i18n-2.32-r0.a  43% |**************                  | 3279k  0:00:03 ETA
glibc-i18n-2.32-r0.a  59% |*******************             | 4464k  0:00:02 ETA
glibc-i18n-2.32-r0.a 100% |********************************| 7489k  0:00:00 ETA
'glibc-i18n-2.32-r0.apk' saved
fetch http://mirrors.aliyun.com/alpine/v3.16/main/x86_64/APKINDEX.tar.gz
fetch http://mirrors.aliyun.com/alpine/v3.16/community/x86_64/APKINDEX.tar.gz
(1/1) Installing glibc-i18n (2.32-r0)
OK: 47 MiB in 28 packages
Removing intermediate container 2ef227c81eff
 ---> 9f2dcd199b37
Successfully built 9f2dcd199b37
Successfully tagged harbor.demo/os/openjre-alpine:18
[root@jason ~]# docker run -it --name=jre18-test harbor.demo/os/openjre-alpine:18 /bin/bash
bash-5.1# java -version
openjdk version "18.0.2.1" 2022-08-18
OpenJDK Runtime Environment (build 18.0.2.1+1-1)
OpenJDK 64-Bit Server VM (build 18.0.2.1+1-1, mixed mode)
bash-5.1# ldd /usr/java/jre/bin/java
        /lib64/ld-linux-x86-64.so.2 (0x7fa7914e7000)
        libz.so.1 => /lib/libz.so.1 (0x7fa7914c9000)
        libjli.so => /usr/java/jre/bin/../lib/libjli.so (0x7fa7914b8000)
        libpthread.so.0 => /lib64/ld-linux-x86-64.so.2 (0x7fa7914e7000)
        libdl.so.2 => /lib64/ld-linux-x86-64.so.2 (0x7fa7914e7000)
        libc.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7fa7914e7000)
Error relocating /usr/java/jre/bin/../lib/libjli.so: __strdup: symbol not found
Error relocating /usr/java/jre/bin/../lib/libjli.so: __rawmemchr: symbol not found
bash-5.1# exit
[root@jason ~]#
  • glibc 一开始使用 2.35 版本,构建的镜像运行java程序报错,改为2.32版本
  • glibc 的三个apk下载经常会失败,可以提前下载,构建镜像的时候复制、安装

wget github.com/sgerrand/al…
wget github.com/sgerrand/al…
wget github.com/sgerrand/al…

86179f4ead41700bf834f76d81d9435.png

7、镜像扫描 openjre-alpine:18

1664538674027.png

8、上述测试过程中操作镜像、容器可能使用到的几个命令

[root@jason ~]# docker ps -a
[root@jason ~]# docker images
[root@jason ~]# docker rm xxxxxx
[root@jason ~]# docker rmi xxxxx
[root@jason ~]# docker start -i xxxxx
[root@jason ~]# docker history openjre-alpine:18 --no-trunc

9、在Springboot项目下创建demo001.dockerfile

FROM harbor.demo/os/openjre-alpine:18

ADD target/*.jar app.jar
EXPOSE 8080
ENV JAVA_OPTION='-server -Dfile.encoding=UTF-8 -Xmx512m -Xms512m -Xmn256m -XX:+UseParallelGC -XX:+HeapDumpOnOutOfMemoryError -XX:+DisableExplicitGC'
CMD java ${JAVA_OPTION} -jar app.jar

10、构建镜像 demo001:

[root@jason ~]# docker build -f demo001.dockerfile -t harbor.demo/samjavademo/demo001 ./
Sending build context to Docker daemon  18.25MB

Step 1/5 : FROM harbor.demo/os/openjre-alpine:18
 ---> 47f8aab03925
Step 2/5 : ADD target/*.jar app.jar
 ---> ca5b450eb256
Step 3/5 : EXPOSE 8080
 ---> Running in 25f4aeb42244
Removing intermediate container 25f4aeb42244
 ---> 81b9df9353ef
Step 4/5 : ENV JAVA_OPTION='-server -Dfile.encoding=UTF-8 -Xmx512m -Xms512m -Xmn256m -XX:+UseParallelGC -Xlog:gc:/tmp/demo001.gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:+DisableExplicitGC'
 ---> Running in 310e1e73bed4
Removing intermediate container 310e1e73bed4
 ---> 4202e65ace2b
Step 5/5 : ENTRYPOINT ["/bin/bash", "-c", "java ${JAVA_OPTION} -jar /opt/app.jar"]
 ---> Running in adbba741334e
Removing intermediate container adbba741334e
 ---> b2d9a332f7d9
Successfully built b2d9a332f7d9
Successfully tagged harbor.demo/samjavademo/demo001:latest
[root@jason ~]# docker images
REPOSITORY                        TAG       IMAGE ID       CREATED          SIZE
harbor.demo/samjavademo/demo001   latest    b2d9a332f7d9   27 minutes ago   160MB
[root@jason ~]# docker run -d --name demo001 -p 8888:8080 harbor.demo/samjavademo/demo001
166b2239499ea87ecf5495c09c5163c54fdeed46c6371271222c1827d187101c
[root@jason ~]# docker ps
166b2239499e   harbor.demo/samjavademo/demo001   "/bin/bash -c 'java …"   2 seconds ago   Up 1 second   0.0.0.0:8888->8080/tcp   demo001
[root@jason ~]# 
  • 启动成功,可以通过浏览器测试demo001中的接口

参考

祝大家国庆快乐~~~ 祝祖国繁荣昌盛~~~


  • 通过操作实践认识docker、kubernetes(k8s),积累多了自然就理解了
  • 把理解的知识分享出来,自造福田,自得福缘
  • 追求简单,容易使人理解,知识的上下文也是知识的一部分,例如版本,时间等
  • 欢迎留言交流,也可以提出问题,一般在周末回复和完善文档
  • Jason@vip.qq.com 2022-9-30