# 0. Introduction - Did it on a macbook air as I am away from my Linux workstation at home - I will use some of my selfhosted services in examples, e.g. `registry.bouvais.lu` for docker registry and `git.bouvais.lu` for gitea. # 1. Create env First let's install everything that I will use using `brew`. ``` brew install docker ``` # 2. Images To created the needed dependency, I did a simple 2 images base + jupyter. The first image is a minimal python slim. I then add some ### 2.1. Base ```images/base/dockerfile FROM python:3.12-slim-bookworm AS base LABEL org.opencontainers.image.title="tenant-base" \ org.opencontainers.image.description="Hardened base image for tenant workspaces" \ org.opencontainers.image.source="https://git.bouvais.lu/adrien/" # System deps only — keep this layer stable so it's rarely rebuilt RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ curl \ tini \ && rm -rf /var/lib/apt/lists/* # Non-root user, fixed UID/GID for predictable K8s securityContext RUN groupadd --gid 1000 appuser \ && useradd --uid 1000 --gid appuser --shell /bin/bash --create-home appuser WORKDIR /home/appuser USER appuser ENTRYPOINT ["tini", "--"] ``` Then build and push it to the registry ``` docker build -t registry.bouvais.lu/tenant-base:1.0.0 images/base docker push registry.bouvais.lu/tenant-base:1.0.0 ``` ### 2.2. Jupyter Now I dp the same for a simple jupyter image. ``` ARG BASE_IMAGE=registry.bouvais.lu/tenant-base:1.0.0 FROM ${BASE_IMAGE} LABEL org.opencontainers.image.title="tenant-jupyter" \ org.opencontainers.image.description="JupyterLab image built on tenant-base" \ org.opencontainers.image.base.name="${BASE_IMAGE}" USER root COPY --chown=appuser:appuser requirements.txt /tmp/requirements.txt RUN pip install --no-cache-dir -r /tmp/requirements.txt \ && rm /tmp/requirements.txt # No secrets baked in — S3 creds come from a mounted K8s Secret / env at runtime USER appuser WORKDIR /home/appuser/work EXPOSE 8888 CMD ["jupyter", "lab", \ "--ip=0.0.0.0", \ "--port=8888", \ "--no-browser", \ "--ServerApp.token=", \ "--ServerApp.allow_remote_access=True"] ```