# SPDX-FileCopyrightText: 2026 Bart Broere # SPDX-License-Identifier: GPL-3.0-or-later # peo: neo4j-browser on top of PostgreSQL + Apache AGE. # # Two images can be built from this file: # # full (the default): the Apache AGE image (PostgreSQL with the AGE extension) # plus peo, neo4j-browser and pgAdmin, all in one container. # slim (--target slim): only peo and neo4j-browser, for connecting to a # separate PostgreSQL server with AGE; see compose.yaml. # # peo is the Python package that speaks the Bolt protocol to the browser and # translates Cypher into AGE `cypher()` calls. The browser stage builds the # neo4j-browser static frontend from source for both images. ARG AGE_IMAGE=docker.io/apache/age:release_PG18_1.8.0 ARG SLIM_BASE_IMAGE=docker.io/library/debian:trixie-slim # 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 ${SLIM_BASE_IMAGE} AS slim RUN apt-get update \ && apt-get install -y --no-install-recommends python3 python3-psycopg python3-venv \ && rm -rf /var/lib/apt/lists/* # peo itself, using Debian's psycopg and the other dependencies from PyPI. License # notices: see THIRD_PARTY_NOTICES.md. COPY container/collect-python-licenses.py /tmp/ COPY container/licenses/ /tmp/licenses/ COPY pyproject.toml README.md LICENSE /tmp/peo/ COPY peo /tmp/peo/peo RUN python3 -m venv --system-site-packages /opt/peo/venv \ && /opt/peo/venv/bin/pip install --no-cache-dir "/tmp/peo[browser]" \ && /opt/peo/venv/bin/python /tmp/collect-python-licenses.py \ /usr/share/doc/peo/peo-python-licenses /tmp/licenses \ && rm -r /tmp/peo /tmp/collect-python-licenses.py /tmp/licenses COPY LICENSE THIRD_PARTY_NOTICES.md /usr/share/doc/peo/ COPY --from=browser /src/LICENSE /src/NOTICE.txt /src/LICENSES.txt /neo4j-browser-source.tar.gz \ /usr/share/doc/peo/neo4j-browser/ COPY --from=browser /src/dist /opt/peo/browser RUN useradd --system --no-create-home --home-dir /nonexistent --shell /usr/sbin/nologin peo USER peo ENV PEO_BROWSER_DIR=/opt/peo/browser \ PEO_HTTP_PORT=7474 \ PEO_BOLT_PORT=7687 # 7474: neo4j-browser (HTTP), 7687: Bolt EXPOSE 7474 7687 CMD ["/opt/peo/venv/bin/peo"] FROM ${AGE_IMAGE} AS full 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 container/collect-python-licenses.py /tmp/ COPY container/licenses/ /tmp/licenses/ RUN /opt/pgadmin/bin/python /tmp/collect-python-licenses.py \ /usr/share/doc/peo/pgadmin-python-licenses /tmp/licenses # peo itself, using Debian's psycopg and the other dependencies from PyPI. COPY pyproject.toml README.md LICENSE /tmp/peo/ COPY peo /tmp/peo/peo RUN python3 -m venv --system-site-packages /opt/peo/venv \ && /opt/peo/venv/bin/pip install --no-cache-dir "/tmp/peo[browser]" \ && /opt/peo/venv/bin/python /tmp/collect-python-licenses.py \ /usr/share/doc/peo/peo-python-licenses /tmp/licenses \ && rm -r /tmp/peo /tmp/collect-python-licenses.py /tmp/licenses COPY LICENSE THIRD_PARTY_NOTICES.md /usr/share/doc/peo/ COPY --from=browser /src/LICENSE /src/NOTICE.txt /src/LICENSES.txt /neo4j-browser-source.tar.gz \ /usr/share/doc/peo/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/peo/apache-age/ COPY --from=browser /src/dist /opt/peo/browser COPY container/initdb/ /docker-entrypoint-initdb.d/ COPY container/pgadmin/config_distro.py /opt/peo/pgadmin/config_distro.py COPY container/peo-entrypoint.sh /usr/local/bin/peo-entrypoint.sh ENV PEO_DEFAULT_GRAPH=neo4j \ PEO_BROWSER_DIR=/opt/peo/browser \ PEO_HTTP_PORT=7474 \ PEO_BOLT_PORT=7687 \ PEO_PG_HOST=127.0.0.1 \ PEO_PG_PORT=5432 \ PEO_PGADMIN=true \ PEO_PGADMIN_PORT=5050 \ CONFIG_DISTRO_FILE_PATH=/opt/peo/pgadmin/config_distro.py # 7474: neo4j-browser (HTTP), 7687: Bolt, 5050: pgAdmin, 5432: PostgreSQL EXPOSE 7474 7687 5050 5432 ENTRYPOINT ["/usr/local/bin/peo-entrypoint.sh"] CMD ["postgres", "-c", "shared_preload_libraries=age"]