- Review each guideline
- Add your comments and suggestions to the "Comments" column
- The disposition will be determined based on of your input and discussion with the team.
- Once you have input your comments, close the JIRA task to signal the team that you have provided your input.
The guidelines listed here:
- Are intended to address the build and validation processes.
- Don't address the fundamentals or principles of container images.
- add guideline addressing base images, e.g. example in project proposal re: alpine base image (FS)
- add guideline addressing multi-platform images (FS)
- add guideline addressing image names, e.g. "db" discouraged, "onap-component-db" preferred, e.g. "music-db" (FS)
- add guideline addressing proper use of onap image repo (FS)
When executing "
Irrespective of where the
Inadvertently including files that are not necessary for building an image results in a larger build context and larger image size.
This can increase the time to build the image, time to pull and push it, and the container runtime size.
"this can increase'..."
I suggest the very first guideline should be a general statement about image size, as many of these individual items address that general concern
2. Exclude with .dockerignore
Exclude files not relevant to the build with a
This file supports exclusion patterns similar to
3.Use multi-stage builds
Multi-stage builds reduces the size of an image, without worrying about the number of intermediate layers and files.
An image is built during the final stage of the build process. The number of image layers can be minimized by leveraging build cache.
For a build that contains several layers, order them from the less frequently changed (re-use build cache) to the more frequently changed:
|"the number of layers..." Perhaps say "see below 'Re-use the build cache'|
4. Don’t install unnecessary packages
Avoid installing extra or unnecessary packages.
This will reduce complexity, dependencies, file sizes, and build times, Don't include a text editor in a database image.
5. Decouple applications
Apply the principle of "separation of concerns."
Each container should have only one concern. Decoupling applications into multiple containers makes it easier to reuse containers.
6. Minimize the number of layers
Use multi-stage builds, to only copy the artifacts you need into the final image.
Tools and debug information can be added to intermediate build stages without increasing the size of the final image.
|"tools and debug info..." I don't understand this. Perhaps an example would be helpful|
7. Sort multi-line arguments
To minimize duplication of packages and make the list of packages much easier to update, sort multi-line arguments alphanumerically.
8. Re-use the build cache
As each instruction in the Dockerfile is examined, the builder looks for an existing image in its cache that can be reused, rather than creating a duplicate image.
Once the cache is invalidated, all subsequent
Build File Instructions
Use current official repositories for base images. ONAP images must be vendor agnostic; ensure that the base images are cpu architecture-agnostic.
|are there base images that are multi-pltfrom, or is there a need to create multiple images for multiple targets? eg. there is 'alpine' and 'arm64v8/alpine'|
Labels are unique key-value pairs used to add metadata to container images and containers. They help organize images by project, add licensing information, or to support build and CI pipeline.
An image can have more that one label. For each label, begin a new line with "LABEL" and add one or more key-value pairs.
To make the build file (e.g. Dockerfile) more readable, understandable and maintainable:
ERRORS IN STAGES OF A PIPE
7. Use "set -o pipefail &&" to ensure that the RUN command only succeeds if all stages of a pipe succeed.
This instruction provides defaults to run the application packaged in a container image. It should always be used in the form:
Typically, CMD should run an interactive shell. That way users get a usable shell when they execute "docker run -it ..." For example:
CMD ["sh", "-c", "echo $ENV" ]
Note: If the user provides arguments to "docker run", they override the defaults specified in "CMD."
Use well-known ports for your application. For example, an image containing Apache web server should use
Use ENV to avoid hard-coding values for variables and parameters in the your build file. ENV can parameterize container variables. For example, the version of the software in the container (VERSION), the PATH environment variable and other execution environment variables (MAJOR).
ADD or COPY
ADD is recommended for local tar file auto-extraction into the image (e.g.
If you have to copy several files from your context,
To reduce the number of layers and the image size, don't use
The image can be run as
$ docker run my_command
$ docker rum my_command --verbose -n 10
Copy the script into the container and run it via
User can then execute:
$ docker run redis
VOLUME exposes database storage areas, configuration storage, or files/folders created by the container.
Do not run containers as root. Use USER to change to an non-root user.
Create the user and group as in this example:
Avoid installing or using
To minimize the number of layers, avoid switching
Always use absolute paths for your
Images built from
There are concerns in building images outside the scope of the Dockerfile itself
See here for image tagging guidelines: Independent Versioning and Release Process#StandardizedDockerTagging
The CIA has undertaken to reduce image size and ensure images may be build and run on multiple platforms.
This activity has exposed the team to differing approaches taken by project teams to build images. This page
presents best practices for building images, as an extension the the best practices currently described for
Dockerfiles (add link)
Note: the best practices are currently documented both
and here https://wiki.onap.org/display/DW/Container+Image+Minimization+Guidelines
There are two scenarios for image builds; Local and CSIT.
Local builds are required in order to validate assets such as poms, Dockerfiles, and scripts.
Developers should not push assets into a project repo until there have been validated, and the CSIT
pipeline requires that assets are in repos, ergo, local builds are mandatory.
Local builds involve not simply building images, but running them and testing wether they are behaving properly.
These steps are often not documented, and in some cases require reverse-engineering to
Every project should document steps to building images and testing them locally. This should be part of the project
ReadTheDocs. The CIA team can contribute to documentation as it works through projects. Documentation should be
addressed to an audience that has general Unix and programming skills, but does not have knowledge of project or
arcane topics such as complex maven definitions.
Recommendation: project RTD includes materail describing local build and test of docker images
Many projects build images as part of the workflow of building application targets. While this provides some
convenience, there are drawbacks.
This approach tightly-couples the application build process with the container packaging process, perhaps
Other projects provide shell scripts to build images. This has the benefit of separating the build and packaging steps
There are currently several maven plugins in use by ONAP project teams.
The spotify docker-maven-plugin is no longer recommended, as Spotify encourages the use of pre-written Dockerfiles,
as opposed to generating a Dockerfile via plugin configuration.
In addition, this plugin does not execute on all platforms, including Arm, and therefore should not be used.
The spotify dockerfile-maven-plugin has the benefit of supporting a pre-written Dockerfile, but also has issues
running on all platforms, and therefore should not be used (TBD - confirm details).
Finally, the fabric8 docker-maven-plugin has been used successfully to build images, using explicit Dockerfiles,
on multiple platforms.
Recommendation: If one uses maven to build images, use the fabric8 docker-maven-plugin (v 0.28.0, as previous don't work on Arm)
For projects that employ maven to build images, care must be taken to ensure that images may be built on a number
of platforms (e.g. amd64, arm64, etc)
Normative base images are available on DockerHub as multi-platfrom FAT manifests (i.e. a universal label that
lists platform specific images). However, projects often make use of the ONAP nexus registry as a source of images.
While this serves as an image cache that improves CSIT build performance, it breaks multi-platfrom compatibility as
only a platform-specific image is cached, not the multi-platform manifest.
ONAP provides a maven settings.xml file which defines the following:
This in effect hardcodes an amd64 base image for a project using maven as the image build tool.
To address this issue, and avoid changing the ONAP provided settings.xml, one may use the following directive
in the configuration section of the fabric8 docker-maven-plugin
and set the docker.pull.registry variable when invoking maven, e.g.
> mvn install -Pdocker -Ddocker.pull.registry=docker.io
In order to test the maven lifecycle to push images, a developer must instantiate a local docker registry,
configure the pom appropriately, and invoke mvn appropriately.
Start a local docker image repo:
> docker run -d -p 5000:5000 --restart=always --name registry registry:2
Add the following directive in the configuration section of the fabric8 docker-maven-plugin
and set the docker.push.registry variable when invoking maven, e.g.
> mvn install -Pdocker -Ddocker.push.registry=localhost:5000 docker:push
Note invocation of docker:deploy lifecycle
1) alpine images use sh rather then bash. Some side-effects
- In Dockerfile, CMD and ENTRYPOINT
bash - ENTRYPOINT ["startup.sh"]
sh - ENTRYPOINT ["sh", "startup.sh"]