Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Option to auto-generate Dockerfile and other deployment tooling in IntelliJ?

I'm exploring the initial steps of containerising a Tomcat-based Java project using Docker. With IntelliJ as my preferred IDE, I have successfully:

  • written a proof-of-concept Servlet;
  • set up a build artefact to create the resulting WAR;
  • with the IntelliJ Docker plugin and one of the official Tomcat Docker images, set up a container configuration that includes the WAR contents as one of its mount points;
  • deployed the container to Docker locally through IntelliJ and confirmed that I can successfully hit the Servlet through my local browser.

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!

like image 563
Neil Coffey Avatar asked Sep 16 '25 20:09

Neil Coffey


2 Answers

Jib by Google

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.

Configuration

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

    • Build your image
    • Build to Docker daemon
    • Build an image tarball
  • For projects with Gradle: https://github.com/GoogleContainerTools/jib/tree/master/jib-gradle-plugin

    • Same options as for Maven

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").

Demo

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>
  • Executing the following goals will create the docker image on the fly:
mvn clean package jib:dockerBuild
  • Confirm that the image was created:
docker image ls
  • Starting a container from the image
docker run --rm -p 8082:8080 registry.localhost/hello-world:latest

Result:

Hello World from Tomcat docker container

Deployment

To deploy the image to an external docker registry, you can check the sections below:

  • Authentication Methods
  • Using Specific Credentials

IDE

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): Maven and Jib with IntelliJ IDEA

like image 56
Kenan Güler Avatar answered Sep 19 '25 05:09

Kenan Güler


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']
        }
}
like image 33
Chayne P. S. Avatar answered Sep 19 '25 05:09

Chayne P. S.