Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  • The Jenkins job builds an image using just the Dockerfile with no custom parameters. Therefore, the Dockerfile all by itself must build and image for the Yale environment, while files in this project override build args and provide additional tags only on the developer’s desktop.

  • The exact method of doing the equivalent of a “docker build” on the desktop is defined by the developer in a profile. It is possible to use a local docker command, or a remote ssh docker command, or a substitute for Docker like Podman.

  • Each user provides a profile that defines the Sandbox environment (the local substitute for Artifactory and Harbor for example) and the personal choices (the use of a local docker, remote docker, or substitute).

  • A script file is included in every project to define any project specific overrides. For example, the Dockerfile may contain a reference to a Released artifact version such as 1.0.19 while the script may contain the developer’s override version 1.0.20-SANDBOX.

...

ARGs

Whenever there is a value in the Dockerfile that should be different in the Sandbox from the Jenkins build value, create an ARG and set the default to match the value in Jenkins. Then you can override this ARG value by adding a --build-arg parameter to the “docker build”.

...

Remember, the build.ps1 and build.json files are checked into the Git project but are not used by the Jenkins build. While they contain information for you, they are mostly intended to help the next developers who works on this project, providing an example of things that they may want to customize.

Parameters for the Build

Most parameters like --build-arg and -t are described in the Docker documentation and have obvious uses. Two parameters are always supplied by Jenkins and turn out to be very useful for developers as well. They are more obscure and should be explained:

Remove Bad Optimization

Docker has two default behaviors that over optimize the build process and generate mistakes. These should be suppressed by adding parameters to turn them off.

--no-cache disables a Docker optimization which caches the results of each line in the Dockerfile and in a subsequent run of the same file (or any file that starts out the same), uses the saved results from the previous run instead of re-executing the statement. This might be occasionally helpful if you have a very long running statement that never changes, but in practice it is often a bad optimization. There are some statements that reference things in the network that change over time, and though the statement itself has not changed, the results are different. An example everyone may use isWhile this may save a few seconds, it produces unexpected behavior and is counter intuitive. The problem occurs with statements that get files or packages from the network. The Dockerfile statement is expected to get the most current files and not some files downloaded and saved months ago. This can happen with all sorts of statements, but the one example that makes the problem clear is the commonly used expression to apply the most recent bugfixes to the system:

“RUN apt update && apt upgrade -Y”

You expect this to put all the currently available fixes on the image, but if this was run and cached a month ago then Docker will reuse the result, which omits fixes added in the last month. There are less obvious examples that suggest that --no-cache is a better defaultSince this statement itself doesn’t change, the default behavior of Docker is to download fixes the first time you build the image, and then never apply any new patches to any future build. Specifying --no-cache runs the entire Dockerfile fresh every time.

--pull is a special version of --no-cache that applies to the image in the FROM statement. A DockerHub image like “tomcat:latest” is periodically updated with the latest version and fixes. Nobody would use it, but more specific tags that require jdk11 and tomcat 9 will still be automatically update with the latest version of 9 and the latest fixes to jdk11. When you use a base image name that is periodically updated, and you want to get the most recent version, you have to specific --pull on the docker build or docker will use the previous image that it pulled which had the same tag name.

Base Image Choice

If you look at all the Tomcat tags in DockerHub, you will find versions based on several distributions. Currently Debian is the simplest distribution that remains current and has fixes for all reported vulnerabilitiesA more reasonable choice for a base image specifies a particular version of Java and Tomcat, but then allows the latest dot release with bug fixes. The default Docker behavior is to download a base image and then never check DockerHub for a newer version of the image as long as the tag doesn’t change. Adding --pull causes Docker to check for a more recent version of the base image and pull one if it is available.

Base Choice

The official Tomcat images offer versions of OpenJDK from various sources (Amazon, Eclipse, etc.) and various releases of Debian and Ubuntu.

Plain OpenJDK and the most recent release of Debian seem to be good choices, and Debian has a special package repository that is quickly updated whenever a vulnerability is announced.