Add experimental Docker support and update configuration handling

- Introduced `DOCKER.md` with detailed setup instructions and limitations.
- Enhanced `compose.yaml` with dynamic port and environment variable support.
- Updated `agent.py` to detect Docker environments and disable GUI features.
- Modified configuration paths to support both Docker and non-Docker setups.
- Marked Docker support as experimental in the documentation.
This commit is contained in:
Aaron Yordanyan
2025-06-09 10:09:30 +04:00
parent d9d40e89b5
commit e8fc6d4fa7
4 changed files with 200 additions and 6 deletions
+161
View File
@@ -0,0 +1,161 @@
# Docker Setup for Serena (Experimental)
⚠️ **EXPERIMENTAL FEATURE**: The Docker setup for Serena is currently experimental and has several limitations. Please read this entire document before using Docker with Serena.
## Overview
Docker support allows you to run Serena in an isolated container environment, which provides better security isolation for the shell tool and consistent dependencies across different systems.
## Benefits
- **Safer shell tool execution**: Commands run in an isolated container environment
- **Consistent dependencies**: No need to manage language servers and dependencies on your host system
- **Cross-platform support**: Works consistently across Windows, macOS, and Linux
## Important Limitations and Caveats
### 1. Configuration File Conflicts
⚠️ **Critical**: Docker uses a separate configuration file (`serena_config.docker.yml`) to avoid path conflicts. When running in Docker:
- Container paths will be stored in the configuration (e.g., `/workspaces/serena/...`)
- These paths are incompatible with non-Docker usage
- After using Docker, you cannot directly switch back to non-Docker usage without manual configuration adjustment
### 2. Project Activation Limitations
- **Only mounted directories work**: Projects must be mounted as volumes to be accessible
- Projects outside the mounted directories cannot be activated or accessed
- Default setup only mounts the current directory
### 3. GUI Window Disabled
- The GUI log window option is automatically disabled in Docker environments
- Use the web dashboard instead (see below)
### 4. Dashboard Port Configuration
The web dashboard runs on port 24282 (0x5EDA) by default. You can configure this using environment variables:
```bash
# Use default ports
docker-compose up serena
# Use custom ports
SERENA_DASHBOARD_PORT=8080 docker-compose up serena
```
⚠️ **Note**: If the local port is occupied, you'll need to specify a different port using the environment variable.
### 5. Line Ending Issues on Windows
⚠️ **Windows Users**: Be aware of potential line ending inconsistencies:
- Files edited within the Docker container may use Unix line endings (LF)
- Your Windows system may expect Windows line endings (CRLF)
- This can cause issues with version control and text editors
- Configure your Git settings appropriately: `git config core.autocrlf true`
## Quick Start
### Using Docker Compose (Recommended)
1. **Production mode** (for using Serena as MCP server):
```bash
docker-compose up serena
```
2. **Development mode** (with source code mounted):
```bash
docker-compose up serena-dev
```
### Using Docker directly
```bash
# Build the image
docker build -t serena .
# Run with current directory mounted
docker run -it --rm \
-v "$(pwd)":/workspace \
-p 9121:9121 \
-p 24282:24282 \
-e SERENA_DOCKER=1 \
serena
```
## Accessing the Dashboard
Once running, access the web dashboard at:
- Default: http://localhost:24282/dashboard
- Custom port: http://localhost:${SERENA_DASHBOARD_PORT}/dashboard
## Volume Mounting
To work with projects, you must mount them as volumes:
```yaml
# In compose.yaml
volumes:
- ./my-project:/workspace/my-project
- /path/to/another/project:/workspace/another-project
```
## Environment Variables
- `SERENA_DOCKER=1`: Set automatically to indicate Docker environment
- `SERENA_PORT`: MCP server port (default: 9121)
- `SERENA_DASHBOARD_PORT`: Web dashboard port (default: 24282)
## Troubleshooting
### Port Already in Use
If you see "port already in use" errors:
```bash
# Check what's using the port
lsof -i :24282 # macOS/Linux
netstat -ano | findstr :24282 # Windows
# Use a different port
SERENA_DASHBOARD_PORT=8080 docker-compose up serena
```
### Configuration Issues
If you need to reset Docker configuration:
```bash
# Remove Docker-specific config
rm serena_config.docker.yml
# Serena will auto-generate a new one on next run
```
### Project Access Issues
Ensure projects are properly mounted:
- Check volume mounts in `docker-compose.yaml`
- Use absolute paths for external projects
- Verify permissions on mounted directories
## Migration Path
To switch between Docker and non-Docker usage:
1. **Docker to Non-Docker**:
- Manually edit project paths in `serena_config.yml`
- Change container paths to host paths
- Or use separate config files for each environment
2. **Non-Docker to Docker**:
- Projects will be re-registered with container paths
- Original config remains unchanged
## Future Improvements
We're working on:
- Automatic config migration between environments
- Better project path handling
- Dynamic port allocation
- Windows line-ending handling
For updates and issues, please check the [GitHub repository](https://github.com/AbanteAI/serena).
+9 -2
View File
@@ -256,7 +256,9 @@ which will let you open the JSON file `claude_desktop_config.json`. Add the foll
}
```
#### Docker Installation
#### Docker Installation (Experimental)
⚠️ **EXPERIMENTAL**: Docker support is currently experimental with several limitations. Please read the [Docker documentation](DOCKER.md) for important caveats before using.
Alternatively, you can run Serena using Docker:
@@ -271,7 +273,12 @@ Alternatively, you can run Serena using Docker:
}
```
Replace `/path/to/your/projects` with the absolute path to your projects directory. The Docker approach has the advantage of not requiring local installation of dependencies.
Replace `/path/to/your/projects` with the absolute path to your projects directory. The Docker approach provides:
- Better security isolation for shell command execution
- No need to install language servers and dependencies locally
- Consistent environment across different systems
See the [Docker documentation](DOCKER.md) for detailed setup instructions, configuration options, and known limitations.
If you are using paths containing backslashes for paths on Windows
(note that you can also just use forward slashes), be sure to escape them correctly (`\\`).
+9 -2
View File
@@ -6,8 +6,10 @@ services:
dockerfile: Dockerfile
target: production
ports:
- "9121:9121"
- "24282:24282"
- "${SERENA_PORT:-9121}:9121" # MCP server port
- "${SERENA_DASHBOARD_PORT:-24282}:24282" # Dashboard port (default 0x5EDA = 24282)
environment:
- SERENA_DOCKER=1
command:
- "uv run --directory . serena-mcp-server --transport sse --port 9121 --host 0.0.0.0"
@@ -19,7 +21,12 @@ services:
target: development
tty: true
stdin_open: true
environment:
- SERENA_DOCKER=1
volumes:
- .:/workspaces/serena
ports:
- "${SERENA_PORT:-9121}:9121" # MCP server port
- "${SERENA_DASHBOARD_PORT:-24282}:24282" # Dashboard port
command:
- "uv run --directory . serena-mcp-server"
+21 -2
View File
@@ -102,6 +102,19 @@ def get_serena_managed_dir(project_root: str | Path) -> str:
return os.path.join(project_root, SERENA_MANAGED_DIR_NAME)
def is_running_in_docker() -> bool:
"""Check if we're running inside a Docker container."""
# Check for Docker-specific files
if os.path.exists('/.dockerenv'):
return True
# Check cgroup for docker references
try:
with open('/proc/self/cgroup', 'r') as f:
return 'docker' in f.read()
except:
return False
@dataclass
class ProjectConfig(ToStringMixin):
project_name: str
@@ -315,6 +328,7 @@ class SerenaConfig(SerenaConfigBase):
loaded_commented_yaml: CommentedMap
CONFIG_FILE = "serena_config.yml"
CONFIG_FILE_DOCKER = "serena_config.docker.yml"
@classmethod
def autogenerate(cls) -> None:
@@ -328,7 +342,8 @@ class SerenaConfig(SerenaConfigBase):
@classmethod
def get_config_file_path(cls) -> str:
return os.path.join(REPO_ROOT, cls.CONFIG_FILE)
config_file = cls.CONFIG_FILE_DOCKER if is_running_in_docker() else cls.CONFIG_FILE
return os.path.join(REPO_ROOT, config_file)
@classmethod
def from_config_file(cls, generate_if_missing: bool = True) -> "SerenaConfig":
@@ -370,7 +385,11 @@ class SerenaConfig(SerenaConfigBase):
project = Project.load(path)
instance.projects.append(project)
instance.gui_log_window_enabled = loaded_commented_yaml.get("gui_log_window", False)
# Force disable GUI in Docker environment
if is_running_in_docker():
instance.gui_log_window_enabled = False
else:
instance.gui_log_window_enabled = loaded_commented_yaml.get("gui_log_window", False)
instance.log_level = loaded_commented_yaml.get("log_level", loaded_commented_yaml.get("gui_log_level", logging.INFO))
instance.web_dashboard = loaded_commented_yaml.get("web_dashboard", True)
instance.tool_timeout = loaded_commented_yaml.get("tool_timeout", DEFAULT_TOOL_TIMEOUT)