Build Java Gradle project within a Docker container? - gradle

We have a Java project built with Gradle, and it requires Java 8 etc. Developers have different Java versions on their machines (different projects, IDEA has always been picky about Open JDK, but we use it to run our apps) and we would like to easily be able to build with the correct Java version.
The idea is to use Docker for the task, i.e. start a docker container with the correct Java version and use it for the build (compile, test, assemble etc.).
Is this a good idea? How would I go about it? For example, do I tell Gradle to start the container, and tell it to use its javac? Or do I start the container, mount a volume with the project code, and build using Gradle in that container? This would have the disadvantage that people need to start a container first, but I guess it could be scripted.
Does anybody do something like this?

If the goal is to standardise the build, then you should use a build automatisation software:
Jenkins
TeamCity
Bamboo
...
Also, if your gradle project must be run with a specific version, you may enforce it: How do I tell Gradle to use specific JDK version?
I wouldn't use docker for that.

I used a gradle container to build my springboot java project. You can do something similar.
Dockerfile
FROM gradle:jdk8
COPY . /home/gradle/project
WORKDIR /home/gradle/project
ENTRYPOINT ["gradle"]
CMD ["bootRepackage"]
You can also find information about different gradle containers at https://hub.docker.com/_/gradle/ which shows how you can mount your host directory as volume to the container and build.

Related

Springboot 2.3 with Docker. I want to build image for a specific app when I have multiple springboot applications in same repository

Building a springboot application version 2.3. I want to build a docker image with the cloud native build packs. I have 2 springboot applications sitting inside my repository, say App A and App B. Usually, I do mvn install, pick up the jars and start them individually. Run jar "a" for aapp a and jar "b" for app b. Now, How do I tell the build pack on which jar I want to build my docker image on.
Building on a stack of other answers, you can use the advanced reactor options to target a single module in the reactor and build the image just for that module.
A command like
mvn -pl <module-name> -am spring-boot:build-image
will likely give you what you're looking for.
Whichever platform you're using, you should be able to point the build toward your relevant subdirectory. For instance, if you're using pack, you can use pack build -p <repo dir>/<app A dir>. Depending on which Java buildpack you're using, it should run Maven for you and set up the resulting JAR to launch when the app image is started.

Run Gradle build offline in a docker container

I am trying to run gradle build test on my Kotlin app in a docker container which does not have access to the internet hence I copy Gradle in Dockerfile
ADD https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip /usr/bin/gradle.zip
but the problem is that my app has got the following plugin in the app.
plugins {
kotlin("jvm") version "1.3.40"
}
so how would I go about to add these plugins to my container before running gradle offline in container?
You should put all your GRADLE_USER_HOME into the container as well. It contains Gradle wrapper distributions, plugins and dependencies. By default, GRADLE_USER_HOME is ~/.gradle directory.
I suppose, what you can do is run your full build once in a fresh container with Internets access and then just copy /root/.gradle (or whatever your user is configured to be inside the container) from it. Or just use that existing container as a base for your build image.

How to manage custom common libraries built in maven for my Application in kubernetes

I need to understand how to deal with common libraries that i have created which my Application depends upon. When i create jar for this app using maven it creates a package. But how do we maintain or configure other common libraries which are listed in pom.xml of this application?
should we have maven also as an image in the docker file?
Please explain in detail.
My current progress is explained below: I have an Application A which has other dependencies like B and C libraries which i have specified in pom.xml. When i run application A in my local system it uses local repository that i have configured in user settings for maven. SO it works fine.
So how do we maintain this in kubenetes.
The images that you use to build the containers that run on Kubernetes should contain everything that's needed to run the application.
When you create the JAR file for your application, this JAR should contain the dependencies. There are different ways to achieve this, using both Maven or Gradle. This is an example using Maven and its Apache Maven Assembly Plugin. This is another good user guide on how to achieve it.
Then, you need to create a container image that can run that JAR file, something like
FROM openjdk:8-jdk-alpine
EXPOSE 8080
WORKDIR /opt/app
CMD ["java", "-jar", "app.jar"]
COPY build/libs/app.jar /opt/app
Once this container image is published on a registry, whenever Kubernetes needs to schedule and create a container, it will just use that image: there is no need to re-compile the application and its dependencies.

Does a Maven packaging type `docker` exists?

I am trying to figure out how to build Docker images as part of the Maven build process. Basically, I want to create a Maven project which builds a Docker image. I think this makes sense.
But what should the packaging type look like? It's obviously not jar, war or maven-plugin. I tried with docker but that does not exist.
Should I just go for pom or is there a way to configure custom package types?
Having it at pom feels wrong to me, as we are producing an output - a Docker image - which is usually not the case in regular pom types (parent pom, bom, ...).
Wow that's ambitious! When you say you want to build a docker image using Maven, I'm assuming you won't be using docker build or other docker commands to generate the final image. Docker images are TAR files so you can use the Maven Assembly plugin to generate the desired tar-file image.
In this case, your project's "type" would be "pom" so that the project itself generates a POM file containing the information about how it was built (such as name and version number). The Assembly plugin will also generate and attach the corresponding TAR file so that when you use mvn deploy or other commands which reference the package, the associated TAR file will be included.
If you are using docker commands to build the images then you are probably going to have to write a custom Maven extension -- depending on what you want to happen when you run mvn deploy. It really depends on your ultimate goal but if you are using this within the confines of Docker then you might do better with a plugin like dockerfile-maven which will allow your build to drive the docker workflow of docker build and/or docker push.
Spotify has created a dockerfile-maven-plugin that allows you to build and publish Docker images with maven. There is an example and lots of other useful info on the project page.
Of today, there's a Maven docker plugin that enables <packaging>docker</packaging>, here:
https://github.com/fabric8io/docker-maven-plugin
Doc here:
https://dmp.fabric8.io/
But take care to specify <extensions>true</extensions>!

maven plugin for docker (e.g. to run with needed db)

Making an image for maven project should be straightforward, as maven know how to build (and can know how to run)
How to build docker image and run it with maven?
Let's say the app also needs MongoDB, that I can run as docker run -p 27017:27017 mongo. Is it possible also to specify with some maven plugin?
The maven plugin created by fabric8 allows you to do this:
the plugin and its documentation is available on github: https://github.com/fabric8io/docker-maven-plugin
The samples include for example https://github.com/fabric8io/docker-maven-plugin/blob/master/samples/data-jolokia-demo/pom.xml (which seems to be similar to what you plan).
An alternative could be using Docker-compose and some scripts outside maven, once the images are created.

Resources