When building my Spring-boot image using Maven I now do this inside the Dockerfile. Maven will download all dependencies and then compile my files. This takes quite some time.
How can I specify that the build process via docker-compose (Dockerfile) re-uses my "Windows10 Home" Maven repository? So, the number of (new) downloads is minimal. My dev context: I use the Docker quickstart terminal, so using a docker-machine.
The is is a part of my docker-compose.yml file:
version: '3'
services:
spring-boot-app:
image: spring-boot-image
build:
context: ./
dockerfile: Dockerfile
depends_on:
- mysql-docker-container
ports:
- 8087:8080
volumes:
- $HOME/.m2/repository:/root/.m2/repository
- /data/spring-boot-app
My Dockerfile is:
FROM java:8
FROM maven:alpine
WORKDIR /app
COPY . /app
RUN mvn -v
RUN mvn clean install -DskipTests
EXPOSE 8080
LABEL maintainer=“[email protected]”
ADD ./target/spring-boot-example-0.0.1-SNAPSHOT.jar /developments/
ENTRYPOINT ["java","-jar","/developments/spring-boot-example-0.0.1-SNAPSHOT.jar"]
This means that Docker calls Maven commands from within a Docker container. While most people think Docker as a deployment format for the application itself, in reality, Docker can be used for the build process as well (i.e. tooling via Docker) The approach has several advantages.
Even though we started this article with Maven plugins for Docker, I hope that you can see that multi-stage builds where Docker is controlling Maven (and not the other way around) are the future: They make our application resilient against Docker API changes It makes the build self-contained. No developer tools are needed on the build machine
Spotify Maven Docker Plugin. The Spotify Maven plugin abstracts some docker concepts away and provides a more traditional maven like interface for configuring a docker build. However, it still utilizing a docker agent to perform the actual build.
While most people think Docker as a deployment format for the application itself, in reality, Docker can be used for the build process as well (i.e. tooling via Docker) The approach has several advantages. First of all, it makes the combination, future proof as the API of the docker daemon is no longer relevant to the build process.
@Jack Gore - thank you very much for pointing me the way. I had seen the post, but there was not a definitive answer yet. After diving in all seperate answers, the info provided me both an answer to the symptom as well with insights how to solve similar questions.
ANSWER: Via the Dockerfile you can build the final images via 1 or more subsequent image layers. To prevent the step from re-downloading the dependencies each time, you can make an image layer for the 'downloading the world' of dependencies. Re-downloading will only be done when a dependency changes in the pom.xml file.
To do so, you split the Dockerfile in 2 build steps: first copy the pom.xml file and build it. That will create an image layer with all dependencies. As a second step you build the application.
FROM java:8
FROM maven:alpine
# image layer
WORKDIR /app
ADD pom.xml /app
RUN mvn verify clean --fail-never
# Image layer: with the application
COPY . /app
RUN mvn -v
RUN mvn clean install -DskipTests
EXPOSE 8080
ADD ./target/your.jar /developments/
ENTRYPOINT ["java","-jar","/developments/your.jar"]
Then you get the following build scenario's:
The impact of seperating image layers is shown via a number of very short videos.
The disadvantage of this way of building is of course that the final (production) image contains more than the appication. Not only the JAR is in it, but also a number of dependencies.
How to solve this iamge being far too big:
For my case this is the best option possible. You automate the process AND keep the image size low.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With