Skip to content

1.Dockerfile文件

dockerfile
FROM alpine:3.17
CMD ["/bin/sh"]
MAINTAINER GLJ
ENV TIME_ZONE="Asia/Shanghai"
ENV ALPINE_GLIBC_PACKAGE_VERSION="2.34-r0"

# Install glibc
COPY locale.md glibc-$ALPINE_GLIBC_PACKAGE_VERSION.apk glibc-bin-$ALPINE_GLIBC_PACKAGE_VERSION.apk glibc-i18n-$ALPINE_GLIBC_PACKAGE_VERSION.apk ./
COPY sgerrand.rsa.pub /etc/apk/keys/sgerrand.rsa.pub
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories \
    && apk add --no-cache ca-certificates libstdc++ fontconfig tzdata \
    && apk add --update ttf-dejavu \
    && fc-cache --force \
    && cp /usr/share/zoneinfo/$TIME_ZONE /etc/localtime \
    && echo $TIME_ZONE > /etc/timezone \
    && apk del tzdata \
    && mv /etc/nsswitch.conf /etc/nsswitch.conf.bak \
    && apk add --no-cache --force-overwrite glibc-$ALPINE_GLIBC_PACKAGE_VERSION.apk glibc-bin-$ALPINE_GLIBC_PACKAGE_VERSION.apk glibc-i18n-$ALPINE_GLIBC_PACKAGE_VERSION.apk \
    && mv /etc/nsswitch.conf.bak /etc/nsswitch.conf \
    && cat locale.md | tr -d '\r' | xargs -i /usr/glibc-compat/bin/localedef -i {} -f UTF-8 {}.UTF-8 \
    && rm -f glibc-$ALPINE_GLIBC_PACKAGE_VERSION.apk glibc-bin-$ALPINE_GLIBC_PACKAGE_VERSION.apk glibc-i18n-$ALPINE_GLIBC_PACKAGE_VERSION.apk locale.md \
    && rm -rf /var/cache/apk/* \
    && addgroup -g 2888 apps \
    && adduser -u 2888 -G apps -h /home/apps -D apps

# Support Chinese
ENV LANG=zh_CN.UTF-8
ENV LANGUAGE=zh_CN.UTF-8

# Install JDK1.8
ADD jdk-8u341-linux-x64.tar.gz /usr/local/jdk
ENV JAVA_HOME=/usr/local/jdk/jdk1.8.0_341
ENV JRE_HOME=$JAVA_HOME/jre
ENV CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib
ENV PATH=$JAVA_HOME/bin:$PATH
FROM alpine:3.17
CMD ["/bin/sh"]
MAINTAINER GLJ
ENV TIME_ZONE="Asia/Shanghai"
ENV ALPINE_GLIBC_PACKAGE_VERSION="2.34-r0"

# Install glibc
COPY locale.md glibc-$ALPINE_GLIBC_PACKAGE_VERSION.apk glibc-bin-$ALPINE_GLIBC_PACKAGE_VERSION.apk glibc-i18n-$ALPINE_GLIBC_PACKAGE_VERSION.apk ./
COPY sgerrand.rsa.pub /etc/apk/keys/sgerrand.rsa.pub
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories \
    && apk add --no-cache ca-certificates libstdc++ fontconfig tzdata \
    && apk add --update ttf-dejavu \
    && fc-cache --force \
    && cp /usr/share/zoneinfo/$TIME_ZONE /etc/localtime \
    && echo $TIME_ZONE > /etc/timezone \
    && apk del tzdata \
    && mv /etc/nsswitch.conf /etc/nsswitch.conf.bak \
    && apk add --no-cache --force-overwrite glibc-$ALPINE_GLIBC_PACKAGE_VERSION.apk glibc-bin-$ALPINE_GLIBC_PACKAGE_VERSION.apk glibc-i18n-$ALPINE_GLIBC_PACKAGE_VERSION.apk \
    && mv /etc/nsswitch.conf.bak /etc/nsswitch.conf \
    && cat locale.md | tr -d '\r' | xargs -i /usr/glibc-compat/bin/localedef -i {} -f UTF-8 {}.UTF-8 \
    && rm -f glibc-$ALPINE_GLIBC_PACKAGE_VERSION.apk glibc-bin-$ALPINE_GLIBC_PACKAGE_VERSION.apk glibc-i18n-$ALPINE_GLIBC_PACKAGE_VERSION.apk locale.md \
    && rm -rf /var/cache/apk/* \
    && addgroup -g 2888 apps \
    && adduser -u 2888 -G apps -h /home/apps -D apps

# Support Chinese
ENV LANG=zh_CN.UTF-8
ENV LANGUAGE=zh_CN.UTF-8

# Install JDK1.8
ADD jdk-8u341-linux-x64.tar.gz /usr/local/jdk
ENV JAVA_HOME=/usr/local/jdk/jdk1.8.0_341
ENV JRE_HOME=$JAVA_HOME/jre
ENV CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib
ENV PATH=$JAVA_HOME/bin:$PATH
  • 构建镜像
bash
docker build -t base-jdk8:v1
docker build -t base-jdk8:v1

2.第二种方式

dockerfile
# 基于alpine-glibc:alpine-3.17_glibc-2.34构建
FROM frolvlad/alpine-glibc:alpine-3.17_glibc-2.34
MAINTAINER GLJ

# Install JDK1.8
ADD jdk-8u341-linux-x64.tar.gz /usr/local/jdk
ENV JAVA_HOME=/usr/local/jdk/jdk1.8.0_341
ENV JRE_HOME ${JAVA_HOME}/jre
ENV CLASSPATH .:${JAVA_HOME}/lib:${JRE_HOME}/lib
ENV PATH=$JAVA_HOME/bin:$PATH
ENV TIME_ZONE="Asia/Shanghai" 

# 安装 JRE
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories \
    && apk add --no-cache libstdc++ fontconfig tzdata \
    && apk add --update ttf-dejavu \
    && fc-cache --force \
    && cp /usr/share/zoneinfo/$TIME_ZONE /etc/localtime \
    && echo $TIME_ZONE > /etc/timezone \
    && apk del tzdata \
    && rm -rf /var/cache/apk/* \
    && addgroup -g 2888 apps \
    && adduser -u 2888 -G apps -h /home/apps -D apps
# 基于alpine-glibc:alpine-3.17_glibc-2.34构建
FROM frolvlad/alpine-glibc:alpine-3.17_glibc-2.34
MAINTAINER GLJ

# Install JDK1.8
ADD jdk-8u341-linux-x64.tar.gz /usr/local/jdk
ENV JAVA_HOME=/usr/local/jdk/jdk1.8.0_341
ENV JRE_HOME ${JAVA_HOME}/jre
ENV CLASSPATH .:${JAVA_HOME}/lib:${JRE_HOME}/lib
ENV PATH=$JAVA_HOME/bin:$PATH
ENV TIME_ZONE="Asia/Shanghai" 

# 安装 JRE
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories \
    && apk add --no-cache libstdc++ fontconfig tzdata \
    && apk add --update ttf-dejavu \
    && fc-cache --force \
    && cp /usr/share/zoneinfo/$TIME_ZONE /etc/localtime \
    && echo $TIME_ZONE > /etc/timezone \
    && apk del tzdata \
    && rm -rf /var/cache/apk/* \
    && addgroup -g 2888 apps \
    && adduser -u 2888 -G apps -h /home/apps -D apps

3.镜像漏扫验证

使用第三方,一定的进行镜像扫描

4.java案例

dockerfile
FROM base-jdk8:v1
USER gzapps
COPY --chown=apps:apps app.jar /home/apps/app.jar

# env for application
ENV PORT=""
ENV JAVA_OPTS=""
ENV AGENT_ARGS=""

EXPOSE $PORT
WORKDIR /home/gzapps

ENTRYPOINT ["/bin/bash","-c","java ${AGENT_ARGS} ${JAVA_OPTS} -jar app.jar"]
#ENTRYPOINT exec java -Djava.security.egd=file:/dev/./urandom -jar -Xms512m -Xmx512m -Xmn200M app.jar > app.jar.log
FROM base-jdk8:v1
USER gzapps
COPY --chown=apps:apps app.jar /home/apps/app.jar

# env for application
ENV PORT=""
ENV JAVA_OPTS=""
ENV AGENT_ARGS=""

EXPOSE $PORT
WORKDIR /home/gzapps

ENTRYPOINT ["/bin/bash","-c","java ${AGENT_ARGS} ${JAVA_OPTS} -jar app.jar"]
#ENTRYPOINT exec java -Djava.security.egd=file:/dev/./urandom -jar -Xms512m -Xmx512m -Xmn200M app.jar > app.jar.log

5.使用jlink构建自定义 JRE 镜像

以用来打包Java应用的基础镜像有几种,包括:

  • JDK Alpine基础镜像:这些镜像体积较小,但不适合所有应用,因此可能会面临一些库的兼容性问题。
  • JDK Slim基础镜像:这些镜像基于Debian或Ubuntu,相较于完整的JDK镜像来说体积较小,但仍然比较大。
  • JDK完整基础镜像:这些镜像体积较大,包含运行应用所需的所有模块和依赖项。

❌ 注意

不能使用JRE镜像而使用JDK镜像,从Java 11开始,JRE不再可用

为了对比大小,我们采用openjdk:17-jdk-slim,eclipse-temurin:17-jdk-alpine

yaml
FROM openjdk:17-jdk-slim

# 设置容器中的工作目录
WORKDIR /app

# 创建用户
RUN addgroup --system spring && adduser --system spring --ingroup spring

# 切换到用户
USER spring:spring

COPY target/*.jar app.jar

EXPOSE 8080

CMD ["java", "-jar", "app.jar"]
FROM openjdk:17-jdk-slim

# 设置容器中的工作目录
WORKDIR /app

# 创建用户
RUN addgroup --system spring && adduser --system spring --ingroup spring

# 切换到用户
USER spring:spring

COPY target/*.jar app.jar

EXPOSE 8080

CMD ["java", "-jar", "app.jar"]
yaml
FROM eclipse-temurin:17-jdk-alpine

ARG APPLICATION_USER=spring
# 创建一个用户来运行应用,不以root用户运行
RUN addgroup --system $APPLICATION_USER && adduser --system $APPLICATION_USER --ingroup $APPLICATION_USER

# 创建应用目录
RUN mkdir /app && chown -R $APPLICATION_USER /app

# 设置运行应用的用户
USER $APPLICATION_USER

# 将jar文件复制到容器中
COPY --chown=$APPLICATION_USER:$APPLICATION_USER target/*.jar /app/app.jar

# 设置工作目录
WORKDIR /app

# 暴露端口
EXPOSE 8080

# 运行应用
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
FROM eclipse-temurin:17-jdk-alpine

ARG APPLICATION_USER=spring
# 创建一个用户来运行应用,不以root用户运行
RUN addgroup --system $APPLICATION_USER && adduser --system $APPLICATION_USER --ingroup $APPLICATION_USER

# 创建应用目录
RUN mkdir /app && chown -R $APPLICATION_USER /app

# 设置运行应用的用户
USER $APPLICATION_USER

# 将jar文件复制到容器中
COPY --chown=$APPLICATION_USER:$APPLICATION_USER target/*.jar /app/app.jar

# 设置工作目录
WORKDIR /app

# 暴露端口
EXPOSE 8080

# 运行应用
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
  • 完整案例
yaml
# 第一阶段,构建自定义 JRE
FROM eclipse-temurin:17-jdk-alpine AS jre-builder

RUN mkdir /opt/app
COPY . /opt/app

WORKDIR /opt/app

ENV MAVEN_VERSION 3.5.4
ENV MAVEN_HOME /usr/lib/mvn
ENV PATH $MAVEN_HOME/bin:$PATH

RUN apk update && \
    apk add --no-cache tar binutils

RUN wget http://archive.apache.org/dist/maven/maven-3/$MAVEN_VERSION/binaries/apache-maven-$MAVEN_VERSION-bin.tar.gz && \
  tar -zxvf apache-maven-$MAVEN_VERSION-bin.tar.gz && \
  rm apache-maven-$MAVEN_VERSION-bin.tar.gz && \
  mv apache-maven-$MAVEN_VERSION /usr/lib/mvn

RUN mvn package -DskipTests
RUN jar xvf target/spring-error-handling-rfc-9457-0.0.1-SNAPSHOT.jar
RUN jdeps --ignore-missing-deps -q  \
    --recursive  \
    --multi-release 17  \
    --print-module-deps  \
    --class-path 'BOOT-INF/lib/*'  \
    target/spring-error-handling-rfc-9457-0.0.1-SNAPSHOT.jar > modules.txt

# 构建小型 JRE 镜像,--add-modules ALL-MODULE-PATH
RUN $JAVA_HOME/bin/jlink \
         --verbose \
         --add-modules $(cat modules.txt) \
         --strip-debug \
         --no-man-pages \
         --no-header-files \
         --compress=2 \
         --output /optimized-jdk-17

# 第二阶段,使用自定义 JRE 并构建应用镜像
FROM alpine:latest
ENV JAVA_HOME=/opt/jdk/jdk-17
ENV PATH="${JAVA_HOME}/bin:${PATH}"

# 从基础镜像复制 JRE
COPY --from=jre-builder /optimized-jdk-17 $JAVA_HOME

# 添加应用用户
ARG APPLICATION_USER=spring

# 创建用户以运行应用程序,不以 root 身份运行
RUN addgroup --system $APPLICATION_USER &&  adduser --system $APPLICATION_USER --ingroup $APPLICATION_USER

# 创建应用程序目录
RUN mkdir /app && chown -R $APPLICATION_USER /app

COPY --chown=$APPLICATION_USER:$APPLICATION_USER target/*.jar /app/app.jar

WORKDIR /app

USER $APPLICATION_USER

EXPOSE 8080
ENTRYPOINT [ "java", "-jar", "/app/app.jar" ]
# 第一阶段,构建自定义 JRE
FROM eclipse-temurin:17-jdk-alpine AS jre-builder

RUN mkdir /opt/app
COPY . /opt/app

WORKDIR /opt/app

ENV MAVEN_VERSION 3.5.4
ENV MAVEN_HOME /usr/lib/mvn
ENV PATH $MAVEN_HOME/bin:$PATH

RUN apk update && \
    apk add --no-cache tar binutils

RUN wget http://archive.apache.org/dist/maven/maven-3/$MAVEN_VERSION/binaries/apache-maven-$MAVEN_VERSION-bin.tar.gz && \
  tar -zxvf apache-maven-$MAVEN_VERSION-bin.tar.gz && \
  rm apache-maven-$MAVEN_VERSION-bin.tar.gz && \
  mv apache-maven-$MAVEN_VERSION /usr/lib/mvn

RUN mvn package -DskipTests
RUN jar xvf target/spring-error-handling-rfc-9457-0.0.1-SNAPSHOT.jar
RUN jdeps --ignore-missing-deps -q  \
    --recursive  \
    --multi-release 17  \
    --print-module-deps  \
    --class-path 'BOOT-INF/lib/*'  \
    target/spring-error-handling-rfc-9457-0.0.1-SNAPSHOT.jar > modules.txt

# 构建小型 JRE 镜像,--add-modules ALL-MODULE-PATH
RUN $JAVA_HOME/bin/jlink \
         --verbose \
         --add-modules $(cat modules.txt) \
         --strip-debug \
         --no-man-pages \
         --no-header-files \
         --compress=2 \
         --output /optimized-jdk-17

# 第二阶段,使用自定义 JRE 并构建应用镜像
FROM alpine:latest
ENV JAVA_HOME=/opt/jdk/jdk-17
ENV PATH="${JAVA_HOME}/bin:${PATH}"

# 从基础镜像复制 JRE
COPY --from=jre-builder /optimized-jdk-17 $JAVA_HOME

# 添加应用用户
ARG APPLICATION_USER=spring

# 创建用户以运行应用程序,不以 root 身份运行
RUN addgroup --system $APPLICATION_USER &&  adduser --system $APPLICATION_USER --ingroup $APPLICATION_USER

# 创建应用程序目录
RUN mkdir /app && chown -R $APPLICATION_USER /app

COPY --chown=$APPLICATION_USER:$APPLICATION_USER target/*.jar /app/app.jar

WORKDIR /app

USER $APPLICATION_USER

EXPOSE 8080
ENTRYPOINT [ "java", "-jar", "/app/app.jar" ]