feat: Docker setup for VPS deployment#10
Merged
Conversation
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
approved these changes
Jun 14, 2026
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! |
Contributor
Author
|
That's great new @emanuilo. Thank you for taking time to review and improve it! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 Debiancompose.yml(Compose v2 name) bind-mounts./dataso MEMORY.md, the SQLite index, images, and bot sessions live on the host and survive image rebuildsdocker/entrypoint.shruns 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 thememclawuser via gosu before exec'ing the CLI - same pattern as the official Postgres / Redis / MariaDB images. No host-sidechownstep required~/.memclaw/.envso Memclaw's interactive setup wizard is skipped and credentials come from composeenv_filedocs/docker.mdcovers configure / build / WhatsApp first-run pairing / persistence / common ops.env.examplegainsMEMCLAW_PLATFORM=telegram. Without it the barememclawcommand falls through to the terminal REPL, so adocker compose up -ddeployment silently never registers with Telegram / Slack / WhatsAppTest plan
docker compose up -d --buildwith a Telegram bot token boots, logsStarting Memclaw Telegram bot..., and replies to a DM./dataon the host./datato 1000:1000 on first boot without any manual chowndocker compose run --rm memclawshows the QR, pairs, anddocker compose up -dreuses the saved session