From 67ecf3b8d7d712de17571ec47f212fdb00542722 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 30 Aug 2026 21:56:28 +0200 Subject: [PATCH] Docker setup --- .dockerignore | 2 ++ .env.example | 1 + .gitignore | 4 ++++ Dockerfile | 45 +++++++++++++++++++++++++++++++++++++++++++++ compose.yaml | 14 ++++++++++++++ constants.py | 13 +++++++------ main.py | 3 ++- 7 files changed, 75 insertions(+), 7 deletions(-) create mode 100644 .dockerignore create mode 100644 .env.example create mode 100644 Dockerfile create mode 100644 compose.yaml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..044cfa7 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +.env* +.git* diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..eced4af --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +VNC_PORT=5900 diff --git a/.gitignore b/.gitignore index 0685502..e451e89 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,7 @@ settings.json /*.AppImage.zsync .DS_Store *.app +# Docker +/volumes/ +!/volumes/.gitkeep +/.env diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..bbf5862 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,45 @@ +# Python 3.14 base & pip installation +FROM python:3.14 AS base + +WORKDIR /app + +RUN apt-get update && apt-get install -y \ + libgirepository1.0-dev \ + libcairo2-dev \ + pkg-config \ + python3-dev \ + gtk+3.0 \ + dbus-x11 \ + x11vnc \ + xvfb \ + fluxbox \ + net-tools \ + libappindicator3-dev \ + libayatana-appindicator3-dev \ + x11-utils + +COPY requirements.txt ./ +RUN pip install --no-cache-dir -r requirements.txt + +# Create the final image +FROM base + +WORKDIR /app + +# Copy the rest of the project files +COPY . . + +# Start Xvfb, Fluxbox, and x11vnc, then run the application +CMD rm -f /tmp/.X1-lock && \ + Xvfb :1 -screen 0 1280x720x16 & \ + fluxbox & \ + # Wait for the X server to be up + while ! xdpyinfo -display :1 > /dev/null 2>&1; do \ + echo "Waiting for X server to be available..."; \ + sleep 1; \ + done && \ + echo "X server is running" || (echo "X server failed to start, exiting..." && exit 1); \ + # Start x11vnc with additional logging + x11vnc -display :1 -nopw -listen 0.0.0.0 -forever -xkb -no6 -noxdamage -o /var/log/x11vnc.log & \ + # Explicitly set the DISPLAY variable for the Python application + export DISPLAY=:1 && python main.py 2>&1 | tee /var/log/main.log diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..2da3c72 --- /dev/null +++ b/compose.yaml @@ -0,0 +1,14 @@ +services: + app: + build: + context: ./ + dockerfile: ./Dockerfile + environment: + - TZ=Europe/Berlin + env_file: + - .env + restart: unless-stopped + ports: + - "127.0.0.1:${VNC_PORT:-5900}:5900" + volumes: + - ./volumes/data:/app/data diff --git a/constants.py b/constants.py index cdbd47d..8fdaa2f 100644 --- a/constants.py +++ b/constants.py @@ -92,6 +92,7 @@ else: if SELF_PATH.stem == "pyinstaller" or SELF_PATH.name == "gui.py": SELF_PATH = Path(__file__).with_name("main.py").resolve() WORKING_DIR = SELF_PATH.parent +DATA_DIR = Path(WORKING_DIR, "data") # Development paths VENV_PATH = Path(WORKING_DIR, "env") SITE_PACKAGES_PATH = Path(VENV_PATH, SYS_SITE_PACKAGES) @@ -100,13 +101,13 @@ SCRIPTS_PATH = Path(VENV_PATH, SYS_SCRIPTS) # NOTE: These don't have to be available to the end-user, so the path points to the internal dir LANG_PATH = _resource_path("lang") # Other Paths -LOG_PATH = Path(WORKING_DIR, "log.txt") -DUMP_PATH = Path(WORKING_DIR, "dump.dat") -LOCK_PATH = Path(WORKING_DIR, "lock.file") -CACHE_PATH = Path(WORKING_DIR, "cache") +LOG_PATH = Path(DATA_DIR, "log.txt") +DUMP_PATH = Path(DATA_DIR, "dump.dat") +LOCK_PATH = Path(DATA_DIR, "lock.file") +CACHE_PATH = Path(DATA_DIR, "cache") CACHE_DB = Path(CACHE_PATH, "mapping.json") -COOKIES_PATH = Path(WORKING_DIR, "cookies.jar") -SETTINGS_PATH = Path(WORKING_DIR, "settings.json") +COOKIES_PATH = Path(DATA_DIR, "cookies.jar") +SETTINGS_PATH = Path(DATA_DIR, "settings.json") # Typing JsonType = Dict[str, Any] URLType = NewType("URLType", str) diff --git a/main.py b/main.py index dc62829..af217a6 100644 --- a/main.py +++ b/main.py @@ -187,7 +187,8 @@ if __name__ == "__main__": client.gui.status.update(_("gui", "status", "terminated")) # notify the user about the closure client.gui.grab_attention(sound=True) - await client.gui.wait_until_closed() + # Docker: do not wait until close so docker can recognize the exit and restart + # await client.gui.wait_until_closed() # save the application state # NOTE: we have to do it after wait_until_closed, # because the user can alter some settings between app termination and closing the window