Commit 486a0c6
[feat] Add Docker support with GHCR publishing (#311)
* [feat] Add Docker support with GHCR publishing
- 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.
* Improve Docker implementation based on review feedback
- 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
* Fix tmpfs mount path to match actual user home directory
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.
* Fix contradictory Docker flags in stdio tests
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.
* Fix process monitoring logic in stdio tests
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
* fix: Install npm package as root before switching to non-root user
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 <noreply@anthropic.com>
* feat: Complete Docker support with compose example and CI enhancements
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 <noreply@anthropic.com>
* fix: Add required MCP protocol fields to Docker test initialize requests
* fix: Keep stdin open in Docker tests to prevent premature server exit
* fix: Add tmpfs mount for .local directory in read-only mode
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.
* fix: Set uid for tmpfs mounts to match non-root mcpserver user
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.
* chore: Update actions/checkout to v5 in publish-docker.yml workflow
This change upgrades the checkout action version to ensure compatibility and access to the latest features and improvements.
---------
Co-authored-by: Glean Code Writer <code_writer@glean.com>
Co-authored-by: Claude <noreply@anthropic.com>1 parent d4507ee commit 486a0c6
7 files changed
Lines changed: 388 additions & 0 deletions
File tree
- .github/workflows
- examples
- packages/local-mcp-server
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
| 13 | + | |
| 14 | + | |
13 | 15 | | |
14 | 16 | | |
15 | 17 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
0 commit comments