AGE keeps all properties in one agtype column and its Cypher writes fire no triggers, so the bridge periodically calls a stored procedure that adds a stored generated text column for every new property key. Only label tables with inserts or updates since the previous run are scanned. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
84 lines
3.4 KiB
Docker
84 lines
3.4 KiB
Docker
# SPDX-FileCopyrightText: 2026 Bart Broere
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
# peo4c: neo4j-browser on top of PostgreSQL + Apache AGE.
|
|
#
|
|
# Stage 1 builds the neo4j-browser static frontend from source.
|
|
# Stage 2 is the Apache AGE image (PostgreSQL with the AGE extension) plus the
|
|
# peo4c bridge, which speaks the Bolt protocol to the browser and translates
|
|
# Cypher into AGE `cypher()` calls, and pgAdmin as a SQL interface.
|
|
|
|
ARG AGE_IMAGE=docker.io/apache/age:release_PG18_1.8.0
|
|
# Commit of apache/age's release/PG18/1.8.0 branch, for AGE's LICENSE and NOTICE.
|
|
ARG AGE_SOURCE_REF=b570cf7c1486863f77c14e9c0e07b0e9bfd01bf4
|
|
ARG PGADMIN_VERSION=9.18
|
|
|
|
FROM docker.io/library/node:16.20.2-bullseye AS browser
|
|
|
|
ARG NEO4J_BROWSER_REPO=https://github.com/neo4j/neo4j-browser.git
|
|
ARG NEO4J_BROWSER_REF=3928c10fd6f148fd615b391d27d3fd6ce43a9044
|
|
|
|
WORKDIR /src
|
|
RUN git init -q . \
|
|
&& git remote add origin "$NEO4J_BROWSER_REPO" \
|
|
&& git fetch -q --depth 1 origin "$NEO4J_BROWSER_REF" \
|
|
&& git checkout -q FETCH_HEAD \
|
|
&& git archive --format=tar.gz --prefix=neo4j-browser/ -o /neo4j-browser-source.tar.gz HEAD
|
|
RUN yarn install --frozen-lockfile --network-timeout 600000
|
|
RUN yarn build && test -f dist/index.html
|
|
|
|
|
|
FROM ${AGE_IMAGE}
|
|
|
|
ARG AGE_SOURCE_REF
|
|
ARG PGADMIN_VERSION
|
|
|
|
RUN apt-get update \
|
|
&& apt-get install -y --no-install-recommends python3 python3-psycopg python3-venv \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
RUN python3 -m venv /opt/pgadmin \
|
|
&& /opt/pgadmin/bin/pip install --no-cache-dir "pgadmin4==${PGADMIN_VERSION}" gunicorn \
|
|
&& ln -s "$(/opt/pgadmin/bin/python -c 'import sysconfig; print(sysconfig.get_paths()["purelib"])')/pgadmin4" \
|
|
/opt/pgadmin/app \
|
|
&& mkdir -p /var/lib/pgadmin \
|
|
&& chown postgres:postgres /var/lib/pgadmin
|
|
|
|
# License notices: see THIRD_PARTY_NOTICES.md. neo4j-browser is GPL-3.0, so its
|
|
# complete source is shipped next to the license.
|
|
COPY docker/collect-python-licenses.py /tmp/
|
|
COPY docker/licenses/ /tmp/licenses/
|
|
RUN /opt/pgadmin/bin/python /tmp/collect-python-licenses.py \
|
|
/usr/share/doc/peo4c/pgadmin-python-licenses /tmp/licenses \
|
|
&& rm -r /tmp/collect-python-licenses.py /tmp/licenses
|
|
COPY LICENSE THIRD_PARTY_NOTICES.md /usr/share/doc/peo4c/
|
|
COPY --from=browser /src/LICENSE /src/NOTICE.txt /src/LICENSES.txt /neo4j-browser-source.tar.gz \
|
|
/usr/share/doc/peo4c/neo4j-browser/
|
|
ADD https://raw.githubusercontent.com/apache/age/${AGE_SOURCE_REF}/LICENSE \
|
|
https://raw.githubusercontent.com/apache/age/${AGE_SOURCE_REF}/NOTICE \
|
|
/usr/share/doc/peo4c/apache-age/
|
|
|
|
COPY --from=browser /src/dist /opt/peo4c/browser
|
|
COPY bridge /opt/peo4c/bridge
|
|
COPY docker/initdb/ /docker-entrypoint-initdb.d/
|
|
COPY docker/pgadmin/config_distro.py /opt/peo4c/pgadmin/config_distro.py
|
|
COPY docker/peo4c-entrypoint.sh /usr/local/bin/peo4c-entrypoint.sh
|
|
|
|
ENV PEO4C_DEFAULT_GRAPH=neo4j \
|
|
PEO4C_BROWSER_DIR=/opt/peo4c/browser \
|
|
PEO4C_HTTP_PORT=7474 \
|
|
PEO4C_BOLT_PORT=7687 \
|
|
PEO4C_PG_HOST=127.0.0.1 \
|
|
PEO4C_PG_PORT=5432 \
|
|
PEO4C_PROPERTY_COLUMNS=true \
|
|
PEO4C_PROPERTY_COLUMNS_INTERVAL=5 \
|
|
PEO4C_PGADMIN=true \
|
|
PEO4C_PGADMIN_PORT=5050 \
|
|
CONFIG_DISTRO_FILE_PATH=/opt/peo4c/pgadmin/config_distro.py
|
|
|
|
# 7474: neo4j-browser (HTTP), 7687: Bolt, 5050: pgAdmin, 5432: PostgreSQL
|
|
EXPOSE 7474 7687 5050 5432
|
|
|
|
ENTRYPOINT ["/usr/local/bin/peo4c-entrypoint.sh"]
|
|
CMD ["postgres", "-c", "shared_preload_libraries=age"]
|