Containerfile.lite•6.22 kB
# syntax=docker/dockerfile:1.7
###############################################################################
# MCP Gateway (lite) - OCI-compliant container build
#
# This multi-stage Dockerfile produces an ultra-slim, scratch-based runtime
# image that automatically tracks the latest Python 3.11.x patch release
# from the RHEL 9 repositories and is fully patched on each rebuild.
#
# Key design points:
# - Builder stage has full DNF + devel headers for wheel compilation
# - Runtime stage is scratch: only the Python runtime and app
# - Both builder and runtime rootfs receive `dnf upgrade -y`
# - Development headers are dropped from the final image
# - Hadolint DL3041 is suppressed to allow "latest patch" RPM usage
###############################################################################
###########################
# Build-time arguments
###########################
# Temporary dir for assembling the scratch rootfs
ARG ROOTFS_PATH=/tmp/rootfs
# Python major.minor series to track
ARG PYTHON_VERSION=3.11
###########################
# Base image for copying into scratch
###########################
FROM registry.access.redhat.com/ubi9/ubi-micro:9.6-1751962311 AS base
###########################
# Builder stage
###########################
FROM registry.access.redhat.com/ubi9/ubi:9.6-1751897624 AS builder
SHELL ["/bin/bash", "-c"]
ARG PYTHON_VERSION
ARG ROOTFS_PATH
# ----------------------------------------------------------------------------
# 1) Patch the OS
# 2) Install Python + headers for building wheels
# 3) Register python3 alternative
# 4) Clean caches to reduce layer size
# ----------------------------------------------------------------------------
# hadolint ignore=DL3041
RUN set -euo pipefail \
&& dnf upgrade -y \
&& dnf install -y \
python${PYTHON_VERSION} \
python${PYTHON_VERSION}-devel \
&& update-alternatives --install /usr/bin/python3 python3 /usr/bin/python${PYTHON_VERSION} 1 \
&& dnf clean all
WORKDIR /app
# Copy project source last so small code changes don't bust earlier caches
COPY . /app
# ----------------------------------------------------------------------------
# Create and populate virtual environment
# - Upgrade pip, setuptools, wheel, pdm, uv
# - Install project dependencies and package
# - Remove build caches
# ----------------------------------------------------------------------------
RUN set -euo pipefail \
&& python3 -m venv /app/.venv \
&& /app/.venv/bin/pip install --no-cache-dir --upgrade pip setuptools wheel pdm uv \
&& /app/.venv/bin/uv pip install ".[redis,postgres]" \
&& rm -rf /root/.cache /var/cache/dnf
# ----------------------------------------------------------------------------
# Build a minimal, fully-patched rootfs containing only the runtime Python
# ----------------------------------------------------------------------------
# hadolint ignore=DL3041
RUN set -euo pipefail \
&& mkdir -p "${ROOTFS_PATH}" \
&& dnf --installroot="${ROOTFS_PATH}" --releasever=9 upgrade -y \
&& dnf --installroot="${ROOTFS_PATH}" --releasever=9 install -y \
--setopt=install_weak_deps=0 \
python${PYTHON_VERSION} \
&& dnf clean all --installroot="${ROOTFS_PATH}"
# ----------------------------------------------------------------------------
# Create `python3` symlink in the rootfs for compatibility
# ----------------------------------------------------------------------------
RUN ln -s /usr/bin/python${PYTHON_VERSION} ${ROOTFS_PATH}/usr/bin/python3
# ----------------------------------------------------------------------------
# Copy application directory into the rootfs and fix permissions for non-root
# ----------------------------------------------------------------------------
RUN cp -r /app ${ROOTFS_PATH}/app \
&& chown -R 1001:0 ${ROOTFS_PATH}/app \
&& chmod -R g=u ${ROOTFS_PATH}/app
###########################
# Final runtime (squashed)
###########################
FROM scratch AS runtime
ARG PYTHON_VERSION
ARG ROOTFS_PATH
# ----------------------------------------------------------------------------
# OCI image metadata
# ----------------------------------------------------------------------------
LABEL maintainer="Mihai Criveti" \
org.opencontainers.image.title="mcp/mcpgateway" \
org.opencontainers.image.description="MCP Gateway: An enterprise-ready Model Context Protocol Gateway" \
org.opencontainers.image.licenses="Apache-2.0" \
org.opencontainers.image.version="0.3.1"
# ----------------------------------------------------------------------------
# Copy the entire prepared root filesystem from the builder stage
# ----------------------------------------------------------------------------
COPY --from=builder ${ROOTFS_PATH}/ /
# ----------------------------------------------------------------------------
# Ensure our virtual environment binaries have priority in PATH
# ----------------------------------------------------------------------------
ENV PATH="/app/.venv/bin:${PATH}"
# ----------------------------------------------------------------------------
# Application working directory
# ----------------------------------------------------------------------------
WORKDIR /app
# ----------------------------------------------------------------------------
# Expose application port
# ----------------------------------------------------------------------------
EXPOSE 4444
# ----------------------------------------------------------------------------
# Run as non-root user (1001)
# ----------------------------------------------------------------------------
USER 1001
# ----------------------------------------------------------------------------
# Health check
# ----------------------------------------------------------------------------
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
CMD ["python3", "-c", "import httpx,sys;sys.exit(0 if httpx.get('http://localhost:4444/health',timeout=5).status_code==200 else 1)"]
# ----------------------------------------------------------------------------
# Entrypoint
# ----------------------------------------------------------------------------
CMD ["./run-gunicorn.sh"]