diff --git a/experimental/docker_invenio_next/docker-invenio/Dockerfile b/experimental/docker_invenio_next/docker-invenio/Dockerfile new file mode 100644 index 0000000..67e542f --- /dev/null +++ b/experimental/docker_invenio_next/docker-invenio/Dockerfile @@ -0,0 +1,200 @@ +# syntax=docker/dockerfile:1 +# +# Invenio Base Docker Images +# +# Build targets: +# docker build --target builder -t inveniosoftware/almalinux:1-builder . +# docker build --target runtime -t inveniosoftware/almalinux:1-runtime . +# docker build --target debug -t inveniosoftware/almalinux:1-debug . +# +# Copyright (C) 2018-2025 CERN. +# Copyright (C) 2022 Graz University of Technology. +# Copyright (C) 2022 University of Münster. +# Copyright (C) 2023-2024 KTH Royal Institute of Technology. +# +# Invenio is free software; you can redistribute it and/or modify it +# under the terms of the MIT License; see LICENSE file for more details. + +ARG LINUX_VERSION=9 +ARG PYTHON_VERSION=3.14 +ARG NODE_VERSION=22 + +# ============================================================================= +# BASE: Common configuration shared by all variants +# ============================================================================= +FROM almalinux:${LINUX_VERSION} AS base + +ARG PYTHON_VERSION + +# Locale configuration +RUN dnf install -y glibc-langpack-en && \ + dnf clean all + +ENV LANG=en_US.UTF-8 \ + LANGUAGE=en_US:en \ + LC_ALL=en_US.UTF-8 + +# Python configuration +ENV PYTHONUNBUFFERED=1 \ + PYTHONDONTWRITEBYTECODE=1 \ + PYTHONFAULTHANDLER=1 + +# Working directory structure +ENV WORKING_DIR=/opt/invenio \ + INVENIO_INSTANCE_PATH=/opt/invenio/var/instance + +# Create invenio user (UID 1000 for compatibility with common setups) +ARG INVENIO_USER_ID=1000 +RUN useradd --uid ${INVENIO_USER_ID} --gid 0 --create-home invenio + +# Create directory structure +RUN mkdir -p ${WORKING_DIR}/src \ + ${INVENIO_INSTANCE_PATH}/data \ + ${INVENIO_INSTANCE_PATH}/archive \ + ${INVENIO_INSTANCE_PATH}/static && \ + chown -R invenio:0 ${WORKING_DIR} && \ + chmod -R g=u ${WORKING_DIR} + +WORKDIR ${WORKING_DIR}/src + +# Install uv for Python management +COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /usr/local/bin/ + +# Install Python via uv (standalone builds, works for any version) +ENV UV_PYTHON_INSTALL_DIR=/opt/python +RUN uv python install ${PYTHON_VERSION} && \ + ln -sfn $(uv python find ${PYTHON_VERSION}) /usr/local/bin/python && \ + ln -sfn $(uv python find ${PYTHON_VERSION}) /usr/local/bin/python3 + +# uv configuration +ENV UV_PYTHON=${PYTHON_VERSION} \ + UV_COMPILE_BYTECODE=1 \ + UV_LINK_MODE=copy + +# ============================================================================= +# RUNTIME: Minimal production image with only runtime dependencies +# ============================================================================= +FROM base AS runtime + +ARG TARGETARCH + +# Enable EPEL and CRB for additional packages +RUN dnf install -y dnf-plugins-core && \ + dnf config-manager --set-enabled crb && \ + dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm && \ + dnf clean all + +# Install runtime-only system libraries +# Note: These are the RUNTIME packages (no -devel suffix) +RUN --mount=type=cache,target=/var/cache/dnf,sharing=locked,id=dnf-${TARGETARCH} \ + dnf install -y --setopt=install_weak_deps=False \ + # Runtime libraries (shared objects only, no headers) + cairo \ + libffi \ + libpq \ + libxml2 \ + libxslt \ + ImageMagick-libs \ + openssl-libs \ + bzip2-libs \ + xz-libs \ + sqlite-libs \ + xmlsec1 \ + xmlsec1-openssl \ + # Fonts for PDF/image generation + dejavu-sans-fonts \ + # Git (often needed at runtime for editable installs) + git + +# Labels +LABEL org.opencontainers.image.title="Invenio Base (Runtime)" \ + org.opencontainers.image.description="Minimal runtime image for Invenio applications" \ + org.opencontainers.image.vendor="Invenio Software" \ + org.opencontainers.image.licenses="MIT" + +# ============================================================================= +# BUILDER: Full toolchain for compiling Python/Node.js packages +# ============================================================================= +FROM base AS builder + +ARG NODE_VERSION +ARG TARGETARCH + +# Enable EPEL and CRB +RUN dnf install -y dnf-plugins-core && \ + dnf config-manager --set-enabled crb && \ + dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm && \ + dnf clean all + +# Install build tools and development libraries +RUN --mount=type=cache,target=/var/cache/dnf,sharing=locked,id=dnf-${TARGETARCH} \ + dnf install -y --setopt=install_weak_deps=False \ + # Build essentials + gcc \ + gcc-c++ \ + make \ + pkgconf \ + # Development libraries (headers + static libs for compilation) + cairo-devel \ + libffi-devel \ + libpq-devel \ + libxml2-devel \ + libxslt-devel \ + ImageMagick-devel \ + openssl-devel \ + bzip2-devel \ + xz-devel \ + sqlite-devel \ + xmlsec1-devel \ + xmlsec1-openssl-devel \ + # Other build dependencies + git \ + # Fonts + dejavu-sans-fonts + +# Install Node.js with npm for asset building +RUN curl -fsSL https://rpm.nodesource.com/setup_${NODE_VERSION}.x | bash - && \ + dnf install -y --setopt=install_weak_deps=False nodejs && \ + dnf clean all && \ + rm -rf /var/cache/dnf && \ + corepack enable + +# Labels +LABEL org.opencontainers.image.title="Invenio Base (Builder)" \ + org.opencontainers.image.description="Full toolchain for building Invenio applications" \ + org.opencontainers.image.vendor="Invenio Software" \ + org.opencontainers.image.licenses="MIT" + +# ============================================================================= +# DEBUG: Runtime + debugging/inspection tools +# ============================================================================= +FROM runtime AS debug + +ARG TARGETARCH + +# Install debugging and inspection tools +RUN --mount=type=cache,target=/var/cache/dnf,sharing=locked,id=dnf-${TARGETARCH} \ + dnf install -y --allowerasing --setopt=install_weak_deps=False \ + # Process inspection + procps-ng \ + htop \ + strace \ + lsof \ + # File inspection + file \ + less \ + vim-minimal \ + # Disk/IO monitoring + iotop \ + iftop \ + # Network debugging + tcpdump \ + bind-utils \ + net-tools \ + curl \ + wget + +LABEL org.opencontainers.image.title="Invenio Base (Debug)" \ + org.opencontainers.image.description="Runtime image with debugging tools for troubleshooting" \ + org.opencontainers.image.vendor="Invenio Software" \ + org.opencontainers.image.licenses="MIT" diff --git a/experimental/docker_invenio_next/docker-invenio/Dockerfile.debian b/experimental/docker_invenio_next/docker-invenio/Dockerfile.debian new file mode 100644 index 0000000..6ffb592 --- /dev/null +++ b/experimental/docker_invenio_next/docker-invenio/Dockerfile.debian @@ -0,0 +1,184 @@ +# syntax=docker/dockerfile:1 +# +# Invenio Base Docker Images (Debian variant) +# +# Build targets: +# docker build --target builder -t inveniosoftware/debian:1-builder . +# docker build --target runtime -t inveniosoftware/debian:1-runtime . +# docker build --target debug -t inveniosoftware/debian:1-debug . +# +# Copyright (C) 2018-2025 CERN. +# +# Invenio is free software; you can redistribute it and/or modify it +# under the terms of the MIT License; see LICENSE file for more details. + +ARG PYTHON_VERSION=3.14 +ARG NODE_VERSION=22 +ARG DEBIAN_VERSION=bookworm + +# ============================================================================= +# BASE: Common configuration shared by all variants +# ============================================================================= +FROM debian:${DEBIAN_VERSION}-slim AS base + +ARG PYTHON_VERSION + +# Locale configuration +RUN apt-get update && apt-get install -y --no-install-recommends locales ca-certificates && \ + sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \ + locale-gen && \ + rm -rf /var/lib/apt/lists/* + +ENV LANG=en_US.UTF-8 \ + LANGUAGE=en_US:en \ + LC_ALL=en_US.UTF-8 + +# Python configuration +ENV PYTHONUNBUFFERED=1 \ + PYTHONDONTWRITEBYTECODE=1 \ + PYTHONFAULTHANDLER=1 + +# Working directory structure +ENV WORKING_DIR=/opt/invenio \ + INVENIO_INSTANCE_PATH=/opt/invenio/var/instance + +# Create invenio user +ARG INVENIO_USER_ID=1000 +RUN useradd --uid ${INVENIO_USER_ID} --gid 0 --create-home invenio + +# Create directory structure +RUN mkdir -p ${WORKING_DIR}/src \ + ${INVENIO_INSTANCE_PATH}/data \ + ${INVENIO_INSTANCE_PATH}/archive \ + ${INVENIO_INSTANCE_PATH}/static && \ + chown -R invenio:0 ${WORKING_DIR} && \ + chmod -R g=u ${WORKING_DIR} + +WORKDIR ${WORKING_DIR}/src + +# Install uv for Python management +COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /usr/local/bin/ + +# Install Python via uv (standalone builds, works for any version) +ENV UV_PYTHON_INSTALL_DIR=/opt/python +RUN uv python install ${PYTHON_VERSION} && \ + ln -sfn $(uv python find ${PYTHON_VERSION}) /usr/local/bin/python && \ + ln -sfn $(uv python find ${PYTHON_VERSION}) /usr/local/bin/python3 + +# uv configuration +ENV UV_PYTHON=${PYTHON_VERSION} \ + UV_COMPILE_BYTECODE=1 \ + UV_LINK_MODE=copy + +# ============================================================================= +# RUNTIME: Minimal production image with only runtime dependencies +# ============================================================================= +FROM base AS runtime + +ARG TARGETARCH + +# Install runtime-only system libraries +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=apt-cache-${TARGETARCH} \ + --mount=type=cache,target=/var/lib/apt,sharing=locked,id=apt-lib-${TARGETARCH} \ + apt-get update && apt-get install -y --no-install-recommends \ + # Runtime libraries only (no -dev packages) + libcairo2 \ + libffi8 \ + libpq5 \ + libxml2 \ + libxslt1.1 \ + libmagickwand-6.q16-6 \ + libssl3 \ + libbz2-1.0 \ + liblzma5 \ + libsqlite3-0 \ + libxmlsec1 \ + libxmlsec1-openssl \ + # Fonts + fonts-dejavu \ + # Utilities + git \ + curl + +LABEL org.opencontainers.image.title="Invenio Base Debian (Runtime)" \ + org.opencontainers.image.description="Minimal Debian-based runtime image for Invenio" \ + org.opencontainers.image.vendor="Invenio Software" \ + org.opencontainers.image.licenses="MIT" + +# ============================================================================= +# BUILDER: Full toolchain for compiling Python/Node.js packages +# ============================================================================= +FROM base AS builder + +ARG NODE_VERSION +ARG TARGETARCH + +# Install build tools and development libraries +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=apt-cache-${TARGETARCH} \ + --mount=type=cache,target=/var/lib/apt,sharing=locked,id=apt-lib-${TARGETARCH} \ + apt-get update && apt-get install -y --no-install-recommends \ + # Build essentials + build-essential \ + pkg-config \ + # Development libraries (with headers) + libcairo2-dev \ + libffi-dev \ + libpq-dev \ + libxml2-dev \ + libxslt1-dev \ + libmagickwand-dev \ + libssl-dev \ + libbz2-dev \ + liblzma-dev \ + libsqlite3-dev \ + libxmlsec1-dev \ + libxmlsec1-openssl \ + # Other + git \ + curl \ + # Fonts + fonts-dejavu + +# Install Node.js +RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash - && \ + apt-get install -y --no-install-recommends nodejs && \ + corepack enable && \ + rm -rf /var/lib/apt/lists/* + +LABEL org.opencontainers.image.title="Invenio Base Debian (Builder)" \ + org.opencontainers.image.description="Full Debian-based toolchain for building Invenio" \ + org.opencontainers.image.vendor="Invenio Software" \ + org.opencontainers.image.licenses="MIT" + +# ============================================================================= +# DEBUG: Runtime + debugging tools +# ============================================================================= +FROM runtime AS debug + +ARG TARGETARCH + +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=apt-cache-${TARGETARCH} \ + --mount=type=cache,target=/var/lib/apt,sharing=locked,id=apt-lib-${TARGETARCH} \ + apt-get update && apt-get install -y --no-install-recommends \ + # Process inspection + procps \ + htop \ + strace \ + lsof \ + # File inspection + file \ + less \ + vim-tiny \ + # Network debugging + tcpdump \ + dnsutils \ + net-tools \ + wget \ + # I/O monitoring + iotop \ + iftop + +LABEL org.opencontainers.image.title="Invenio Base Debian (Debug)" \ + org.opencontainers.image.description="Debian runtime with debugging tools" \ + org.opencontainers.image.vendor="Invenio Software" \ + org.opencontainers.image.licenses="MIT" diff --git a/experimental/docker_invenio_next/docker-invenio/Makefile b/experimental/docker_invenio_next/docker-invenio/Makefile new file mode 100644 index 0000000..df9f662 --- /dev/null +++ b/experimental/docker_invenio_next/docker-invenio/Makefile @@ -0,0 +1,141 @@ +# Invenio Base Images - Build Makefile +# +# Usage: +# make all # Build all AlmaLinux variants +# make all-debian # Build all Debian variants +# make runtime # Build only runtime variant +# make push # Push all variants to registry + +REGISTRY ?= registry.cern.ch/inveniosoftware +VERSION ?= 1 +PYTHON_VERSION ?= 3.14 +NODE_VERSION ?= 22 + +# Platform: default to linux/amd64 for consistency with production +# Override with: make PLATFORM=linux/arm64 runtime +PLATFORM ?= linux/amd64 + +# AlmaLinux variants +ALMA_IMAGE = $(REGISTRY)/almalinux +ALMA_TARGETS = builder runtime debug + +# Debian variants +DEBIAN_IMAGE = $(REGISTRY)/debian +DEBIAN_TARGETS = builder runtime debug + +.PHONY: all all-debian clean push push-debian help + +# Default: build all AlmaLinux variants +all: $(ALMA_TARGETS) + +all-debian: $(addprefix debian-,$(DEBIAN_TARGETS)) + +# AlmaLinux builds +builder: + docker build \ + --platform $(PLATFORM) \ + --target builder \ + --build-arg PYTHON_VERSION=$(PYTHON_VERSION) \ + --build-arg NODE_VERSION=$(NODE_VERSION) \ + -t $(ALMA_IMAGE):$(VERSION)-builder \ + -f Dockerfile . + +runtime: + docker build \ + --platform $(PLATFORM) \ + --target runtime \ + --build-arg PYTHON_VERSION=$(PYTHON_VERSION) \ + --build-arg NODE_VERSION=$(NODE_VERSION) \ + -t $(ALMA_IMAGE):$(VERSION)-runtime \ + -t $(ALMA_IMAGE):$(VERSION) \ + -f Dockerfile . + +debug: + docker build \ + --platform $(PLATFORM) \ + --target debug \ + --build-arg PYTHON_VERSION=$(PYTHON_VERSION) \ + --build-arg NODE_VERSION=$(NODE_VERSION) \ + -t $(ALMA_IMAGE):$(VERSION)-debug \ + -f Dockerfile . + +# Debian builds +debian-builder: + docker build \ + --platform $(PLATFORM) \ + --target builder \ + --build-arg PYTHON_VERSION=$(PYTHON_VERSION) \ + --build-arg NODE_VERSION=$(NODE_VERSION) \ + -t $(DEBIAN_IMAGE):$(VERSION)-builder \ + -f Dockerfile.debian . + +debian-runtime: + docker build \ + --platform $(PLATFORM) \ + --target runtime \ + --build-arg PYTHON_VERSION=$(PYTHON_VERSION) \ + --build-arg NODE_VERSION=$(NODE_VERSION) \ + -t $(DEBIAN_IMAGE):$(VERSION)-runtime \ + -t $(DEBIAN_IMAGE):$(VERSION) \ + -f Dockerfile.debian . + +debian-debug: + docker build \ + --platform $(PLATFORM) \ + --target debug \ + --build-arg PYTHON_VERSION=$(PYTHON_VERSION) \ + --build-arg NODE_VERSION=$(NODE_VERSION) \ + -t $(DEBIAN_IMAGE):$(VERSION)-debug \ + -f Dockerfile.debian . + +# Push to registry +push: all + docker push $(ALMA_IMAGE):$(VERSION)-builder + docker push $(ALMA_IMAGE):$(VERSION)-runtime + docker push $(ALMA_IMAGE):$(VERSION)-debug + docker push $(ALMA_IMAGE):$(VERSION) + +push-debian: all-debian + docker push $(DEBIAN_IMAGE):$(VERSION)-builder + docker push $(DEBIAN_IMAGE):$(VERSION)-runtime + docker push $(DEBIAN_IMAGE):$(VERSION)-debug + docker push $(DEBIAN_IMAGE):$(VERSION) + +# Show image sizes +sizes: + @echo "=== AlmaLinux variants ===" + @docker images $(ALMA_IMAGE) --format "table {{.Tag}}\t{{.Size}}" + @echo "" + @echo "=== Debian variants ===" + @docker images $(DEBIAN_IMAGE) --format "table {{.Tag}}\t{{.Size}}" + +clean: + docker rmi $(ALMA_IMAGE):$(VERSION)-builder || true + docker rmi $(ALMA_IMAGE):$(VERSION)-runtime || true + docker rmi $(ALMA_IMAGE):$(VERSION)-debug || true + docker rmi $(ALMA_IMAGE):$(VERSION) || true + docker rmi $(DEBIAN_IMAGE):$(VERSION)-builder || true + docker rmi $(DEBIAN_IMAGE):$(VERSION)-runtime || true + docker rmi $(DEBIAN_IMAGE):$(VERSION)-debug || true + docker rmi $(DEBIAN_IMAGE):$(VERSION) || true + +help: + @echo "Invenio Base Image Builder" + @echo "" + @echo "Targets:" + @echo " all Build all AlmaLinux variants (builder, runtime, debug)" + @echo " all-debian Build all Debian variants" + @echo " builder Build AlmaLinux builder image" + @echo " runtime Build AlmaLinux runtime image" + @echo " debug Build AlmaLinux debug image" + @echo " push Push AlmaLinux images to registry" + @echo " push-debian Push Debian images to registry" + @echo " sizes Show image sizes" + @echo " clean Remove all built images" + @echo "" + @echo "Variables:" + @echo " REGISTRY=$(REGISTRY)" + @echo " VERSION=$(VERSION)" + @echo " PLATFORM=$(PLATFORM)" + @echo " PYTHON_VERSION=$(PYTHON_VERSION)" + @echo " NODE_VERSION=$(NODE_VERSION)" diff --git a/experimental/docker_invenio_next/docker-invenio/docker-bake.hcl b/experimental/docker_invenio_next/docker-invenio/docker-bake.hcl new file mode 100644 index 0000000..da7d43a --- /dev/null +++ b/experimental/docker_invenio_next/docker-invenio/docker-bake.hcl @@ -0,0 +1,137 @@ +// docker-bake.hcl +// +// Build all variants in parallel: +// docker buildx bake +// +// Build specific variant: +// docker buildx bake almalinux-runtime +// +// Build and push: +// docker buildx bake --push + +variable "REGISTRY" { + default = "registry.cern.ch/inveniosoftware" +} + +variable "VERSION" { + default = "1" +} + +variable "PYTHON_VERSION" { + default = "3.12" +} + +variable "NODE_VERSION" { + default = "22" +} + +// Groups for building multiple targets at once +group "default" { + targets = ["almalinux-builder", "almalinux-runtime", "almalinux-debug"] +} + +group "almalinux" { + targets = ["almalinux-builder", "almalinux-runtime", "almalinux-debug"] +} + +group "debian" { + targets = ["debian-builder", "debian-runtime", "debian-debug"] +} + +group "all" { + targets = [ + "almalinux-builder", "almalinux-runtime", "almalinux-debug", + "debian-builder", "debian-runtime", "debian-debug" + ] +} + +// AlmaLinux variants +target "almalinux-builder" { + dockerfile = "Dockerfile" + target = "builder" + tags = ["${REGISTRY}/almalinux:${VERSION}-builder"] + args = { + PYTHON_VERSION = "${PYTHON_VERSION}" + NODE_VERSION = "${NODE_VERSION}" + } + cache-from = ["type=registry,ref=${REGISTRY}/almalinux:cache-builder"] + cache-to = ["type=registry,ref=${REGISTRY}/almalinux:cache-builder,mode=max"] +} + +target "almalinux-runtime" { + dockerfile = "Dockerfile" + target = "runtime" + tags = [ + "${REGISTRY}/almalinux:${VERSION}-runtime", + "${REGISTRY}/almalinux:${VERSION}", + "${REGISTRY}/almalinux:latest" + ] + args = { + PYTHON_VERSION = "${PYTHON_VERSION}" + NODE_VERSION = "${NODE_VERSION}" + } + cache-from = ["type=registry,ref=${REGISTRY}/almalinux:cache-runtime"] + cache-to = ["type=registry,ref=${REGISTRY}/almalinux:cache-runtime,mode=max"] +} + +target "almalinux-debug" { + dockerfile = "Dockerfile" + target = "debug" + tags = ["${REGISTRY}/almalinux:${VERSION}-debug"] + args = { + PYTHON_VERSION = "${PYTHON_VERSION}" + NODE_VERSION = "${NODE_VERSION}" + } + // Debug builds on top of runtime, so share cache + cache-from = ["type=registry,ref=${REGISTRY}/almalinux:cache-runtime"] +} + +// Debian variants +target "debian-builder" { + dockerfile = "Dockerfile.debian" + target = "builder" + tags = ["${REGISTRY}/debian:${VERSION}-builder"] + args = { + PYTHON_VERSION = "${PYTHON_VERSION}" + NODE_VERSION = "${NODE_VERSION}" + } + cache-from = ["type=registry,ref=${REGISTRY}/debian:cache-builder"] + cache-to = ["type=registry,ref=${REGISTRY}/debian:cache-builder,mode=max"] +} + +target "debian-runtime" { + dockerfile = "Dockerfile.debian" + target = "runtime" + tags = [ + "${REGISTRY}/debian:${VERSION}-runtime", + "${REGISTRY}/debian:${VERSION}" + ] + args = { + PYTHON_VERSION = "${PYTHON_VERSION}" + NODE_VERSION = "${NODE_VERSION}" + } + cache-from = ["type=registry,ref=${REGISTRY}/debian:cache-runtime"] + cache-to = ["type=registry,ref=${REGISTRY}/debian:cache-runtime,mode=max"] +} + +target "debian-debug" { + dockerfile = "Dockerfile.debian" + target = "debug" + tags = ["${REGISTRY}/debian:${VERSION}-debug"] + args = { + PYTHON_VERSION = "${PYTHON_VERSION}" + NODE_VERSION = "${NODE_VERSION}" + } + cache-from = ["type=registry,ref=${REGISTRY}/debian:cache-runtime"] +} + +// Multi-platform builds (optional, for ARM support) +target "almalinux-runtime-multiarch" { + inherits = ["almalinux-runtime"] + platforms = ["linux/amd64", "linux/arm64"] +} + +target "debian-runtime-multiarch" { + inherits = ["debian-runtime"] + platforms = ["linux/amd64", "linux/arm64"] +} diff --git a/experimental/docker_invenio_next/zenodo-rdm/Dockerfile b/experimental/docker_invenio_next/zenodo-rdm/Dockerfile new file mode 100644 index 0000000..f819f53 --- /dev/null +++ b/experimental/docker_invenio_next/zenodo-rdm/Dockerfile @@ -0,0 +1,165 @@ +# syntax=docker/dockerfile:1 +# +# Zenodo Production Dockerfile +# +# Uses multi-stage build with Invenio base images: +# - Builder stage: compiles Python wheels, builds frontend assets +# - Runtime stage: minimal production image +# +# Note: XRootD (CERN storage) is only available for amd64, so this image +# must be built with --platform=linux/amd64. +# +# Build: +# docker build --platform=linux/amd64 -t zenodo:latest . +# +# Build with specific options: +# docker build --platform=linux/amd64 \ +# --build-arg XROOTD_VERSION=5.9.1 \ +# --build-arg SENTRY_RELEASE=$(git rev-parse HEAD) \ +# -t zenodo:$(git rev-parse --short HEAD) . + +# Global ARGs (available in all stages) +ARG INVENIO_BASE_VERSION=1 +ARG REGISTRY=registry.cern.ch/inveniosoftware +ARG XROOTD_VERSION=5.9.1 + +# ============================================================================= +# STAGE 1: Build Python wheels and frontend assets +# ============================================================================= +FROM ${REGISTRY}/almalinux:${INVENIO_BASE_VERSION}-builder AS builder + +# Re-declare ARG after FROM to use in this stage +ARG XROOTD_VERSION + +# ---- Build dependencies (combined for fewer layers) ---- +# - cmake, libuuid-devel: build xrootd Python bindings from PyPI +# - krb5-devel: build kerberos bindings +# - vips-devel: image processing +# - xrootd-client-*: C libraries to link against +RUN dnf config-manager --add-repo https://cern.ch/xrootd/xrootd.repo && \ + dnf install -y http://rpms.remirepo.net/enterprise/remi-release-9.rpm && \ + dnf install -y \ + cmake \ + krb5-devel \ + libuuid-devel \ + vips-devel \ + xrootd-client-devel-${XROOTD_VERSION} \ + xrootd-client-libs-${XROOTD_VERSION} && \ + dnf clean all + +# ---- Python and uv configuration ---- +ENV PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 \ + UV_CACHE_DIR=/opt/.cache/uv \ + UV_COMPILE_BYTECODE=1 \ + UV_FROZEN=1 \ + UV_LINK_MODE=copy \ + UV_REQUIRE_HASHES=1 \ + UV_VERIFY_HASHES=1 + +# ---- Build Python dependencies ---- +ARG BUILD_EXTRAS="--extra sentry --extra xrootd" + +# Install dependencies (not the workspace packages yet) +# Using bind mounts avoids creating a layer for pyproject.toml/uv.lock +RUN --mount=type=cache,target=/opt/.cache/uv \ + --mount=type=bind,source=uv.lock,target=uv.lock \ + --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ + uv sync --no-dev --no-install-workspace --no-editable ${BUILD_EXTRAS} \ + --no-install-package=xrootd + +# Add venv to PATH for subsequent commands +ENV PATH="${WORKING_DIR}/src/.venv/bin:${PATH}" + +# Build xrootd from PyPI BEFORE copying source (slow step, rarely changes) +# Must link against system xrootd-client libs installed above +RUN UV_REQUIRE_HASHES=0 uv pip install --no-cache xrootd==${XROOTD_VERSION} + +# Copy source code +COPY . . + +# Install workspace packages (zenodo-rdm, zenodo-legacy) +RUN --mount=type=cache,target=/opt/.cache/uv \ + uv sync --frozen --no-dev ${BUILD_EXTRAS} \ + --no-install-package=xrootd + +# Disable uv cache for subsequent commands (filesystem permission reasons) +ENV UV_NO_CACHE=1 + +# ---- Build frontend assets ---- +# Copy static files and assets BEFORE invenio collect +# webpack buildall = create + install + build +RUN --mount=type=cache,target=/root/.npm \ + cp -r ./static/. ${INVENIO_INSTANCE_PATH}/static/ && \ + cp -r ./assets/. ${INVENIO_INSTANCE_PATH}/assets/ && \ + invenio collect --verbose && \ + invenio webpack buildall + +# ============================================================================= +# STAGE 2: Production runtime image +# ============================================================================= +FROM ${REGISTRY}/almalinux:${INVENIO_BASE_VERSION}-runtime AS production + +# Re-declare ARG after FROM to use in this stage +ARG XROOTD_VERSION + +# ---- Runtime dependencies (combined for fewer layers) ---- +# - krb5-*: Kerberos authentication +# - vips: image processing (libs only, no -devel) +# - xrootd-client-*: CERN storage client +RUN dnf config-manager --add-repo https://cern.ch/xrootd/xrootd.repo && \ + dnf install -y http://rpms.remirepo.net/enterprise/remi-release-9.rpm && \ + dnf install -y \ + krb5-libs \ + krb5-workstation \ + vips \ + xrootd-client-${XROOTD_VERSION} \ + xrootd-client-libs-${XROOTD_VERSION} && \ + dnf clean all && \ + rm -rf /var/cache/dnf + +# ---- Copy configuration files ---- +COPY ./krb5.conf /etc/krb5.conf + +# ---- Copy Python environment from builder ---- +COPY --from=builder ${WORKING_DIR}/src/.venv ${WORKING_DIR}/src/.venv +ENV PATH="${WORKING_DIR}/src/.venv/bin:${PATH}" + +# ---- Copy application code ---- +COPY --chown=invenio:0 legacy ./legacy +COPY --chown=invenio:0 site ./site + +# ---- Copy instance configuration ---- +COPY --chown=invenio:0 ./app_data/ ${INVENIO_INSTANCE_PATH}/app_data/ +COPY --chown=invenio:0 ./docker/uwsgi/ ${INVENIO_INSTANCE_PATH} +COPY --chown=invenio:0 ./invenio.cfg ${INVENIO_INSTANCE_PATH} +COPY --chown=invenio:0 ./templates/ ${INVENIO_INSTANCE_PATH}/templates/ +COPY --chown=invenio:0 ./translations ${INVENIO_INSTANCE_PATH}/translations + +# ---- Copy built static assets from builder ---- +COPY --from=builder --chown=invenio:0 ${INVENIO_INSTANCE_PATH}/static ${INVENIO_INSTANCE_PATH}/static +COPY --from=builder --chown=invenio:0 ${WORKING_DIR}/src/static ./static + +# ---- Build metadata ---- +ARG IMAGE_BUILD_TIMESTAMP +ARG SENTRY_RELEASE + +ENV INVENIO_IMAGE_BUILD_TIMESTAMP="'${IMAGE_BUILD_TIMESTAMP}'" \ + SENTRY_RELEASE=${SENTRY_RELEASE} + +# ---- Labels ---- +LABEL org.opencontainers.image.title="Zenodo" \ + org.opencontainers.image.description="Zenodo Research Data Repository" \ + org.opencontainers.image.source="https://github.com/zenodo/zenodo-rdm" \ + org.opencontainers.image.vendor="CERN" \ + org.opencontainers.image.revision="${SENTRY_RELEASE}" + +# ---- Runtime configuration ---- +USER invenio +WORKDIR ${WORKING_DIR}/src +EXPOSE 5000 + +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ + CMD curl -f http://localhost:5000/ping || exit 1 + +ENTRYPOINT ["bash", "-l"] diff --git a/experimental/docker_invenio_next/zenodo-rdm/Makefile b/experimental/docker_invenio_next/zenodo-rdm/Makefile new file mode 100644 index 0000000..5aa36fd --- /dev/null +++ b/experimental/docker_invenio_next/zenodo-rdm/Makefile @@ -0,0 +1,116 @@ +# Zenodo Docker Image Build +# +# Usage: +# make build # Build production image +# make build-no-cache # Build without cache +# make push # Push to registry + +REGISTRY ?= registry.cern.ch/zenodo +IMAGE_NAME ?= zenodo-rdm +VERSION ?= $(shell git rev-parse --short HEAD) +FULL_VERSION ?= $(shell git describe --tags --always) + +# Build timestamp for tracking +BUILD_TIMESTAMP := $(shell date -u +"%Y-%m-%dT%H:%M:%SZ") + +# Invenio base image settings +INVENIO_REGISTRY ?= registry.cern.ch/inveniosoftware +INVENIO_BASE_VERSION ?= 1 + +# XRootD version (5.9.1+ required for Python 3.14) +XROOTD_VERSION ?= 5.9.1 + +# Platform: XRootD only available for amd64 +PLATFORM ?= linux/amd64 + +.PHONY: build build-no-cache push run shell test clean help + +build: + docker build \ + --platform $(PLATFORM) \ + --build-arg INVENIO_BASE_VERSION=$(INVENIO_BASE_VERSION) \ + --build-arg REGISTRY=$(INVENIO_REGISTRY) \ + --build-arg XROOTD_VERSION=$(XROOTD_VERSION) \ + --build-arg IMAGE_BUILD_TIMESTAMP="$(BUILD_TIMESTAMP)" \ + --build-arg SENTRY_RELEASE="$(FULL_VERSION)" \ + -t $(REGISTRY)/$(IMAGE_NAME):$(VERSION) \ + -t $(REGISTRY)/$(IMAGE_NAME):latest \ + . + +build-no-cache: + docker build --no-cache \ + --platform $(PLATFORM) \ + --build-arg INVENIO_BASE_VERSION=$(INVENIO_BASE_VERSION) \ + --build-arg REGISTRY=$(INVENIO_REGISTRY) \ + --build-arg XROOTD_VERSION=$(XROOTD_VERSION) \ + --build-arg IMAGE_BUILD_TIMESTAMP="$(BUILD_TIMESTAMP)" \ + --build-arg SENTRY_RELEASE="$(FULL_VERSION)" \ + -t $(REGISTRY)/$(IMAGE_NAME):$(VERSION) \ + -t $(REGISTRY)/$(IMAGE_NAME):latest \ + . + +# Build using the debug base image (for troubleshooting) +build-debug: + docker build \ + --platform $(PLATFORM) \ + --build-arg INVENIO_BASE_VERSION=$(INVENIO_BASE_VERSION)-debug \ + --build-arg REGISTRY=$(INVENIO_REGISTRY) \ + --build-arg XROOTD_VERSION=$(XROOTD_VERSION) \ + --build-arg IMAGE_BUILD_TIMESTAMP="$(BUILD_TIMESTAMP)" \ + --build-arg SENTRY_RELEASE="$(FULL_VERSION)" \ + -t $(REGISTRY)/$(IMAGE_NAME):$(VERSION)-debug \ + . + +push: + docker push $(REGISTRY)/$(IMAGE_NAME):$(VERSION) + docker push $(REGISTRY)/$(IMAGE_NAME):latest + +# Local development helpers +run: + docker run -it --rm \ + -p 5000:5000 \ + -v $(PWD)/invenio.cfg:/opt/invenio/var/instance/invenio.cfg:ro \ + $(REGISTRY)/$(IMAGE_NAME):latest + +shell: + docker run -it --rm \ + -v $(PWD):/opt/invenio/src \ + $(REGISTRY)/$(IMAGE_NAME):latest \ + bash + +# Show final image size and layers +inspect: + @echo "=== Image Size ===" + @docker images $(REGISTRY)/$(IMAGE_NAME):$(VERSION) --format "{{.Size}}" + @echo "" + @echo "=== Layer History ===" + @docker history $(REGISTRY)/$(IMAGE_NAME):$(VERSION) + +# Security scan with trivy +scan: + trivy image $(REGISTRY)/$(IMAGE_NAME):$(VERSION) + +clean: + docker rmi $(REGISTRY)/$(IMAGE_NAME):$(VERSION) || true + docker rmi $(REGISTRY)/$(IMAGE_NAME):latest || true + docker rmi $(REGISTRY)/$(IMAGE_NAME):$(VERSION)-debug || true + +help: + @echo "Zenodo Docker Build" + @echo "" + @echo "Targets:" + @echo " build Build production image" + @echo " build-no-cache Build without Docker cache" + @echo " build-debug Build with debug base (includes htop, strace, etc.)" + @echo " push Push to registry" + @echo " run Run container locally" + @echo " shell Open shell in container" + @echo " inspect Show image size and layers" + @echo " scan Security scan with trivy" + @echo " clean Remove built images" + @echo "" + @echo "Current settings:" + @echo " VERSION=$(VERSION)" + @echo " FULL_VERSION=$(FULL_VERSION)" + @echo " INVENIO_BASE_VERSION=$(INVENIO_BASE_VERSION)" + @echo " XROOTD_VERSION=$(XROOTD_VERSION)"