|
| 1 | +# ============================================================================= |
| 2 | +# oceanstream-echodata — base image for the batch echodata pipeline |
| 3 | +# ============================================================================= |
| 4 | +# Ships `oceanstream[echodata]` plus every third-party module the scripts under |
| 5 | +# scripts/batch_processing/ import, and the scripts themselves. It runs nothing |
| 6 | +# by itself; downstream images (denoise-lab-worker) add their own entrypoint. |
| 7 | +# |
| 8 | +# Build from the repo root: |
| 9 | +# az acr build --registry oceanstreamdevacr --platform linux/amd64 \ |
| 10 | +# --image oceanstream-echodata:<tag> -f deploy/Dockerfile.echodata . |
| 11 | +# ============================================================================= |
| 12 | + |
| 13 | +ARG PYTHON_VERSION=3.12 |
| 14 | + |
| 15 | +# ----------------------------------------------------------------------------- |
| 16 | +# Stage 1: build the virtualenv |
| 17 | +# ----------------------------------------------------------------------------- |
| 18 | +# Pinned to bookworm: trixie renamed the GDAL runtime lib (libgdal32 -> |
| 19 | +# libgdal36), so the runtime stage below could not satisfy it. |
| 20 | +FROM python:${PYTHON_VERSION}-slim-bookworm AS builder |
| 21 | + |
| 22 | +# git is not optional: pyproject.toml pulls echopype from the OceanStreamIO |
| 23 | +# fork's `oceanstream-integration` branch, and it builds with setuptools_scm, |
| 24 | +# which reads the cloned .git to derive a version. |
| 25 | +RUN apt-get update && apt-get install -y --no-install-recommends \ |
| 26 | + build-essential \ |
| 27 | + git \ |
| 28 | + libgdal-dev \ |
| 29 | + libgeos-dev \ |
| 30 | + libproj-dev \ |
| 31 | + && rm -rf /var/lib/apt/lists/* |
| 32 | + |
| 33 | +RUN python -m venv /opt/venv |
| 34 | +ENV PATH="/opt/venv/bin:$PATH" |
| 35 | +RUN pip install --no-cache-dir --upgrade pip wheel |
| 36 | + |
| 37 | +WORKDIR /src |
| 38 | + |
| 39 | +# Resolve the dependency tree against a package skeleton first. Editing the |
| 40 | +# source then only re-runs the --no-deps install below, instead of re-resolving |
| 41 | +# echopype-from-git, dask[complete], copernicusmarine and friends. |
| 42 | +COPY pyproject.toml ./ |
| 43 | +COPY oceanstream/README.md ./oceanstream/README.md |
| 44 | + |
| 45 | +# The trailing names are modules the batch scripts import that the `echodata` |
| 46 | +# extra does not cover. They go in the SAME pip invocation on purpose: s3fs |
| 47 | +# pulls aiobotocore, which pins botocore to a narrow range, so boto3 has to be |
| 48 | +# resolved alongside it rather than bolted on afterwards. |
| 49 | +# Deliberately absent is the `echodata-viz` extra — holoviews/hvplot/panel/ |
| 50 | +# bokeh/datashader are reached only by plot_interactive_echogram(), which |
| 51 | +# imports them lazily and which this pipeline never calls. |
| 52 | +RUN touch oceanstream/__init__.py \ |
| 53 | + && pip install --no-cache-dir ".[echodata]" \ |
| 54 | + boto3 \ |
| 55 | + cartopy \ |
| 56 | + cmocean \ |
| 57 | + matplotlib \ |
| 58 | + rasterio \ |
| 59 | + geopandas \ |
| 60 | + scipy \ |
| 61 | + pillow \ |
| 62 | + psycopg2-binary \ |
| 63 | + azure-storage-file-share \ |
| 64 | + python-dotenv |
| 65 | + |
| 66 | +COPY oceanstream/ ./oceanstream/ |
| 67 | +RUN pip install --no-cache-dir --no-deps --force-reinstall . |
| 68 | + |
| 69 | +# ----------------------------------------------------------------------------- |
| 70 | +# Stage 2: runtime |
| 71 | +# ----------------------------------------------------------------------------- |
| 72 | +# Must match the builder's Debian release — the venv links against its libs. |
| 73 | +FROM python:${PYTHON_VERSION}-slim-bookworm AS runtime |
| 74 | + |
| 75 | +LABEL org.opencontainers.image.title="oceanstream-echodata" |
| 76 | +LABEL org.opencontainers.image.description="oceanstream[echodata] plus the batch_processing pipeline scripts" |
| 77 | +LABEL org.opencontainers.image.source="https://github.com/OceanStreamIO/oceanstream-cli" |
| 78 | + |
| 79 | +RUN apt-get update && apt-get install -y --no-install-recommends \ |
| 80 | + libgdal32 \ |
| 81 | + libgeos-c1v5 \ |
| 82 | + libproj25 \ |
| 83 | + ca-certificates \ |
| 84 | + curl \ |
| 85 | + && rm -rf /var/lib/apt/lists/* \ |
| 86 | + && apt-get clean |
| 87 | + |
| 88 | +# uid/gid 1000 is fixed on purpose: the worker and web containers share PVCs, |
| 89 | +# and the pod's fsGroup has to match one number across every image. |
| 90 | +RUN groupadd -g 1000 oceanstream \ |
| 91 | + && useradd -u 1000 -g 1000 -m -d /home/oceanstream -s /usr/sbin/nologin oceanstream |
| 92 | + |
| 93 | +COPY --from=builder /opt/venv /opt/venv |
| 94 | +COPY scripts/ /opt/oceanstream/scripts/ |
| 95 | + |
| 96 | +# MPLBACKEND: without Agg, matplotlib picks a GUI backend and dies on import. |
| 97 | +# MPLCONFIGDIR/XDG_CACHE_HOME default under $HOME, which is not writable once |
| 98 | +# the pod runs as an arbitrary fsGroup; /tmp always is. |
| 99 | +ENV PATH="/opt/venv/bin:$PATH" \ |
| 100 | + PYTHONUNBUFFERED=1 \ |
| 101 | + PYTHONDONTWRITEBYTECODE=1 \ |
| 102 | + HOME=/home/oceanstream \ |
| 103 | + OCEANSTREAM_SCRIPTS=/opt/oceanstream/scripts/batch_processing \ |
| 104 | + MPLBACKEND=Agg \ |
| 105 | + MPLCONFIGDIR=/tmp/matplotlib \ |
| 106 | + XDG_CACHE_HOME=/tmp/cache |
| 107 | + |
| 108 | +WORKDIR /opt/oceanstream/scripts/batch_processing |
| 109 | +USER oceanstream |
| 110 | + |
| 111 | +CMD ["python"] |
0 commit comments