Skip to content
Draft
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
110 changes: 110 additions & 0 deletions .github/workflows/build-production-image.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# SPDX-FileCopyrightText: 2025 Jonas Huber <https://github.com/jh-RLI> © Reiner Lemoine Institut
#
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# Builds and pushes production container images to ghcr.io on every v* tag.
#
# Images produced:
# ghcr.io/openenergyplatform/oeplatform-production:<version> (app + Vite build)
# ghcr.io/openenergyplatform/oeplatform-ontop:<version> (Ontop + JDBC driver)
#
# The existing image-build.yaml continues to build the CI/testing image
# (ghcr.io/openenergyplatform/oeplatform) from docker/Dockerfile unchanged.

name: Build and publish production images

on:
push:
tags:
- "v*"
workflow_dispatch:

env:
REGISTRY: ghcr.io
ORG: openenergyplatform
# PostgreSQL JDBC driver version baked into the ontop image
JDBC_VERSION: "42.7.3"

jobs:
build-app:
name: OEPlatform app image
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

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

- name: Log in to container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.ORG }}/oeplatform-production
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=raw,value=latest

- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
file: ./podman/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max

build-ontop:
name: Ontop image
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

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

- name: Download PostgreSQL JDBC driver
run: |
curl -fsSL \
"https://repo1.maven.org/maven2/org/postgresql/postgresql/${{ env.JDBC_VERSION }}/postgresql-${{ env.JDBC_VERSION }}.jar" \
-o docker/serviceConfigs/ontop/postgresql.jar

- name: Log in to container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.ORG }}/oeplatform-ontop
tags: |
type=semver,pattern={{version}}
type=raw,value=latest

- name: Build and push
uses: docker/build-push-action@v6
with:
context: ./docker
file: ./docker/Dockerfile.ontop
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ venv*/
/envs
/node_env
.env*
!.env.example
!**/oep.env.example
/fuseki
apache*
/oep-django-5
Expand Down
2 changes: 1 addition & 1 deletion docker/Dockerfile.ontop
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Use the official Ontop image as the base
FROM ontop/ontop:latest
FROM docker.io/ontop/ontop:latest

# Copy the PostgreSQL JDBC driver into Ontop's lib directory
COPY serviceConfigs/ontop/postgresql.jar /opt/ontop/lib/postgresql.jar
Expand Down
37 changes: 37 additions & 0 deletions podman/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# SPDX-FileCopyrightText: 2025 Jonas Huber <https://github.com/jh-RLI> © Reiner Lemoine Institut
#
# SPDX-License-Identifier: AGPL-3.0-or-later

# Copy this file to .env on the server and fill in all values before starting
# the stack. The .env file must never be committed to version control.
#
# Usage:
# cp podman/.env.example .env
# # edit .env with real values
# podman-compose --env-file .env -f podman/podman-compose.yaml up -d

# ── PostgreSQL ────────────────────────────────────────────────────────────────
POSTGRES_USER=
POSTGRES_PASSWORD=

# ── OEPlatform app ────────────────────────────────────────────────────────────
# Database credentials passed to Django (must match the PostgreSQL values above)
OEP_DJANGO_USER=
OEP_DB_PW=
OEP_DJANGO_HOST=postgres
OEP_DJANGO_NAME=oep_django
LOCAL_DB_USER=
LOCAL_DB_PASSWORD=
LOCAL_DB_NAME=oedb
LOCAL_DB_HOST=postgres

# ── Fuseki ────────────────────────────────────────────────────────────────────
FUSEKI_ADMIN_PASSWORD=
FUSEKI_DATASET_1=ds

# ── Ports (optional — defaults shown) ────────────────────────────────────────
# OEP_PORT_WEB=8080
# OEP_PORT_POSTGRES=5432
# OEP_PORT_FUSEKI=3030
# OEP_PORT_ONTOP=8081
# OEP_PORT_LOOKUP=3004
57 changes: 57 additions & 0 deletions podman/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# SPDX-FileCopyrightText: 2025 Jonas Huber <https://github.com/jh-RLI> © Reiner Lemoine Institut
#
# SPDX-License-Identifier: AGPL-3.0-or-later

# ── Stage 1: build Vite frontend assets ──────────────────────────────────────
FROM node:25.2.1 AS vite-build

WORKDIR /app

# Install deps first for better layer caching
COPY package*.json ./
RUN npm ci

COPY . .
RUN npm run build
# Output: /app/assets/ (including manifest.json read by django-vite)


# ── Stage 2: production application ──────────────────────────────────────────
FROM python:3.10.14

RUN apt-get update \
&& apt-get install -y --no-install-recommends apache2 apache2-dev wget unzip \
&& rm -rf /var/lib/apt/lists/*

# Enable required Apache modules
RUN a2enmod headers

WORKDIR /app

COPY requirements.txt /app/requirements.txt
RUN pip install -r requirements.txt \
&& pip install mod_wsgi \
&& mod_wsgi-express module-config >> /etc/apache2/apache2.conf

COPY podman/apache2.conf /etc/apache2/conf-enabled/oeplatform.conf
COPY . /app

# Overwrite any local assets/ with the freshly built Vite output from stage 1
COPY --from=vite-build /app/assets /app/assets

COPY podman/entrypoint.sh /app/entrypoint.sh
RUN chmod +x /app/entrypoint.sh

# Build-time static asset collection (no DB needed)
# Compress is also run at build time since it only reads templates and static files
RUN cp /app/oeplatform/securitysettings.py.default /app/oeplatform/securitysettings.py \
&& python manage.py collectstatic --noinput \
&& python manage.py compress --force \
&& rm /app/oeplatform/securitysettings.py

# Volume mount points — created here so named volumes initialise correctly
RUN mkdir -p /app/ontologies /app/media/oeo_ext

EXPOSE 80

CMD ["/app/entrypoint.sh"]
Loading
Loading