How to build a Tango image using PyTango
When building OCI images, it is recommended to use a separate build stage from the runtime stage to avoid including build-time dependencies in the final image.
ska-base-images provides ska-build-python as a build image for python-based applications and can be used for building PyTango-based application images.
For the runtime image it is recommended to use
ska-tango-images-tango-python. ska-tango-images-tango-python provides the
tango_admin utility which is often useful to include in the image.
Dockerfile Template
It is recommended to install your application into a python virtual environment in the build image, then copy this environment across to the runtime image.
For PyTango applications that can be installed via pip, this can be done with the following skeleton:
ARG BUILD_IMAGE=artefact.skao.int/ska-build-python:0.3.1
ARG BASE_IMAGE=artefact.skao.int/ska-tango-images-tango-python:0.3.1
FROM $BUILD_IMAGE AS build
ENV VIRTUAL_ENV=/app
RUN set -xe; \
apt-get update; \
apt-get install -y --no-install-recommends \
python3-venv; \
python3 -m venv $VIRTUAL_ENV
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
# install application into $VIRTUAL_ENV
# We don't want to copy pip into the runtime image
RUN pip uninstall -y pip
FROM $BASE_IMAGE
ENV VIRTUAL_ENV=/app
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
COPY --from=build $VIRTUAL_ENV $VIRTUAL_ENV
LABEL int.skao.image.team=<my-team> \
int.skao.image.authors=<author> \
int.skao.image.url=<gitlab url> \
description=<description> \
license=<license>
Note
It is recommended to provide BUILD_IMAGE and BASE_IMAGE arguments rather than hard-coding them directly. These arguments can be used by tools such as the SKA Tango Test Bench to test out different versions of build and base images.
Dockerfile Template for poetry applications
To build an image containing a local application managed by poetry, you could use the following skeleton to have poetry install the application into the virtual environment:
ARG BUILD_IMAGE=artefact.skao.int/ska-build-python:0.3.1
ARG BASE_IMAGE=artefact.skao.int/ska-tango-images-tango-python:0.3.1
FROM $BUILD_IMAGE AS build
ENV VIRTUAL_ENV=/app \
POETRY_NO_INTERACTION=1 \
POETRY_VIRTUALENVS_IN_PROJECT=1
RUN set -xe; \
apt-get update; \
apt-get install -y --no-install-recommends \
python3-venv; \
python3 -m venv $VIRTUAL_ENV; \
mkdir /build; \
ln -s $VIRTUAL_ENV /build/.venv
ENV PATH=$VIRTUAL_ENV/bin:$PATH
WORKDIR /build
# We install the dependencies and the application in two steps so that the
# dependency installation can be cached by the OCI image builder. The
# important point is to install the dependencies _before_ we copy in src so
# that changes to the src directory to not result in needlessly reinstalling the
# dependencies.
# Installing the dependencies into /app here relies on the .venv symlink created
# above. We use poetry to install the dependencies so that we can pass
# `--only main` to avoid installing dev dependencies. This option is not
# available for pip.
COPY pyproject.toml poetry.lock* ./
RUN poetry install --only main --no-root --no-directory
# The README.md here must match the `tool.poetry.readme` key in the
# pyproject.toml otherwise the `pip install` step below will fail.
COPY README.md ./
COPY src ./src
# We use pip to install the application because `poetry install` is
# equivalent to `pip install --editable` which creates symlinks to the src
# directory, whereas we want to copy the files.
RUN pip install --no-deps .
# We don't want to copy pip into the runtime image
RUN pip uninstall -y pip
FROM $BASE_IMAGE
ENV VIRTUAL_ENV=/app
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
COPY --from=build $VIRTUAL_ENV $VIRTUAL_ENV
LABEL int.skao.image.team=<my-team> \
int.skao.image.authors=<author> \
int.skao.image.url=<gitlab url> \
description=<description> \
license=<license>
Example
The following Dockerfile builds a dsconfig image, similar to ska-tango-images-tango-dsconfig, except without pinning the versions:
ARG BUILD_IMAGE=artefact.skao.int/ska-build-python:0.3.1
ARG BASE_IMAGE=artefact.skao.int/ska-tango-images-tango-python:0.3.1
FROM $BUILD_IMAGE AS build
ENV VIRTUAL_ENV=/app
RUN set -xe; \
apt-get update; \
apt-get install -y --no-install-recommends \
python3-venv; \
python3 -m venv $VIRTUAL_ENV
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
RUN pip install --no-cache-dir dsconfig
# We don't want to copy pip into the runtime image
RUN pip uninstall -y pip
FROM $BASE_IMAGE
ENV VIRTUAL_ENV=/app
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
COPY --from=build $VIRTUAL_ENV $VIRTUAL_ENV
ENTRYPOINT ["python", "-m", "dsconfig.dump"]
LABEL int.skao.image.team="Team Example" \
int.skao.image.authors="an@example.com" \
int.skao.image.url="https://gitlab.com/example" \
description="This is just an example and these labels should be updated" \
license="BSD-3-Clause"
To build and run an image using this example, copy the above into a file named
Dockerfile and run the following commands from a terminal inside the same
directory:
docker image build -t my-dsconfig .
docker run --rm --env TANGO_HOST=$TANGO_HOST --net=host my-dsconfig
This will place you in an interactive terminal for the container, which will have the dsconfig command line tools such as json2tango installed.