How-to: Container Tasks#

Step-by-step guides for common container tasks at SKAO.


Write an efficient Dockerfile#

Minimise layers and image size:

# Use build arguments for flexibility
ARG base_image="python:3.9.5"
FROM $base_image

# Install packages and clean up in one layer
RUN apt-get update && \
    apt-get install -y \
        apache2-bin \
        binutils \
        cmake && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

# Copy requirements first (changes less often)
COPY pyproject.toml poetry.lock ./
ENV POETRY_NO_INTERACTION=1
ENV POETRY_VIRTUALENVS_IN_PROJECT=1
ENV POETRY_VIRTUALENVS_CREATE=1

RUN poetry install --no-root


# Copy application code last (changes most often)
COPY ./app /app

Key practices:

  • Order layers from least to most frequently changing

  • Combine RUN commands to reduce layers

  • Always clean package caches after apt-get install

  • Sort multi-line arguments alphabetically for readability

Use multi-stage builds#

Multi-stage builds separate build tools from runtime to reduce final image size:

FROM artefact.skao.int/ska-build-python:0.1.1 as build

WORKDIR /src
COPY pyproject.toml poetry.lock* ./

ENV POETRY_NO_INTERACTION=1
ENV POETRY_VIRTUALENVS_IN_PROJECT=1
ENV POETRY_VIRTUALENVS_CREATE=1

# Install dependencies only (not the code)
RUN poetry install --no-root

FROM artefact.skao.int/ska-python:0.1.2

WORKDIR /src

# Add virtualenv to PATH
ENV VIRTUAL_ENV=/src/.venv
ENV PATH="$VIRTUAL_ENV/bin:$PATH"

# Copy only the built virtualenv
COPY --from=build ${VIRTUAL_ENV} ${VIRTUAL_ENV}
COPY ./src/my_project ./my_project

ENV PYTHONPATH=${PYTHONPATH}:/src/

This keeps build tools (compilers, dev packages) out of your production image.

Name and tag images correctly#

Image naming convention:

ska-tango-examples/powersupply:1.13.2
└── repository ──────┘└─ app ─┘└ tag ┘

Tagging strategy:

  1. During development: Tag with short commit hash

    git rev-parse --verify --short=8 HEAD
    # Result: bbedf059
    
  2. For production releases: Tag with semantic version

    ska-tango-examples/powersupply:1.13.2   # Full version
    ska-tango-examples/powersupply:1.13     # Minor version
    ska-tango-examples/powersupply:1        # Major version
    ska-tango-examples/powersupply:latest   # Current release
    
  3. For debug images: Append -dev

    ska-tango-examples/powersupply-dev:1.13.2
    

Warning

Always use fully qualified semantic versions for production deployments. Never deploy using :latest — it changes unexpectedly.

Configure ENTRYPOINT and CMD#

Use ENTRYPOINT for the application and CMD for default arguments:

ENTRYPOINT ["/bin/cat"]
CMD ["/etc/hosts"]

Always use the exec format (["thing"]) to ensure proper signal propagation:

# Correct — signals propagate to the application
ENTRYPOINT ["/usr/bin/myapp"]

# Incorrect — signals go to the shell, not the app
ENTRYPOINT /usr/bin/myapp

Run containers with resource limits#

Set memory and CPU constraints to prevent runaway containers:

docker run --rm --name postgresdb \
    --memory="1g" \
    --cpu-shares="1024" \
    --cpuset-cpus="1,3" \
    -d postgres

This limits the container to 1GB memory and pins it to CPUs 1 and 3.

Mount volumes securely#

Use read-only mounts when you don’t need write access:

docker run -v /etc/passwd:/etc/passwd:ro \
           -v /config:/app/config:ro \
           myimage:1.0.0

Pass configuration via environment variables#

Set defaults in your Dockerfile:

ENV APP_PORT=8080
ENV LOG_LEVEL=INFO

Override at runtime:

docker run -e APP_PORT=9090 -e LOG_LEVEL=DEBUG myimage:1.0.0

Warning

Never pass secrets (passwords, API keys) via command line arguments. Use environment variables or mounted secret files instead.

Sign and push images to the registry#

Push to the SKAO Central Artefact Repository:

docker push artefact.skao.int/ska-tango-images/myimage:1.0.0

Verify image signatures:

docker trust inspect --pretty \
    artefact.skao.int/ska-tango-images/ska-python-runtime:1.2.3

Create a Helm chart for Kubernetes#

Create the chart structure:

charts/myapp/
    Chart.yaml          # Chart metadata and dependencies
    values.yaml         # Default configuration values
    templates/          # Kubernetes manifest templates
    templates/NOTES.txt # Usage notes shown after install
    templates/tests/    # Test templates for 'helm test'

Chart.yaml requirements:

name: my-app
version: 1.0.0
description: Very important app
home: https://www.skao.int/
sources:
  - https://gitlab.com/ska-telescope/my-app
maintainers:
  - name: myaccount
    email: myaccount@skatelescope.org

Validate your chart:

helm lint ./charts/my-app/

Test locally with Minikube:

helm install --dry-run --debug ./charts/my-app/

See Also#