Search code examples
spring-bootdockerwar

Packaging war file into docker image in multiple layers


I'm trying to put a Spring Boot application with war packaging into a docker image. The simplest way to get this can be using the following Dockerfile:

FROM adoptopenjdk/openjdk8:alpine-slim
VOLUME /tmp
COPY target/demo.war app.war
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.war"]

Following this approach I'm creating a big layer every time I change the project's source code. An alternative to this is to split the war into different docker layers as it is explained in this post: https://spring.io/blog/2018/11/08/spring-boot-in-a-container#a-better-dockerfile

However, I'm afraid this is only possible with jar packaging and not with war. Am I right?

Thanks in advance.


Solution

  • This is the way I get a multilayer docker image with a war applicaton.

    First open the war file to find out which folders have to be copied to the image:

    jar -xf youapp.war
    

    In my project the war file is composed of these folders:

    /WEB-INF
    /META-INF
    /resources
    /org
    

    Based on this, I created the following Dockerfile:

    FROM openjdk:8-jdk-alpine AS builder
    WORKDIR target/dependency
    ARG APPWAR=target/*.war
    COPY ${APPWAR} app.war
    RUN jar -xf ./app.war
    RUN mv WEB-INF/lib-provided lib-provided
    RUN mv WEB-INF/lib lib
    
    FROM openjdk:8-jre-alpine
    VOLUME /tmp
    ARG DEPENDENCY=target/dependency
    COPY --from=builder ${DEPENDENCY}/lib /app/WEB-INF/lib
    COPY --from=builder ${DEPENDENCY}/lib-provided /app/WEB-INF/lib-provided
    COPY --from=builder ${DEPENDENCY}/org /app/org
    COPY --from=builder ${DEPENDENCY}/resources /app/resources
    COPY --from=builder ${DEPENDENCY}/META-INF /app/META-INF
    COPY --from=builder ${DEPENDENCY}/WEB-INF /app/WEB-INF
    
    ENTRYPOINT ["java","-cp","/app/WEB-INF/classes:/app/WEB-INF/lib/*:/app/WEB-INF/lib-provided/*","com.company.project.Application"]
    

    I hope it is useful.