Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
62 changes: 62 additions & 0 deletions .github/workflows/docker-publish.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: Publish Docker image to GHCR

on:
repository_dispatch:
types: [build]
workflow_dispatch:

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

jobs:
build-and-push-docker-image:
runs-on: ubuntu-25.10
permissions:
contents: read
packages: write # Required to push images to GHCR

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Fetch external versions and build date
id: vars
shell: bash
run: |
echo "date=$(date -u +'%Y-%m-%d')" >> $GITHUB_OUTPUT
echo "schema=$(gh release view --repo CCPBioSim/biosim-schema --json tagName --template '{{.tagName}}')" >> $GITHUB_OUTPUT
echo "extractor=$(gh release view --repo CCPBioSim/biosim-extractor --json tagName --template '{{.tagName}}')" >> $GITHUB_OUTPUT
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.repository_owner }}
password: ${{ secrets.BUILD_TOKEN }}

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=raw,value=latest,enable={{is_default_branch}}
type=sha
labels: |
org.opencontainers.image.created=${{ steps.vars.outputs.date }}
biosim.schema.version=${{ steps.vars.outputs.schema }}
biosim.extractor.version=${{ steps.vars.outputs.extractor }}

- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
file: ./docker/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
12 changes: 6 additions & 6 deletions biosimdb_interface/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ def create_app(test_config=None):
UPLOAD_FOLDER=os.getenv("UPLOAD_FOLDER", "/tmp"), # App specific
CLIENT_ID=os.getenv("CLIENT_ID", ""),
CLIENT_SECRET=os.getenv("CLIENT_SECRET", ""),
AUTH_URL=os.getenv("AUTH_URL"),
TOKEN_URL=os.getenv("TOKEN_URL"),
BASE_URL=os.getenv("BASE_URL"),
API_BASE=os.getenv("API_BASE"),
REDIRECT_URI=os.getenv("REDIRECT_URI"),
AUTH_URL=os.getenv("AUTH_URL", ""),
TOKEN_URL=os.getenv("TOKEN_URL", ""),
BASE_URL=os.getenv("BASE_URL", ""),
API_BASE=os.getenv("API_BASE", ""),
REDIRECT_URI=os.getenv("REDIRECT_URI", ""),
SCOPES=os.getenv("SCOPES", "").strip(),
) # invenio app configs

Expand All @@ -61,7 +61,7 @@ def create_app(test_config=None):

@app.context_processor
def inject_base_url():
return {"BASE_URL": app.config.get("BASE_URL", "")}
return {"BASE_URL": app.config.get("BASE_URL") or ""}

# ensure the instance folder exists
try:
Expand Down
4 changes: 2 additions & 2 deletions biosimdb_interface/schema/webform.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ def get_simulation_metadata():
dict: Parsed simulation metadata schema.
"""
path = os.getenv("WEBFORM_SCHEMA_PATH")
if not path:
# Return an empty schema or raise a more descriptive error if preferred
if not path or not os.path.exists(path):
# Return an empty schema
return {}

mtime = os.path.getmtime(path)
Expand Down
99 changes: 84 additions & 15 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,25 +1,94 @@
FROM python:3.12-slim
# Stage 1: Fetch Schema Artifacts
FROM ubuntu:25.10 AS schema-fetcher

WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends curl jq tar ca-certificates \
&& rm -rf /var/lib/apt/lists/* \
&& apt-get clean

WORKDIR /tmp

RUN TAG=$(curl -fsSL https://api.github.com/repos/CCPBioSim/biosim-schema/releases/latest | jq -r .tag_name) && \
curl -fsSL -o artifacts.tar.gz \
"https://github.com/CCPBioSim/biosim-schema/releases/download/${TAG}/biosim-schema-artifacts.tar.gz" && \
mkdir -p /opt/biosim-schema && \
tar -xzf artifacts.tar.gz -C /opt/biosim-schema


# Stage 2: Build Python dependencies
FROM ubuntu:25.10 AS builder

ENV DEBIAN_FRONTEND=noninteractive \
PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1

# Install build dependencies for MDAnalysis
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
g++ \
python3 \
python3-pip \
python3-venv \
python3-dev \
build-essential \
libgomp1 \
&& rm -rf /var/lib/apt/lists/*

# Install the package
COPY pyproject.toml .
COPY README.md .
COPY LICENSE .
# Create virtual environment
RUN python3 -m venv /venv

# Activate venv and install dependencies
ENV PATH="/venv/bin:$PATH"

WORKDIR /app

COPY pyproject.toml README.md LICENSE ./
COPY biosimdb_interface/ biosimdb_interface/
RUN pip install --no-cache-dir .

# Copy schema files at a known path (mounted at runtime for dev — see below)
# COPY ../biosim-schema /biosim-schema
# Install application and its dependencies into the venv
RUN pip install --upgrade pip setuptools && \
pip install --no-cache-dir gunicorn .


# Stage 3: Runtime
FROM ubuntu:25.10

ARG PORT=5002

ENV DEBIAN_FRONTEND=noninteractive \
PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1

RUN apt-get update && apt-get install -y --no-install-recommends \
python3-minimal \
libgomp1 \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*

RUN groupadd -g 10001 biosim && \
useradd \
--uid 10001 \
--gid biosim \
--create-home \
--shell /usr/sbin/nologin \
biosim

WORKDIR /app

# Copy the pre-built virtual environment from the builder stage
COPY --from=builder --chown=biosim:biosim /venv /venv

# Copy schema artifacts from the fetcher stage
COPY --from=schema-fetcher --chown=biosim:biosim /opt/biosim-schema /opt/biosim-schema

# Set PATH to include the virtual environment's bin directory
ENV PATH="/venv/bin:$PATH"

USER biosim

EXPOSE 5002
ENV PORT=${PORT} \
FLASK_APP=biosimdb_interface \
PYSTOW_HOME=/app/.pystow \
WEBFORM_SCHEMA_PATH=/opt/biosim-schema/project/schema_webformfields.json \
ENGINE_MAPPING_SCHEMA_PATH=/opt/biosim-schema/project/schema_enginemappings.json \
BIOSIM_SCHEMA_PATH=/opt/biosim-schema/biosim_schema/schema/biosim_schema.yaml

ENV FLASK_APP=biosimdb_interface
EXPOSE ${PORT}

CMD ["gunicorn", "--bind", "0.0.0.0:5002", "biosimdb_interface:create_app()"]
CMD ["sh", "-c", "gunicorn --bind 0.0.0.0:$PORT 'biosimdb_interface:create_app()'"]
Loading