Building an image

This topic explains how to include an extra system, third-party tool, or configuration in your image by bundling workshop content from the Learning Center workshop base image. The following sample workshop template provides a Dockerfile.

Structure of the Dockerfile

The structure of the Dockerfile in the sample workshop template is:


COPY --chown=1001:0 . /home/eduk8s/

RUN mv /home/eduk8s/workshop /opt/workshop

RUN fix-permissions /home/eduk8s

The default Dockerfile action is to:

  • Copy all files from a registry to the /home/eduk8s directory. You must build the custom workshop images on the workshop image. You can do this directly or you can also create an intermediate base image to install extra packages required by a number of different workshops. The --chown=1001:0 option ensures that files are owned by the appropriate user and group.
  • The workshop subdirectory is moved to /opt/workshop so that it is not visible to the user. This subdirectory is in an area searchable for workshop content, in addition to /home/eduk8s/workshop.

To customize your Dockerfile:

  • You can ignore other files or directories from the repository, by listing them in the .dockerignore file.
  • You can include RUN statements in the Dockerfile to run custom-build steps, but the USER inherited from the base image has user ID 1001 and is not the root user.

Base images and version tags

The sample Dockerfile provided above and the GitHub repository workshop templates reference the workshop base image as follows:

Custom workshop base images

The base-environment workshop images include language run times for Node.js and Python. If you need a different language runtime or a different version of a language runtime, you must create a custom workshop base image which includes the environment you need. This custom workshop image is derived from base-environment but includes extra runtime components.

The following Dockerfile example creates a Java JDK11-customized image:

FROM ${IMAGE_REPOSITORY}/pkgs-java-tools as java-tools
COPY --from=java-tools --chown=1001:0 /opt/jdk11 /opt/java
COPY --from=java-tools --chown=1001:0 /opt/gradle /opt/gradle
COPY --from=java-tools --chown=1001:0 /opt/maven /opt/maven
COPY --from=java-tools --chown=1001:0 /opt/code-server/extensions/.  /opt/code-server/extensions/
COPY --from=java-tools --chown=1001:0 /home/eduk8s/. /home/eduk8s/
COPY --from=java-tools --chown=1001:0 /opt/eduk8s/. /opt/eduk8s/
ENV PATH=/opt/java/bin:/opt/gradle/bin:/opt/maven/bin:$PATH \
    JAVA_HOME=/opt/java \

Installing extra system packages

Installing extra system packages requires that you run the installation as root. You must switch the user commands before running the command, and then switch the user back to user ID of 1001.

USER root

RUN ... commands to install system packages

USER 1001

VMware recommends that you only use the root user to install extra system packages. Don’t use the root user when adding anything under /home/eduk8s. Otherwise, you must ensure the user ID and group for directories and files are set to 1001:0 and then run the fix-permissions command if necessary.

When you run any command as root, you must temporarily override the value of the HOME environment variable and set it to /root.

If you don’t do this the root user drops configuration files in /home/eduk8s, thinking it is the root home directory, because the HOME environment variable is by default set to /home/eduk8s. This can cause commands run later during the workshop to fail if they try to update the configuration files as they have wrong permissions.

Fixing the file and group ownership and running fix-permissions can help with this problem, but not in every case, because of permissions the root user may apply and how container image layers work. VMware recommends that you use the following:

USER root

RUN HOME=/root && \
    ... commands to install system packages

USER 1001

Installing third-party packages

If you are not using system packaging tools to install extra packages, but are manually downloading packages and optionally compiling them to binaries, it is better to do this as the default user and not root.

If compiling packages, VMware recommends working in a temporary directory under /tmp and removing the directory as part of the same RUN statement when done.

If you are installing a binary, you can install it in /home/eduk8s/bin. This directory is in the application search path defined by the PATH environment variable for the image.

To install a directory hierarchy of files, create a separate directory under /opt to install everything. You can override the PATH environment variable in the Dockerfile to add an extra directory for application binaries and scripts. You can override the LD_LIBRARY_PATH environment variable for the location of shared libraries.

If installing any files from a RUN instruction into /home/eduk8s, VMware recommends that you run fix-permissions as part of the same instruction to avoid copies of files being made into a new layer, which applies to the case where fix-permissions is only run in a later RUN instruction. You can still leave the final RUN instruction for fix-permissions as it is smart enough not to apply changes if the file permissions are already set correctly and so it does not trigger a copy of a file when run more than once.

check-circle-line exclamation-circle-line close-line
Scroll to top icon