I'm exploring the initial steps of containerising a Tomcat-based Java project using Docker. With IntelliJ as my preferred IDE, I have successfully:
So in terms of the basic development cycle, I'm up and running.
But when I eventually come to external deployment (and even at some point during the development process), I will need to add libraries and resources and generate a truly self-contained container: in other words, I will need to go from the simple deployment that the IntelliJ plugin is currently doing of an "image with mount points" to having a full-fledged Dockerfile with all the relevant configuration specified, including my mounts effectively being translated into instructions to copy in the relevant content.
Now my question: how do people generally achieve this? Is there tooling built into IntelliJ that will assist with this? In the container deployment configuration settings in IntelliJ (where the mount points, base image etc are specified), there doesn't seem to be an option to configure resources to copy, for example (or an option to "copy into standalone container rather than mount from host FS"). Am I missing a tool/option somewhere, or is the scripting of the Docker file essentially a manual process? Or am I just barking up the wrong tree with my whole approach? I'd appreciate any advice on the process that people generally use for this!
I think, Jib would provide, what you need. It also provides plugins for both Maven and Gradle, and the respective plugin can be triggered in IntelliJ via Run/Debug Configuration (see the example at the very bottom).
What is Jib?
Jib builds optimized Docker and OCI images for your Java applications without a Docker daemon - and without deep mastery of Docker best-practices. It is available as plugins for Maven and Gradle and as a Java library.
What does Jib do?
Jib handles all steps of packaging your application into a container image. You don't need to know best practices for creating Dockerfiles or have Docker installed. Jib organizes your application into distinct layers; dependencies, resources, and classes; and utilizes Docker image layer caching to keep builds fast by only rebuilding changes. Jib's layer organization and small base image keeps overall image size small, which improves performance and portability.
You can check the documentation. It contains a lot of information about different kind of configuration options regarding the creation and deploying a Docker image. Where you can also simply make use of environment variables.
For projects with Maven: https://github.com/GoogleContainerTools/jib/tree/master/jib-maven-plugin
For projects with Gradle: https://github.com/GoogleContainerTools/jib/tree/master/jib-gradle-plugin
Regarding your question, check this part for example: adding Arbitrary Files to the Image
In the container deployment configuration settings in IntelliJ (where the mount points, base image etc are specified), there doesn't seem to be an option to configure resources to copy, for example (or an option to "copy into standalone container rather than mount from host FS").
For demonstration purposes, I've created a simple project with Maven, where I also used the base image tomcat:9.0.36-jdk8-openjdk
, which is also optional by the way - see Jib WAR Projects:
Servlet:
@WebServlet(urlPatterns = {"/hello-world"})
public class HelloWorld extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("Hello World");
}
}
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>mvn-jib-example</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<failOnMissingWebXml>false</failOnMissingWebXml>
</properties>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>servlet-hello-world</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>2.5.0</version>
<configuration>
<allowInsecureRegistries>true</allowInsecureRegistries>
<from>
<image>tomcat:9.0.36-jdk8-openjdk</image>
</from>
<to>
<image>registry.localhost/hello-world</image>
<auth>
<username>registry_username</username>
<password>registry_password</password>
</auth>
<tags>
<tag>latest</tag>
</tags>
</to>
<container>
<appRoot>/usr/local/tomcat/webapps/ROOT</appRoot>
</container>
<extraDirectories>
<paths>
<path>
<from>./src/main/resources/extra-stuff</from>
<into>/path/in/docker/image/extra-stuff</into>
</path>
<path>
<from>/absolute/path/to/other/stuff</from>
<into>/path/in/docker/image/other-stuff</into>
</path>
</paths>
</extraDirectories>
</configuration>
</plugin>
</plugins>
</build>
</project>
mvn clean package jib:dockerBuild
docker image ls
docker run --rm -p 8082:8080 registry.localhost/hello-world:latest
Result:
To deploy the image to an external docker registry, you can check the sections below:
Last but not least, since you are working with IntellIJ IDEA, you can simply create a RUN/Debug configuration to automate the image creation and deployment via button button, e.g. one configuration for building the image, one for deploying it to localhost and one for deploying to extern registry and so on.
Here an example for maven (see):
The project that I am doing right now is using Spring-boot which actually has embedded Tomcat inside. And I use Docker Gradle plugin(https://plugins.gradle.org/plugin/com.bmuschko.docker-spring-boot-application) to build and push Docker image to registry which can be docker hub or AWS ECR. The combination is playing well with IntelliJ as it is Gradle task anyway.
Because it is Spring-boot, the plugin can build image based on any basic JRE image(I use https://hub.docker.com/_/adoptopenjdk) with minimum configuration. Do not need to write your own Dockerfile at all.
docker {
def registryHost = 'xxx.dkr.ecr.us-west-2.amazonaws.com'
springBootApplication {
baseImage = "${registryHost}/caelus:springboot-jdk14-openj9"
images = ["${registryHost}/caelus:app"]
ports = [8080,8081]
jvmArgs =['-Djdk.httpclient.allowRestrictedHeaders=content-length']
}
}
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