How to Build Docker Image with Helm Chart Or VM Image Using Maven and Packer.

Eugene Paniot
4 min readSep 6, 2021

--

Part 1. Maven

Motivation

We’d like to have independent and portable, of any custom scripts (located externally in git, etc) process to build docker image, and predefined helm-charts to save the time for chart writing. What could be used/ported in any repository.

Maven

Maven gives us out of the box services that assist us when building:

  • Docker image;
  • Helm Chart;
  • Acceptance (PDV) Tests;
  • VM images (GCP, AWS AMI or Digital Ocean Snapshot).

You could also think of the pom.xml as analogous to a Makefile or another Bashish script or any other Automation tool like Jenkins or Rundeck. When you are using Bashish to build something like MySQL or Java Tomcat image, you’ll usually have a file named Makefile or build.sh that contains explicit instructions for build and upload artifacts into Docker registry, Helm repo, or Artifactory.

The POM is also not specific to building Java projects. While Maven’s default plugins are targeted at building JAR artifacts from a set of source, tests, and resources, there is nothing preventing us from defining a POM for a project that contains Docker, Helm Chart, PDV Tests and VM Builds.

Builds Portability

All project’s POM files inherit from a base POM, which defines a set of defaults — settings and instructions shared by all projects.

  1. We want to build a large set of components, some of them are similar, but some of them aren’t. We don’t want to have to repeat the same dependency elements over and over again, and we want to manage projects in a Cattle manner over Pets.

A build’s “portability” is a measure of how easy it is to take a particular project and build it. A build which works without any custom configuration or customization of properties files is more portable than a build which requires a great deal of work to build from scratch.

The most portable project builds tend to just work, out of the box, and the least portable builds require you to jump through hoops and configure settings, credentials, networks or so on.

Maven makes possible to avoid repeating yourself makes use of inheritance via the parent element. When a project specifies a parent, it inherits the information in the parent project’s POM. It can then override and add to the values specified in this parent POM.

Running mvn help:effective-pom in project would show a POM that is the result of merging the Super-POM(parent) with the POM defined by common-parent, then POM defined in tomcat8-legacy-jdk8 and the POM defined in component.

If you are just writing a simple Docker or VM build that produces a Docker image and Helm Chart, or VM Image, you don’t have to write build instructions. All you would need, in this case, is the simplest possible POM.

<?xml version="1.0" encoding="UTF-8"?>
<project>
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<parent>
<groupId>helm.charts</groupId>
<artifactId>parent-common</artifactId>
<version>RELEASE</version>
</parent>
<artifactId>zookeeper</artifactId>
<version>3.6</version>
<description>zookeeper build</description>
...
</project>

This POM defines a groupId, artifactId, and version: the three required coordinates for every project.

It’s time to build

Example for VM Image on GCP.

Just execute:

mvn clean deploy

Output:

[INFO] ---------------------< :jenkins-agent >----------------------
[INFO] Building jenkins-agent v20210730
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ jenkins-agent ---
[INFO]
[INFO] --- git-commit-id-plugin:4.0.2:revision (Get the Git Infos) @ jenkins-agent ---
...
[INFO] --- exec-maven-plugin:1.6.0:exec (Packer Build) @ jenkins-agent ---
==> googlecompute: Checking image does not exist...
==> googlecompute: Creating temporary RSA SSH key for instance...
==> googlecompute: Using image:
==> googlecompute: Creating instance...
googlecompute: Loading zone:
googlecompute: Loading machine type: n1-highcpu-16
googlecompute: Requesting instance creation...
googlecompute: Waiting for creation operation to complete...
googlecompute: Instance has been created!
==> googlecompute: Waiting for the instance to become running...
googlecompute: IP:
==> googlecompute: Using SSH communicator to connect:
==> googlecompute: Waiting for SSH to become available...
==> googlecompute: Connected to SSH!
==> googlecompute: Provisioning with Ansible...
googlecompute: Setting up proxy adapter for Ansible....
...
googlecompute:
==> googlecompute: Deleting instance...
googlecompute: Instance has been deleted!
==> googlecompute: Creating image...
==> googlecompute: Deleting disk...
googlecompute: Disk has been deleted!
==> googlecompute: Running post-processor: manifest
...
==> Builds finished. The artifacts of successful builds are:
--> googlecompute: A disk image was created: jenkins-agent-v20210730
--> googlecompute: A disk image was created: jenkins-agent-v20210730
...
[INFO] --- maven-deploy-plugin:3.0.0-M1:deploy (default-deploy) @ jenkins-agent ---
...[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 13:42 min
[INFO] Finished at: 2021-07-30T18:02:27+03:00
[INFO] ------------------------------------------------------------------------

That’s all! You got jenkins-agent-v20210730 image created just in a single simple command.

Part 2 — https://medium.com/@e.paniot/how-to-build-docker-image-with-helm-chart-or-vm-image-using-maven-and-packer-part-2-1e62dff7773

--

--

Eugene Paniot

Engineer with 15 years of experience in SRE and DevOPS, networking, databases, managing cloud and developing automation solutions.