Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ include:

.images_matrix:
- DOCKERFILE_RELPATH: "geolab-base"
DOCKER_EXTRA_OPTIONS: "--build-arg IMAGE_AUTHORS=geolab@earthscope.org --build-arg PYTHON_VERSION=3.12"
DOCKER_EXTRA_OPTIONS: "--build-arg IMAGE_AUTHORS=geolab@earthscope.org --build-arg PYTHON_VERSION=3.12 --build-arg GEOLAB_VERSION=${IMAGE_VERSION}"
#- DOCKERFILE_RELPATH: "geolab-gpu"


variables:
CONTAINER_REGISTRY_PLATFORM: "AWS-PUB"
DOCKERFILE_RELPATH_IS_IMAGE_NAME: "true"
GITLAB_HOSTED_RUNNER_SIZE: "saas-linux-medium-amd64"

GEOLAB_VERSION: ""
20 changes: 20 additions & 0 deletions geolab-base/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Changelog

All notable changes to this project will be documented in this file.

## [1.0.1]

### Added

- pin base image to pangeo-base:04bb14b
- add geolab-base version as ENV GEOLAB_VERSION (must be manually edited)
- add graphviz package
- add pygraphviz package
- add ipycytoscape
- added tests for new packages

### Changed

- removed test_packages.py
- moved test_notebook functions to test_helpers.py module to make it easier for users to import when writing tests
- updated test_notebook.ipynb to use test_helpers functions
13 changes: 10 additions & 3 deletions geolab-base/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,28 @@
# docker build --platform linux/amd64 \
# --build-arg IMAGE_TITLE=my-geolab-image \
# --build-arg IMAGE_AUTHORS=you@university.edu \
# --build-arg GEOLAB_VERSION=1.0.0 \
# -t my-geolab-image .
# ──────────────────────────────────────────────────────────────
FROM pangeo/base-image:latest
# Changing this tag is a major (breaking) change under semantic versioning.
FROM pangeo/base-image:04bb14b


ARG IMAGE_TITLE="custom-geolab-image" # default if user passes nothing
ARG IMAGE_AUTHORS="NoSpecifiedAuthors" # default if user passes nothing
ARG GEOLAB_VERSION # no default; must be passed with --build-arg

RUN test -n "$GEOLAB_VERSION" || (echo "GEOLAB_VERSION must not be empty" >&2 && exit 1)

LABEL org.opencontainers.image.title="${IMAGE_TITLE}" \
org.opencontainers.image.authors="${IMAGE_AUTHORS}"
org.opencontainers.image.authors="${IMAGE_AUTHORS}" \
org.opencontainers.image.version="${GEOLAB_VERSION}"

# Set locations of PROJ/GDAL resource directories
ENV PROJ_DATA=/srv/conda/envs/notebook/share/proj \
PROJ_LIB=/srv/conda/envs/notebook/share/proj \
GDAL_DATA=/srv/conda/envs/notebook/share/gdal
GDAL_DATA=/srv/conda/envs/notebook/share/gdal \
GEOLAB_VERSION=${GEOLAB_VERSION}

# Default command for standalone use. JupyterHub spawning passes
# its own command (jupyterhub-singleuser), which start respects.
Expand Down
14 changes: 13 additions & 1 deletion geolab-base/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Steps:
- [Running the local testing image](#running-the-local-testing-image)
- [Verifying the installed packages](#verifying-the-installed-packages)
- [Building and publishing the image](#building-and-publishing-the-image)
- [Setting the version and updating the changelog](#setting-the-version-and-updating-the-changelog)
- [Building the platform image](#building-the-platform-image)
- [Publishing the platform image](#publishing-the-platform-image)
- [Running your published image in GeoLab](#running-your-published-image-in-geolab)
Expand Down Expand Up @@ -235,6 +236,16 @@ pytest test_packages.py -v

Once your configuration files are ready, you build the image locally *for the GeoLab platform* and push it to a container registry so GeoLab can access it.

### Setting the version and updating the changelog

Before building, decide on a version number for the image, following [semantic versioning](https://semver.org/) (e.g. `1.2.0`).

- Update `CHANGELOG.md` with a new entry describing what changed in this version. This must be done by hand — it is not generated automatically from commits or the build.
- Pass the same version to the build with the `GEOLAB_VERSION` build-arg (see below). The Dockerfile has no default for it, so the build fails immediately if it is omitted or empty.

> [!NOTE]
> When the official `geolab-base` image is built through GitLab CI, `GEOLAB_VERSION` is a pipeline variable (also with no default) rather than a `--build-arg` you type by hand. Set it on the "Run pipeline" page for each run, matching the `RELEASE_VERSION` you enter for the release job — leaving it blank fails the build the same way an empty `--build-arg` does locally.

### Building the platform image

The `--platform linux/amd64` flag ensures the image runs on the same platform as GeoLab regardless of your own computer architecture. Name the image using your repository username, a descriptive name and tag to track versions, such as `username/my-geolab-image:0.1.0`.
Expand All @@ -244,10 +255,11 @@ docker build --no-cache -f Dockerfile \
--platform linux/amd64 \
--build-arg IMAGE_TITLE=my-geolab-image \
--build-arg IMAGE_AUTHORS=you@university.edu \
--build-arg GEOLAB_VERSION=0.1.0 \
--tag username/my-geolab-image:0.1.0 .
```

Replace `username` with your Docker Hub username (or your registry path), `my-geolab-image` with your image name, and `0.1.0` with your version tag. The `--build-arg` values for `IMAGE_TITLE` and `IMAGE_AUTHORS` are optional but recommended for image metadata.
Replace `username` with your Docker Hub username (or your registry path), `my-geolab-image` with your image name, and `0.1.0` with your version tag. The `--build-arg` values for `IMAGE_TITLE` and `IMAGE_AUTHORS` are optional but recommended for image metadata; `GEOLAB_VERSION` is required and should match the version you added to `CHANGELOG.md` and the tag you build with. It is baked into the image as the `org.opencontainers.image.version` label and as the `GEOLAB_VERSION` environment variable inside the running container.

What does `--no-cache` do? It forces Docker to rerun build steps from scratch, ensuring a clean build when publishing.

Expand Down
1 change: 1 addition & 0 deletions geolab-base/apt.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ git
gmt-dcw
gmt-gshhg
make
nano
3 changes: 3 additions & 0 deletions geolab-base/environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ dependencies:
- distributed
# --- Visualization ---
- matplotlib-base
- graphviz
- pygraphviz
- ipycytoscape
- altair
- hvplot
- holoviews
Expand Down
4 changes: 3 additions & 1 deletion geolab-base/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ earthscope-sdk==1.6.1
earthscope-cli==1.2.0
earthscopestraintools


# --- Jupyter add-ons ---
jupyterlab_jupyterbook_navigation

# --- Geophysics ---

41 changes: 41 additions & 0 deletions geolab-base/test_helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""Helpers for smoke-testing installed packages and CLI tools."""

import importlib
import shutil
import subprocess

RESULTS = []


def reset():
"""Clear RESULTS — call before a fresh run in a long-lived kernel."""
RESULTS.clear()


def py(modname, alias=None, smoke=None):
"""Import `modname` and optionally run `smoke(mod)` as a sanity check."""
label = alias or modname
try:
mod = importlib.import_module(modname)
if smoke is not None:
smoke(mod)
version = getattr(mod, '__version__', '')
RESULTS.append((label, 'OK', str(version), ''))
except Exception as exc:
RESULTS.append((label, 'FAIL', '', f'{type(exc).__name__}: {exc}'))


def cli(cmd, version_flag='--version'):
"""Verify `cmd` is on $PATH and responds to a version flag."""
path = shutil.which(cmd)
if not path:
RESULTS.append((cmd, 'FAIL', '', 'not on $PATH'))
return
try:
r = subprocess.run([cmd, version_flag],
capture_output=True, text=True, timeout=10)
line = (r.stdout or r.stderr).strip().splitlines()
version = line[0] if line else 'on PATH'
RESULTS.append((cmd, 'OK', version[:80], ''))
except Exception as exc:
RESULTS.append((cmd, 'OK', 'on PATH', f'{type(exc).__name__}'))
Loading