FEAT: Implement Docker containerization and deployment guide

This commit is contained in:
2026-04-11 16:02:53 -04:00
parent 0c0a18cb30
commit 728ad5306b
4 changed files with 143 additions and 0 deletions

58
Dockerfile Normal file
View File

@@ -0,0 +1,58 @@
# ORG-AGENT v1.0 Production Environment
FROM debian:bookworm-slim
# Prevent interactive prompts during build
ENV DEBIAN_FRONTEND=noninteractive
# 1. Install System Dependencies
# - sbcl: The Lisp Runtime
# - curl/git/unzip: Standard tools for Quicklisp and binaries
# - default-jre: Required by signal-cli
RUN apt-get update && apt-get install -y \
sbcl \
curl \
git \
unzip \
default-jre \
libsqlite3-0 \
&& rm -rf /var/lib/apt/lists/*
# 2. Install signal-cli (v0.14.0)
ENV SIGNAL_CLI_VERSION=0.14.0
RUN curl -L https://github.com/AsamK/signal-cli/releases/download/v${SIGNAL_CLI_VERSION}/signal-cli-${SIGNAL_CLI_VERSION}-Linux.tar.gz | tar xz -C /opt \
&& ln -s /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/signal-cli /usr/local/bin/signal-cli
# 3. Install Quicklisp
WORKDIR /root
RUN curl -O https://beta.quicklisp.org/quicklisp.lisp \
&& sbcl --non-interactive \
--load quicklisp.lisp \
--eval '(quicklisp-quickstart:install)' \
--eval '(let ((ql-util::*quicklisp-home* (merge-pathnames "quicklisp/" (user-homedir-pathname)))) (ql-dist:install-dist "http://beta.quicklisp.org/dist/quicklisp.txt" :prompt nil))'
# 4. Configure SBCL to load Quicklisp on startup
RUN echo '(let ((quicklisp-init (merge-pathnames "quicklisp/setup.lisp" (user-homedir-pathname)))) (when (probe-file quicklisp-init) (load quicklisp-init)))' > /root/.sbclrc
# 5. Setup Application Directory
WORKDIR /app
COPY . /app/projects/org-agent
# 6. Pre-cache Lisp Dependencies
# This minimizes startup time by downloading dexador, cl-json, etc. during build
RUN sbcl --non-interactive \
--eval '(push #p"/app/projects/org-agent/" asdf:*central-registry*)' \
--eval '(ql:quickload :org-agent)'
# 7. Environment & Volumes
# The host's memex root should be mounted to /memex
ENV MEMEX_DIR=/memex
VOLUME ["/memex"]
# Default Ports
EXPOSE 9105 8080
# Entrypoint
CMD ["sbcl", "--non-interactive", \
"--eval", "(push #p\"/app/projects/org-agent/\" asdf:*central-registry*)", \
"--eval", "(ql:quickload :org-agent)", \
"--eval", "(org-agent:main)"]

19
docker-compose.yml Normal file
View File

@@ -0,0 +1,19 @@
services:
org-agent:
build:
context: .
dockerfile: Dockerfile
container_name: org-agent
env_file: .env
volumes:
# Mount the entire memex directory (2 levels up from projects/org-agent)
- ../..:/memex
# Ensure signal-cli state is preserved
- signal-state:/root/.local/share/signal-cli
ports:
- "${ORG_AGENT_DAEMON_PORT:-9105}:9105"
- "${ORG_AGENT_WEB_PORT:-8080}:8080"
restart: unless-stopped
volumes:
signal-state:

36
docs/deployment.org Normal file
View File

@@ -0,0 +1,36 @@
#+TITLE: Deployment Guide: Containerized Org-Agent
#+AUTHOR: Amr
#+DATE: [2026-04-11 Sat]
#+FILETAGS: :deployment:docker:infrastructure:
* Overview
The ~org-agent~ is designed to run within a Docker container to ensure system dependencies (SBCL, Quicklisp, signal-cli) are perfectly matched across different host environments.
* Prerequisites
- Docker Engine
- Docker Compose
- A valid ~.env~ file in the ~projects/org-agent/~ directory (refer to ~.env.example~).
* Quick Start
** 1. Build and Start
From the ~projects/org-agent/~ directory:
#+begin_src bash
docker-compose up --build -d
#+end_src
** 2. Check Logs
#+begin_src bash
docker-compose logs -f
#+end_src
* Volume Mapping
The ~docker-compose.yml~ file automatically mounts your host's ~memex~ directory to ~/memex~ inside the container. This allows the agent to:
1. Read/Write to your Zettelkasten and GTD files.
2. Maintain its local state (Object Store, snapshots).
* Troubleshooting
** signal-cli Identity
If using the Signal gateway, ensure you have registered your number via the host's ~signal-cli~ or within the container. The state is preserved in the ~signal-state~ Docker volume.
** Re-loading Skills
The container pre-caches dependencies during the build. If you modify core Lisp logic, you must rebuild the image (~--build~). If you only modify ~.org~ skills in your memex, the agent can reload them dynamically if they are part of the startup scan.

View File

@@ -0,0 +1,30 @@
#+TITLE: Root Cause Analysis: Containerized Infrastructure (Docker)
#+DATE: 2026-04-11
#+FILETAGS: :rca:docker:deployment:infrastructure:psf:
* Executive Summary
Standardized the `org-agent` execution environment by creating a production-grade Docker infrastructure. This ensures that all system dependencies, including the Lisp runtime and external binaries like `signal-cli`, are locked down and portable.
* 1. Architectural Intent: The "Clean Room" Model
** Problem
The `org-agent` was relying on host-local binaries (`sbcl`, `signal-cli`) and manually configured Quicklisp dists. This made deployment to other environments (e.g., a VPS or a Sovereign Home Server) fragile and prone to version drift.
** Solution
1. **Dockerfile:** Created a multi-step build process that installs Debian Bookworm, SBCL, Java, and `signal-cli 0.14.0`.
2. **Pre-Caching:** The build process triggers a `ql:quickload` of the `:org-agent` system, ensuring all Lisp dependencies are pre-downloaded and stored in the image layer, drastically reducing startup time.
3. **Compose Orchestration:** Standardized the runtime via `docker-compose.yml`, which handles volume mounting of the user's `memex` directory and injection of `.env` secrets.
* 2. Volume Mapping & Persistence
** Strategy
To maintain the "Sovereign" mandate, the agent's code is isolated, but its memory (the `memex`) remains on the host.
- **Mapping:** `../..` (host) -> `/memex` (container).
- **State:** Created a named Docker volume `signal-state` to ensure that `signal-cli` identities and cryptographic keys survive container restarts and image updates.
* 3. Alignment with PSF Mandates
** Evolutionary Completion
By moving to Docker, we have achieved "Evolutionary Completion" for the deployment track. The system is no longer a collection of scripts; it is a deployable appliance.
** Documentation
A new `Deployment Guide` was added to `docs/deployment.org` to ensure standard operating procedures are preserved.
* 4. Permanent Learnings
- **Lisp Build Layers:** Always push the system to the ASDF registry and quickload during Docker build to bake dependencies into the image.
- **Compose Locality:** Placing the `docker-compose.yml` inside the `projects/org-agent/` folder keeps infrastructure code close to the implementation logic.