Skip to content
Closed
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
29 changes: 20 additions & 9 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,28 +1,39 @@
FROM debian:13.4
FROM ghcr.io/astral-sh/uv:0.11.6-python3.13-trixie@sha256:b3c543b6c4f23a5f2df22866bd7857e5d304b67a564f4feab6ac22044dde719b AS uv_source
FROM tianon/gosu:1.19-trixie@sha256:3b176695959c71e123eb390d427efc665eeb561b1540e82679c15e992006b8b9 AS gosu_source
FROM debian:13.4-slim

# Disable Python stdout buffering to ensure logs are printed immediately
ENV PYTHONUNBUFFERED=1

# Install system dependencies in one layer, clear APT cache
# Install system dependencies in one layer, including chromium dependencies, clear APT cache
RUN apt-get update && \
apt-get install -y --no-install-recommends \
build-essential nodejs npm python3 python3-pip ripgrep ffmpeg gcc python3-dev libffi-dev procps && \
build-essential nodejs npm python3 ripgrep ffmpeg gcc python3-dev libffi-dev git \
libasound2t64 libatk-bridge2.0-0t64 libatk1.0-0t64 libatspi2.0-0t64 libcairo2 libcups2t64 libdbus-1-3 libdrm2 libgbm1 libglib2.0-0t64 libnspr4 libnss3 libpango-1.0-0 libx11-6 libxcb1 libxcomposite1 libxdamage1 libxext6 libxfixes3 libxkbcommon0 libxrandr2 xvfb fonts-noto-color-emoji fonts-unifont libfontconfig1 libfreetype6 xfonts-scalable fonts-liberation fonts-ipafont-gothic fonts-wqy-zenhei fonts-tlwg-loma-otf fonts-freefont-ttf && \
rm -rf /var/lib/apt/lists/*

# user IDs over 10000 are recommended for security; this can be overridden at runtime for easier permissions handling (running under the same UID as the computer user, for instance)
RUN useradd -u 10000 -m -d /opt/data hermes

COPY . /opt/hermes
COPY --chmod=0755 --from=gosu_source /gosu /usr/local/bin/
COPY --chmod=0755 --from=uv_source /usr/local/bin/uv /usr/local/bin/uvx /usr/local/bin/
COPY --chown=hermes:hermes . /opt/hermes
WORKDIR /opt/hermes

USER hermes

# Install Python and Node dependencies in one layer, no cache
RUN pip install --no-cache-dir uv --break-system-packages && \
uv pip install --system --break-system-packages --no-cache -e ".[all]" && \
RUN uv venv && \
uv pip install --no-cache-dir -e ".[all]" && \
uv pip install --no-cache-dir -e ".[matrix]" && \
npm install --prefer-offline --no-audit && \
npx playwright install --with-deps chromium --only-shell && \
cd /opt/hermes/scripts/whatsapp-bridge && \
npm install --prefer-offline --no-audit && \
npm cache clean --force

WORKDIR /opt/hermes

RUN chmod +x /opt/hermes/docker/entrypoint.sh

USER root

ENV HERMES_HOME=/opt/data
VOLUME [ "/opt/data" ]
Expand Down
24 changes: 24 additions & 0 deletions docker/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,30 @@ set -e
HERMES_HOME="/opt/data"
INSTALL_DIR="/opt/hermes"

if [ "$(id -u)" = "0" ]; then
if [ -n "$HERMES_UID" -a "$HERMES_UID" != "$(id -u hermes)" ]; then
echo "Changing hermes UID to $HERMES_UID"
usermod -u "$HERMES_UID" hermes
fi

if [ -n "$HERMES_GID" -a "$HERMES_GID" != "$(id -g hermes)" ]; then
echo "Changing hermes GID to $HERMES_GID"
groupmod -g "$HERMES_GID" hermes
fi

actual_hermes_uid=$(id -u hermes)
if [ "$(stat -c %u $HERMES_HOME)" != "$actual_hermes_uid" ]; then
echo "$HERMES_HOME is not owned by $actual_hermes_uid, fixing"
chown -R hermes:hermes $HERMES_HOME
fi
echo "Dropping root privileges"
exec gosu hermes $0 "$@"
fi

source ${INSTALL_DIR}/.venv/bin/activate

npx playwright install chromium --only-shell

# Create essential directory structure. Cache and platform directories
# (cache/images, cache/audio, platforms/whatsapp, etc.) are created on
# demand by the application β€” don't pre-create them here so new installs
Expand Down