1、起因 eclipse-temurin:18-jre-alpine 镜像有安全漏洞
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…
7、镜像扫描 openjre-alpine:18
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