Creating Dockerfile Templates
IB Manifest uses Jinja templating to make updating the Dockerfiles in the Iron
Bank (IB) repo as painless as possible. Each IB repo will need a Dockerfile
template located at /config/Dockerfile.tpl
. This guide will explain how to
create the Dockerfile template for new projects.
Dockerfile Templates in IB Manifest
For the most part, the Dockerfiles are fairly static with the exception of the python packages that get copied into them. Every time there is a change to the IB repo image, these packages get updated. The Dockerfile template allows you to avoid copy and pasting these COPY blocks or doing large string concatenations.
An example Dockerfile template is shown in the repository in the /templates
directory. One is also provided here for reference, but we recommend starting
with the Dockerfile you are trying to templatize.
Example Dockerfile Template
ARG BASE_REGISTRY=registry1.dso.mil
ARG BASE_IMAGE=ironbank/opensource/metrostar/miniconda
ARG BASE_TAG=4.11.0
FROM ${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG}
WORKDIR /opt
ENV LOCAL_CONDA_CHANNEL="${WORKDIR}/local_channel"
USER root
RUN mkdir /home/${NB_USER} \
&& chown -R ${NB_USER}:${NB_USER} /home/${NB_USER}
RUN mkdir -p ${LOCAL_CONDA_CHANNEL} && chown -R ${NB_USER}:${NB_USER} ${LOCAL_CONDA_CHANNEL}
COPY --chown=${NB_USER}:${NB_USER} /config/channeldata.json ${LOCAL_CONDA_CHANNEL}/channeldata.json
COPY --chown=${NB_USER}:${NB_USER} /config/linux-64/repodata.json ${LOCAL_CONDA_CHANNEL}/linux-64/repodata.json
COPY --chown=${NB_USER}:${NB_USER} /config/noarch/repodata.json ${LOCAL_CONDA_CHANNEL}/noarch/repodata.json
RUN chown -R ${NB_USER}:${NB_USER} ${LOCAL_CONDA_CHANNEL}
RUN dnf update -y && dnf install -y bzip2 gcc
# noarch packages
COPY [ \{%- for pkg in noarch_packages %}
"{{ pkg }}", \
{%- endfor %}
"${LOCAL_CONDA_CHANNEL}/noarch/", \
]
# linux packages
COPY [ \{%- for pkg in linux_packages %}
"{{ pkg }}", \
{%- endfor %}
"${LOCAL_CONDA_CHANNEL}/linux-64/", \
]
# special handling for packages with underscores
{%- for pkg in underscore_packages %}
COPY ["{{ pkg }}", "${LOCAL_CONDA_CHANNEL}/linux-64/_{{ pkg }}"]
{%- endfor %}
RUN chown -R ${NB_USER}:${NB_USER} ${LOCAL_CONDA_CHANNEL}
RUN chown -R ${NB_USER}:${NB_USER} /opt/
RUN chown -R ${NB_USER}:${NB_USER} /home/
USER ${NB_USER}
ENV PATH="${CONDA_PATH}/bin:$PATH"
WORKDIR /home/${NB_USER}
USER root
RUN dnf clean all && \
dnf remove -y bzip2 gcc && \
rm -rf info && \
conda clean -yaf && \
rm -rf /home/${NB_USER}/.conda && \
rm -rf /opt/conda/pkgs/cache && \
rm -rf /root/micromamba/pkgs/cache
RUN chown -R ${NB_USER}:${NB_USER} /opt/
RUN chown -R ${NB_USER}:${NB_USER} /home/
USER ${NB_USER}
HEALTHCHECK NONE
In order to create a Dockerfile, we really only need to account for 3 things:
- a list of noarch packages
- a list of linux packages
- a list of packages which start with an underscore
That last one is rather interesting. Because of the linting stage of the IB Pipeline, packages that lead with an underscore are deemed a security threat. To avoid conflicts, we remove the underscore temporarily and add it back on the other side of the fence.
All you need to do is replace these 3 things with the jinja syntax for handling
those lists. Instead of many lines of COPY
statments, you'll now have:
COPY [ \{%- for pkg in noarch_packages %}
"{{ pkg }}", \
{%- endfor %}
"${LOCAL_CONDA_CHANNEL}/noarch/", \
]
for the noarch, linux, and underscore packages.
Using a template in the workflow
The high level Update Repository
workflow will determine these package lists
for you and provide them to the template as a dictionary. You can either allow
the code to automatically pull the template from the IB repo by calling:
update_repository(
repo_dir='path_to_repo',
dockerfile_version='dockerfile_version',
)
Or, you can specify the specific location of a template you'd like to usse.
update_repository(
repo_dir='path_to_repo',
dockerfile_version='dockerfile_version',
dockerfile_template_path='path/to/template.tpl,
)
Building a Dockerfile
If you just want to build an individual Dockerfile from a template, you can call:
write_dockerfile(
noarch_packages=["requests-2.28.1-pyhd8ed1ab_1.tar.bz2"],
linux_packages=["python-3.10.6-h582c2e5_0_cpython.tar.bz2"],
underscore_packages=["openmp_mutex-4.5-2_gnu.tar.bz2"],
output_path='Dockerfile,
dockerfile_template_path='path/to/template.tpl,
)