Files
zooqueenandHanzo Dev 9e0fbd66ea
Hanzo CI/CD / cicd (push) Waiting to run
CI/CD / cicd (push) Waiting to run
Carry the NLTK corpora the search index reads in the image
helpdesk's after_migrate hook downloads the tagger, punkt_tab and brown
corpora when they are missing from the container. The image now holds
them, so a boot runs migrate without a network download.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-15 12:55:05 -07:00

108 lines
5.0 KiB
Docker

# syntax=docker/dockerfile:1.7
# Hanzo Help Center — Frappe Helpdesk on Base/SQLite.
#
# Proves the "one Frappe-core -> all Frappe apps" thesis: the SAME recipe
# (bench + hanzoai/frappe SQLite driver) is reused across every Frappe app;
# only the app layer (helpdesk) swaps. Second Frappe app after hanzoai/erp.
#
# Data model: org == tenant. One SQLite site per org, persisted on the
# mounted volume (Hanzo Base/SQLite). No MariaDB, no Postgres, no external DB.
# Built on-cluster via arcd/BuildKit (never GitHub builders, never locally).
ARG PYTHON_VERSION=3.14
FROM python:${PYTHON_VERSION}-slim-trixie AS build
ENV DEBIAN_FRONTEND=noninteractive \
PYTHONUNBUFFERED=1 \
PIP_NO_CACHE_DIR=1 \
NODE_MAJOR=24 \
BENCH_DIR=/home/frappe/frappe-bench \
PATH=/home/frappe/.local/bin:$PATH
# Frappe system dependencies. SQLite is stdlib in CPython, so no DB client.
# wkhtmltopdf for PDF/print, redis-server for cache/queue/socketio (in-pod),
# node for the frappe-ui / helpdesk SPA asset build.
ARG WKHTMLTOX_DEB=https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-3/wkhtmltox_0.12.6.1-3.bookworm_amd64.deb
RUN apt-get update && apt-get install -y --no-install-recommends \
git curl wget ca-certificates build-essential pkg-config \
cron \
redis-server \
libffi-dev libssl-dev \
# C-extension build headers for frappe's pinned deps (mysqlclient, psycopg2,
# python-ldap, lxml, pillow) — compiled from source on Python 3.14.
default-libmysqlclient-dev libpq-dev libldap2-dev libsasl2-dev \
libxml2-dev libxslt1-dev libjpeg-dev zlib1g-dev libcups2-dev \
fontconfig libjpeg62-turbo libxrender1 libxext6 xfonts-75dpi xfonts-base \
fonts-cantarell \
gettext \
# wkhtmltopdf (patched-Qt static build; the apt package was dropped in trixie)
&& wget -q -O /tmp/wkhtmltox.deb "${WKHTMLTOX_DEB}" \
&& apt-get install -y --no-install-recommends /tmp/wkhtmltox.deb \
&& rm -f /tmp/wkhtmltox.deb \
&& curl -fsSL https://deb.nodesource.com/setup_${NODE_MAJOR}.x | bash - \
&& apt-get install -y --no-install-recommends nodejs \
&& npm install -g yarn \
&& rm -rf /var/lib/apt/lists/*
RUN useradd -ms /bin/bash frappe
USER frappe
WORKDIR /home/frappe
# frappe-bench CLI, pinned: bench's file:// handling below is this version's.
RUN pip install --user frappe-bench==5.31.0
# Every app enters the bench as a local git repository at one commit. bench clones
# a file:// URL like any remote, and reads a bare local path as an app already in
# apps/. The Frappe core (hanzoai/frappe, which carries the SQLite driver) and
# telephony are pinned by commit; helpdesk is this build context.
ARG FRAPPE_REPO=https://github.com/hanzoai/frappe
ARG FRAPPE_COMMIT=56736629baf1c3782a6d08193513c8940744e191
RUN git init -q /tmp/apps/frappe \
&& git -C /tmp/apps/frappe fetch -q --depth 1 "${FRAPPE_REPO}" "${FRAPPE_COMMIT}" \
&& git -C /tmp/apps/frappe checkout -q -B develop FETCH_HEAD \
&& bench init --skip-redis-config-generation --verbose \
--frappe-path file:///tmp/apps/frappe frappe-bench \
&& rm -rf /tmp/apps
WORKDIR ${BENCH_DIR}
# telephony is a hard frappe-dependency of helpdesk (pyproject).
ARG TELEPHONY_REPO=https://github.com/frappe/telephony
ARG TELEPHONY_COMMIT=c213488a87c21b25475f1110526e80486412b7ff
RUN git init -q /tmp/apps/telephony \
&& git -C /tmp/apps/telephony fetch -q --depth 1 "${TELEPHONY_REPO}" "${TELEPHONY_COMMIT}" \
&& git -C /tmp/apps/telephony checkout -q -B develop FETCH_HEAD \
&& bench get-app --skip-assets file:///tmp/apps/telephony \
&& rm -rf /tmp/apps
# helpdesk itself: the build context, committed into a local repository. The
# frappe-ui submodule is a development checkout; the desk build reads the npm
# package.
RUN --mount=type=bind,target=/tmp/context \
mkdir -p /tmp/apps \
&& cp -R /tmp/context /tmp/apps/helpdesk \
&& rm -rf /tmp/apps/helpdesk/frappe-ui \
&& git -C /tmp/apps/helpdesk init -q -b develop \
&& git -C /tmp/apps/helpdesk add -A \
&& git -C /tmp/apps/helpdesk -c user.name=hanzo -c user.email=[email protected] commit -qm helpdesk \
&& bench get-app file:///tmp/apps/helpdesk \
&& rm -rf /tmp/apps
# helpdesk's search reads NLTK corpora, and its after_migrate hook downloads any
# that are missing. The image carries them, so a boot makes no download.
RUN env/bin/python -c "import nltk; [nltk.download(c, quiet=True, raise_on_error=True) for c in ('averaged_perceptron_tagger_eng', 'punkt_tab', 'brown')]"
# Build all frontend assets (frappe desk + helpdesk SPA).
RUN bench build --production
# Assets are CODE, not data: snapshot the built sites/ tree (apps.txt +
# assets symlink targets + default configs) so the entrypoint can restore
# them on top of the persistent (data-only) volume at every boot.
RUN cp -a ${BENCH_DIR}/sites /home/frappe/sites-template
COPY --chown=frappe:frappe deploy/entrypoint.sh /home/frappe/entrypoint.sh
RUN chmod +x /home/frappe/entrypoint.sh
EXPOSE 8000 9000
ENTRYPOINT ["/home/frappe/entrypoint.sh"]