[feat] Add Docker support with GHCR publishing#311
Merged
chris-freeman-glean merged 12 commits intomainfrom Nov 19, 2025
Merged
[feat] Add Docker support with GHCR publishing#311chris-freeman-glean merged 12 commits intomainfrom
chris-freeman-glean merged 12 commits intomainfrom
Conversation
- Add Dockerfile for multi-arch Docker image support (amd64/arm64) - Create GitHub Actions workflow to publish images to GHCR on releases - Add docker-test workflow for CI validation - Simplify Docker documentation to use published GHCR images - Remove .dockerignore (no longer needed with npm install approach) Docker images will be automatically published to ghcr.io/gleanwork/local-mcp-server when releases are created, providing users with a sandboxed execution environment that abstracts over local environment differences.
4ab0f86 to
d3e6243
Compare
- Increase test sleep times from 2s to 5s for reliability on slower systems - Add tmpfs mount for .npm directory in read-only filesystem test - Add PACKAGE_VERSION build arg to Dockerfile for version pinning - Document both env block and -e flag approaches for environment variables - Add comprehensive Docker troubleshooting section to README - Address container exits, authentication errors, and connection issues
The Dockerfile creates user 'mcpserver' with home at /home/mcpserver, but the test was mounting tmpfs at /home/mcp/.npm. This caused the mount to be created at an incorrect path that doesn't match the user's actual home directory.
Remove -d (detached) flag which conflicts with -i (interactive) for stdio testing. Detached containers don't have stdin connected, causing MCP servers to fail or hang when trying to read from unavailable stdin. New approach: - Run container in foreground with -i flag and stdin from /dev/null - Use timeout to prevent hanging - Run in background with & to allow process checking - Verify process is running after startup - Properly cleanup with kill and wait This properly tests that the server can start and accept stdio communication.
The previous approach had critical flaws: - $! captured the timeout command PID, not docker - Killing timeout left docker running uncontrolled in background - Process checks verified wrong PID - No actual verification that stdio communication worked New approach: - Pipe actual MCP initialize message to container via stdin - Use 'timeout' as prefix (not wrapper) so docker is the background process - Capture docker's PID directly with $! - Use 'kill -0' to check if process is still running (non-destructive) - Capture output to verify MCP server responds - Check for JSON-RPC response to confirm stdio communication works - Proper cleanup with kill and wait - Show output on failure for debugging This properly tests that: 1. Container starts successfully 2. Accepts stdin input 3. MCP server can process requests 4. Works with security constraints
The Docker build was failing because npm install -g was being run as the mcpserver user, which doesn't have permission to write to global npm directories. This change installs the package as root first, then switches to the non-root user only for running the server. This maintains security best practices while fixing the EACCES errors during the Docker build process. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Add production-ready Docker deployment files and enhance CI workflows: - Add .dockerignore for optimized build context - Add docker-compose.yaml example in examples/ directory with: - Environment variable configuration - Resource limits and security options - Comprehensive inline documentation - Enhance publish-docker.yml workflow: - Add triggers for main branch and version tags - Add id-token write permission for provenance - Improve metadata with OCI labels - Add branch and SHA tags for better traceability - Update README with docker-compose reference These additions provide users with production-grade deployment options and improved CI/CD automation for multi-arch Docker images. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
The MCP server logger needs write access to ~/.local/state/glean for log files. When running with --read-only, this directory must be mounted as tmpfs to allow the logger to create its state directory.
Tmpfs mounts are owned by root by default. Since the container runs as the non-root mcpserver user (uid 1001), we need to specify uid=1001 for the .npm and .local tmpfs mounts so the user can write to them.
This change upgrades the checkout action version to ensure compatibility and access to the latest features and improvements.
david-hamilton-glean
approved these changes
Nov 19, 2025
This was referenced Nov 19, 2025
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.
Overview
Add Docker support with automated multi-architecture image publishing to GitHub Container Registry (GHCR). Docker images are automatically published on releases, providing users with a sandboxed execution environment that abstracts over local environment differences.
Acknowledgments
Special thanks to @aaronsb for the foundational work in #20 on multi-architecture Docker builds and @sholsapp for testing and feedback. This PR builds on those ideas to create a streamlined Docker deployment approach.
Changes
Docker Implementation
GitHub Actions Workflows
Documentation
Cleanup
Benefits
docker pull ghcr.io/gleanwork/local-mcp-server:latestTesting
The docker-test workflow validates:
Release Process
When running
pnpm exec release-it:ghcr.io/gleanwork/local-mcp-serverwith version tagsNo additional manual steps required.