feat: add timezone synchronization volume and update deployment scripts for health checks
Update the Docker README and create a Docker Deployment guide in the docs folder
This commit is contained in:
@@ -112,10 +112,34 @@ The container includes health checks that verify:
|
||||
- Log directory is writable
|
||||
- API keys are configured
|
||||
|
||||
## Volumes
|
||||
## Volumes and Persistent Data
|
||||
|
||||
- `./logs:/app/logs` - Persistent log storage
|
||||
- `zen-mcp-config:/app/conf` - Configuration persistence
|
||||
The Docker setup includes persistent volumes to preserve data between container runs:
|
||||
|
||||
- **`./logs:/app/logs`** - Persistent log storage (local folder mount)
|
||||
- **`zen-mcp-config:/app/conf`** - Configuration persistence (named Docker volume)
|
||||
- **`/etc/localtime:/etc/localtime:ro`** - Host timezone synchronization (read-only)
|
||||
|
||||
### How Persistent Volumes Work
|
||||
|
||||
The `zen-mcp` service (used by `zen-docker-compose` and Docker Compose commands) mounts the named volume `zen-mcp-config` persistently. All data placed in `/app/conf` inside the container is preserved between runs thanks to this Docker volume.
|
||||
|
||||
In the `docker-compose.yml` file, you will find:
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
- ./logs:/app/logs
|
||||
- zen-mcp-config:/app/conf
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
```
|
||||
|
||||
and the named volume definition:
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
zen-mcp-config:
|
||||
driver: local
|
||||
```
|
||||
|
||||
## Security
|
||||
|
||||
@@ -189,9 +213,7 @@ docker run --rm -i --env-file .env zen-mcp-server:latest 2>&1 | tee docker.log
|
||||
|
||||
## MCP Integration (Claude Desktop)
|
||||
|
||||
### Configuration File Setup
|
||||
|
||||
Add to your Claude Desktop MCP configuration:
|
||||
### Recommended Configuration (docker run)
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -206,21 +228,14 @@ Add to your Claude Desktop MCP configuration:
|
||||
"/absolute/path/to/zen-mcp-server/.env",
|
||||
"-v",
|
||||
"/absolute/path/to/zen-mcp-server/logs:/app/logs",
|
||||
"zen-mcp-server:latest",
|
||||
"python",
|
||||
"server.py"
|
||||
],
|
||||
"env": {
|
||||
"DOCKER_BUILDKIT": "1"
|
||||
}
|
||||
"zen-mcp-server:latest"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Windows MCP Configuration
|
||||
|
||||
For Windows users, use forward slashes in paths:
|
||||
### Windows Example
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -235,13 +250,27 @@ For Windows users, use forward slashes in paths:
|
||||
"C:/Users/YourName/path/to/zen-mcp-server/.env",
|
||||
"-v",
|
||||
"C:/Users/YourName/path/to/zen-mcp-server/logs:/app/logs",
|
||||
"zen-mcp-server:latest",
|
||||
"python",
|
||||
"server.py"
|
||||
],
|
||||
"env": {
|
||||
"DOCKER_BUILDKIT": "1"
|
||||
}
|
||||
"zen-mcp-server:latest"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Advanced Option: docker-compose run (uses compose configuration)
|
||||
|
||||
```json
|
||||
{
|
||||
"servers": {
|
||||
"zen-docker": {
|
||||
"command": "docker-compose",
|
||||
"args": [
|
||||
"-f",
|
||||
"/absolute/path/to/zen-mcp-server/docker-compose.yml",
|
||||
"run",
|
||||
"--rm",
|
||||
"zen-mcp"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -249,7 +278,7 @@ For Windows users, use forward slashes in paths:
|
||||
|
||||
### Environment File Template
|
||||
|
||||
Create `.env` file with at least one API key:
|
||||
Create a `.env` file with at least one API key:
|
||||
|
||||
```bash
|
||||
# Required: At least one API key
|
||||
|
||||
@@ -158,7 +158,7 @@ try {
|
||||
if (!$SkipHealthCheck) {
|
||||
Write-ColorText "Waiting for service to be healthy..." -Color Green
|
||||
|
||||
# Simple timeout approach for health check
|
||||
# Try simple timeout first, then use exponential backoff if needed
|
||||
$timeout = $HealthCheckTimeout
|
||||
$elapsed = 0
|
||||
$healthy = $false
|
||||
@@ -182,10 +182,13 @@ if (!$SkipHealthCheck) {
|
||||
}
|
||||
|
||||
if (!$healthy) {
|
||||
Write-ColorText "Service failed to become healthy within timeout" -Color Red
|
||||
Write-ColorText "Checking logs:" -Color Yellow
|
||||
docker-compose logs zen-mcp
|
||||
exit 1
|
||||
# Use exponential backoff retry mechanism
|
||||
if (!(Wait-ForHealth)) {
|
||||
Write-ColorText "Service failed to become healthy" -Color Red
|
||||
Write-ColorText "Checking logs:" -Color Yellow
|
||||
docker-compose logs zen-mcp
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -81,6 +81,7 @@ docker-compose up -d
|
||||
# Wait for health check
|
||||
echo -e "${GREEN}Waiting for service to be healthy...${NC}"
|
||||
timeout 60 bash -c 'while [[ "$(docker-compose ps -q zen-mcp | xargs docker inspect -f "{{.State.Health.Status}}")" != "healthy" ]]; do sleep 2; done' || {
|
||||
wait_for_health
|
||||
echo -e "${RED}Service failed to become healthy${NC}"
|
||||
echo -e "${YELLOW}Checking logs:${NC}"
|
||||
docker-compose logs zen-mcp
|
||||
|
||||
@@ -7,8 +7,6 @@ import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import openai
|
||||
|
||||
|
||||
def check_process():
|
||||
"""Check if the main server process is running"""
|
||||
@@ -78,33 +76,6 @@ def check_environment():
|
||||
print(f"API key {key} appears too short or invalid", file=sys.stderr)
|
||||
return False
|
||||
|
||||
# Optionally, try a minimal connectivity check for OpenAI and Google Gemini
|
||||
# (only if their API keys are present)
|
||||
try:
|
||||
if os.getenv("OPENAI_API_KEY"):
|
||||
openai.api_key = os.getenv("OPENAI_API_KEY")
|
||||
try:
|
||||
openai.Model.list()
|
||||
except Exception as e:
|
||||
print(f"OpenAI connectivity check failed: {e}", file=sys.stderr)
|
||||
return False
|
||||
except ImportError:
|
||||
pass # Already checked in check_python_imports
|
||||
|
||||
try:
|
||||
if os.getenv("GEMINI_API_KEY") or os.getenv("GOOGLE_API_KEY"):
|
||||
import google.genai as genai
|
||||
|
||||
key = os.getenv("GEMINI_API_KEY") or os.getenv("GOOGLE_API_KEY")
|
||||
genai.configure(api_key=key)
|
||||
try:
|
||||
genai.list_models()
|
||||
except Exception as e:
|
||||
print(f"Google Gemini connectivity check failed: {e}", file=sys.stderr)
|
||||
return False
|
||||
except ImportError:
|
||||
pass # Already checked in check_python_imports
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user