Skip to content

feat: Docker setup for VPS deployment#10

Merged
emanuilo merged 8 commits into
emanuilo:mainfrom
kkomelin:main
Jun 14, 2026
Merged

feat: Docker setup for VPS deployment#10
emanuilo merged 8 commits into
emanuilo:mainfrom
kkomelin:main

Conversation

@kkomelin

@kkomelin kkomelin commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Summary

  • docker/Dockerfile - multi-stage build (python:3.12-slim-trixie + uv 0.11.17 + Node 24 LTS + Claude Code CLI + libmagic + tini + gosu). gnupg is purged after the NodeSource apt setup so the runtime image doesn't carry GnuPG CVEs it never uses. OS HIGH/CRITICAL CVEs settle at 16, all unfixed upstream in current Debian
  • compose.yml (Compose v2 name) bind-mounts ./data so MEMORY.md, the SQLite index, images, and bot sessions live on the host and survive image rebuilds
  • docker/entrypoint.sh runs as root, chowns the bind mount only when its uid isn't already 1000 (so steady-state restarts skip the recursive walk), then drops to the memclaw user via gosu before exec'ing the CLI - same pattern as the official Postgres / Redis / MariaDB images. No host-side chown step required
  • The entrypoint also creates an empty ~/.memclaw/.env so Memclaw's interactive setup wizard is skipped and credentials come from compose env_file
  • docs/docker.md covers configure / build / WhatsApp first-run pairing / persistence / common ops
  • .env.example gains MEMCLAW_PLATFORM=telegram. Without it the bare memclaw command falls through to the terminal REPL, so a docker compose up -d deployment silently never registers with Telegram / Slack / WhatsApp

Test plan

  • docker compose up -d --build with a Telegram bot token boots, logs Starting Memclaw Telegram bot..., and replies to a DM
  • Restart the container; MEMORY.md / memclaw.db survive in ./data on the host
  • On a host where the invoking user isn't uid 1000, confirm the entrypoint chowns ./data to 1000:1000 on first boot without any manual chown
  • WhatsApp first-run: docker compose run --rm memclaw shows the QR, pairs, and docker compose up -d reuses the saved session

kkomelin and others added 6 commits May 31, 2026 16:33
Two-stage Dockerfile (uv-built venv + slim runtime with Node for the
Claude CLI and libmagic for WhatsApp), docker-compose with a named
volume for ~/.memclaw, and a VPS deployment guide.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Without MEMCLAW_PLATFORM set, the bare `memclaw` command falls through
to the terminal REPL, so Docker users running `docker compose up -d`
end up with a bot that never registers with Telegram/Slack/WhatsApp
and silently ignores all messages.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Host bind mount makes MEMORY.md, the SQLite index, images, and bot
sessions directly visible / backupable / git-trackable on the host,
which is what most VPS deployments actually want. Container user is
already uid:gid 1000:1000 so most hosts need no chown.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Run the entrypoint as root so it can fix ownership of the bind-mounted
data directory on a fresh host where the user isn't already uid 1000,
then drop privileges to the `memclaw` user via gosu before exec'ing the
CLI - the standard pattern used by the official Postgres / Redis /
MariaDB images.

Only walks the tree when ownership is actually wrong, so steady-state
restarts skip the recursive chown. Removes the manual `chown -R 1000:1000 data`
step from the deploy docs.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Base: python:3.12-slim-bookworm -> python:3.12-slim-trixie. Debian 13
  has newer / patched system packages; OS HIGH/CRITICAL CVEs drop from
  36 to 16 (55% reduction), the residual being upstream issues with no
  fix available in any current image yet.
- uv: 0.5.14 (Dec 2024) -> 0.11.17.
- Purge gnupg/dirmngr after the NodeSource apt setup. They only exist
  to verify the apt repo signature during build and carry ~12 unfixed
  GnuPG CVEs into the runtime image for zero benefit.
- Move Dockerfile to docker/Dockerfile and rename docker-compose.yml to
  compose.yml - Compose v2 prefers the unprefixed name and grouping
  build-context files under docker/ matches modern convention.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Node 24 ("Krypton") has been the active LTS since late 2025; Node 22
moved into maintenance. claude-code only requires node >=18, so 24
works fine.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@emanuilo emanuilo self-requested a review June 14, 2026 10:46
@emanuilo

Copy link
Copy Markdown
Owner

@kkomelin It looks great! I just added one note for the timezone in docker.md because reminders weren't working properly without it. Thanks a lot!

@emanuilo emanuilo merged commit 2cd4759 into emanuilo:main Jun 14, 2026
4 checks passed
@kkomelin

Copy link
Copy Markdown
Contributor Author

That's great new @emanuilo. Thank you for taking time to review and improve it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants