Feature/docker compose - #349
Open
opticon454 wants to merge 2 commits into
Open
Conversation
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
This PR adds first-party Docker Compose support for Codeman while preserving its ability to create and manage isolated agent containers.
With this PR Codeman itself runs inside a container & it can still spawn isolated Claude, Codex, Gemini, OpenCode, and shell case containers through the host Docker daemon. These are sibling containers, not nested Docker-in-Docker containers.
The Compose deployment:
Motivation
Codeman was originally designed to run directly on a host where Codeman and the Docker daemon shared the same filesystem namespace.
Not everyone want's to run applications directly on their desktop and docker is a perfect way to isolate systems. It also allows end-users to run linux applications on Windows using WSL2.
Docker containers also run as a system level so you don't even have to log into your desktop in order to use CM because docker is running as a service.
Future development of CM can also be adapted to spin up named containers based on the branch name to test multiple feature and bugfix additons with AI. Simply ask your AI to spin up a new instance on a new branch with a prefix.
Docker build vs published Image
This setup is building the docker image manually, there's no requirement for actions/pipelines to create an image and publish it to dockerhub (although this can be added at any point in time).
Creating the CM container this way at this point of CM's development allows for a simple git pull and then re-rerun the Start-Container.sh script to rebuild the image with the latest version or use CM's built-ni self update tool.
CodeMan can also self-update within the container and just requires a restart to use the latest version. A future idea would be to add in a self-terminate and restart capability to the container doesn't even need to be restarted.
Application Data
Codemans' user folder is passed mapped through to a docker host volume or folder, preserving all history during rebuilds or updates.
User running context
Running Codeman as root was not a suitable workaround because some agent CLIs, particularly Claude Code, refuse or fail to operate correctly as root. A dedicated user is created during the container build, username is set as per the .env file.
Isolated container support
The Compose deployment uses Docker-outside-of-Docker:
/var/run/docker.sock.CODEMAN_CASES_PATHprovides a workspace path that is identical inside Codeman and on the Docker host.CODEMAN_DOCKER_HOST_HOMEtranslates generated credential, seed, transcript, and hook-secret paths from Codeman's container filesystem into host-visible paths.Docker itself is not run as a daemon inside the Codeman container. Only the Docker CLI is installed in the image.
Direct host installations continue using the existing behaviour because path translation is enabled only when
CODEMAN_DOCKER_HOST_HOMEis configured.Changes
docker/server.Dockerfiledocker/.env.exampledocker/Start-Codeman.shopencode.CODEMAN_RUNTIME_USER.CODEMAN_CASES_PATHfor host-visible isolated workspaces.CODEMAN_DOCKER_HOST_HOMEtranslation for:CODEMAN_DOCKER_DISABLE_SWAP_LIMITcompatibility for hosts without swap accounting:--memory-swapoption.Security
no-new-privilegesis enabled..env.examplemust be replaced before exposing Codeman to a network.Backwards compatibility
Direct host installations retain their existing behaviour when the new Compose-specific environment variables are absent.
Existing isolated Docker cases continue using the normal host-native path handling outside Compose deployments.
Swap limiting retains its current behaviour unless
CODEMAN_DOCKER_DISABLE_SWAP_LIMIT=1is explicitly configured.Validation
The complete validation suite passed in a clean Linux container with Node.js 22 and tmux installed:
The following checks passed:
npm run typecheck npm run lint npm run format:check npm run check:frontend-syntax npm test bash -n docker/Start-Codeman.sh docker compose --env-file docker/.env.example \ -f docker/docker-compose.yaml config --quietThe server image was built and validated with multiple host identity combinations:
Manual end-to-end validation was performed on an Unraid Docker host, including:
opencodeaccount.