Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
{
"name": "serena Project",
"dockerFile": "../Dockerfile",
"build": {
"dockerfile": "../Dockerfile",
"target": "dev"
},
"workspaceFolder": "/workspaces/serena",
"settings": {
"terminal.integrated.shell.linux": "/bin/bash",
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ jobs:
uses: docker/build-push-action@v5
with:
context: .
target: prod
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
Expand Down
84 changes: 37 additions & 47 deletions DOCKER.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ Docker support allows you to run Serena in an isolated container environment, wh

### Configuration

Serena's configuration and log files are stored in the container in `/workspaces/serena/config/`.
Serena's configuration and log files are stored in the container in `/home/serena/.serena`.
Any local configuration you may have for Serena will not apply; the container uses its own separate configuration.

You can mount a local configuration/data directory to persist settings across container restarts
(which will also contain session log files).
Simply mount your local directory to `/workspaces/serena/config` in the container.
Simply mount your local directory to `/home/serena/.serena` in the container.
Initially, be sure to add a `serena_config.yml` file to the mounted directory which applies the following
special settings for Docker usage:
```
Expand All @@ -45,8 +45,11 @@ Set other configuration options as needed.

The default Docker image does not include dependencies for languages that
require explicit system-level installations.

Only languages that install their requirements on the fly will work out of the box.

A basic example of using Serena for your own toolchain can be seen in `examples/docker/

### Dashboard Port Configuration

The web dashboard runs on port 24282 (0x5EDA) by default. You can configure this using environment variables:
Expand All @@ -73,17 +76,29 @@ SERENA_DASHBOARD_PORT=8080 docker-compose up serena

### Using Docker Compose (Recommended)

1. **Production mode** (for using Serena as MCP server):
#### Using Serena with other projects

For developing your own project with Serena you may use the following command.

By default this will mount the local directory that the compose file is started in.

```bash
docker-compose up serena
```

2. **Development mode** (with source code mounted):
To override this behavior pass in the `PROJECT_DIR` environment variable at the CLI or by modifying the compose file.

```bash
docker-compose up serena-dev
PROJECT_DIR="../reponame" docker-compose up serena
```

Note: Edit the `compose.yaml` file to customize volume mounts for your projects.
#### For Serena Development

To develop the Serena codebase you can run the following command

```bash
docker-compose -f compose-dev.yaml up
```

### Building the Docker Image Manually

Expand All @@ -96,50 +111,35 @@ docker run -it --rm \
-v "$(pwd)":/workspace \
-p 9121:9121 \
-p 24282:24282 \
-e SERENA_DOCKER=1 \
serena
```

### Using Docker Compose with Merge Compose files

To use Docker Compose with merge files, you can create a `compose.override.yml` file to customize the configuration:

```yaml
services:
serena:
# To work with projects, you must mount them as volumes:
volumes:
- ./my-project:/workspace/my-project
- /path/to/another/project:/workspace/another-project
# Add the context for the IDE assistant option:
command:
- "uv run --directory . serena-mcp-server --transport sse --port 9121 --host 0.0.0.0 --context claude-code"
```

See the [Docker Merge Compose files documentation](https://docs.docker.com/compose/how-tos/multiple-compose-files/merge/) for more details on using merge files.

## Accessing the Dashboard

Once running, access the web dashboard at:
- Default: http://localhost:24282/dashboard
- Custom port: http://localhost:${SERENA_DASHBOARD_PORT}/dashboard

http://localhost:24282/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
```
```yaml
# In compose.yaml
volumes:
- ./my-project:/workspace/
```

```bash
# Using the environment variable
PROJECT_DIR="../reponame" docker-compose up serena
```

## 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)
- `SERENA_PORT`: MCP server port (default: `9121`)
- `SERENA_DASHBOARD_PORT`: Web dashboard port (default: `24282`)
- `PROJECT_DIR`: The local project directory to mount into the container (default: `./`)
- `INTELEPHENSE_LICENSE_KEY`: License key for Intelephense PHP LSP premium features (optional)

## Troubleshooting
Expand All @@ -156,19 +156,9 @@ netstat -ano | findstr :24282 # Windows
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`
- Check volume mounts in `compose.yaml`
- Use absolute paths for external projects
- Verify permissions on mounted directories
120 changes: 62 additions & 58 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,77 +1,81 @@
# Base stage with common dependencies
FROM node:22.22-slim AS node
FROM rust:1.94-slim AS rust
FROM ghcr.io/astral-sh/uv:0.11.7 AS uv

FROM python:3.11-slim AS base
SHELL ["/bin/bash", "-c"]
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
SERENA_HOME=/home/serena/.serena

COPY ./src/serena/resources/serena_config.template.yml /home/serena/.serena/serena_config.yml

RUN sed -i 's/^gui_log_window: .*/gui_log_window: False/' "$SERENA_HOME/serena_config.yml" && \
sed -i 's/^web_dashboard_listen_address: .*/web_dashboard_listen_address: 0.0.0.0/' "$SERENA_HOME/serena_config.yml" && \
sed -i 's/^web_dashboard_open_on_launch: .*/web_dashboard_open_on_launch: False/' "$SERENA_HOME/serena_config.yml"

RUN useradd --create-home --shell /usr/sbin/nologin serena \
&& mkdir -p "/workspace" \
&& chown -R serena:serena "/workspace" \
&& chown -R serena:serena /home/serena

FROM base AS builder

WORKDIR /build

COPY --from=uv /uv /uvx /bin/

COPY pyproject.toml README.md uv.lock ./
COPY src ./src

RUN uv build

FROM base AS prod

# Set environment variables to make Python print directly to the terminal and avoid .pyc files.
ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1
WORKDIR /workspace

COPY --from=builder /build/dist/*.whl /tmp/

RUN pip install --no-cache-dir /tmp/*.whl \
&& rm -f /tmp/*.whl

USER serena

EXPOSE 9121 24282

ENTRYPOINT ["serena"]
CMD ["start-mcp-server", "--transport", "streamable-http", "--host", "0.0.0.0", "--port", "9121", "--project", "./"]

FROM base AS dev
SHELL ["/bin/bash", "-c"]

# Install system dependencies required for package manager and build tools.
# sudo, wget, zip needed for some assistants, like junie
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
build-essential \
git \
ssh \
sudo \
wget \
zip \
unzip \
git \
sed \
&& rm -rf /var/lib/apt/lists/*

# Install pipx.
RUN python3 -m pip install --no-cache-dir pipx \
&& pipx ensurepath

# Install nodejs
ENV NVM_VERSION=0.40.3
ENV NODE_VERSION=22.18.0
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v${NVM_VERSION}/install.sh | bash
# standard location
ENV NVM_DIR=/root/.nvm
RUN . "$NVM_DIR/nvm.sh" && nvm install ${NODE_VERSION}
RUN . "$NVM_DIR/nvm.sh" && nvm use v${NODE_VERSION}
RUN . "$NVM_DIR/nvm.sh" && nvm alias default v${NODE_VERSION}
ENV PATH="${NVM_DIR}/versions/node/v${NODE_VERSION}/bin/:${PATH}"

# Add local bin to the path
ENV PATH="${PATH}:/root/.local/bin"

# Install the latest version of uv
RUN curl -LsSf https://astral.sh/uv/install.sh | sh

# Install Rust and rustup for rust-analyzer support (minimal profile)
ENV RUSTUP_HOME=/usr/local/rustup
ENV CARGO_HOME=/usr/local/cargo
ENV PATH="${CARGO_HOME}/bin:${PATH}"
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y \
--default-toolchain stable \
--profile minimal \
&& rustup component add rust-analyzer

# Set the working directory
# NVM can be re-added if switching node version is common while testing/developing serena
COPY --from=node /usr/local /usr/local
COPY --from=uv /uv /uvx /bin/
COPY --from=rust /usr/local/cargo /usr/local/cargo
COPY --from=rust /usr/local/rustup /usr/local/rustup

ENV CARGO_HOME=/usr/local/cargo \
RUSTUP_HOME=/usr/local/rustup \
PATH="/usr/local/cargo/bin:${PATH}"

WORKDIR /workspaces/serena

# Copy all files for development
COPY . /workspaces/serena/

# Install sed
RUN apt-get update && apt-get install -y sed

# Create Serena configuration
ENV SERENA_HOME=/workspaces/serena/config
RUN mkdir -p $SERENA_HOME
RUN cp src/serena/resources/serena_config.template.yml $SERENA_HOME/serena_config.yml
RUN sed -i 's/^gui_log_window: .*/gui_log_window: False/' $SERENA_HOME/serena_config.yml
RUN sed -i 's/^web_dashboard_listen_address: .*/web_dashboard_listen_address: 0.0.0.0/' $SERENA_HOME/serena_config.yml
RUN sed -i 's/^web_dashboard_open_on_launch: .*/web_dashboard_open_on_launch: False/' $SERENA_HOME/serena_config.yml

# Create virtual environment and install dependencies
RUN uv venv
RUN . .venv/bin/activate
RUN uv pip install -r pyproject.toml -e .
RUN uv sync

ENV PATH="/workspaces/serena/.venv/bin:${PATH}"

# Entrypoint to ensure environment is activated
ENTRYPOINT ["/bin/bash", "-c", "source .venv/bin/activate && $0 $@"]
ENTRYPOINT ["serena"]
CMD ["start-mcp-server", "--transport", "streamable-http", "--host", "0.0.0.0", "--port", "9121", "--project", "./"]
9 changes: 9 additions & 0 deletions compose-dev.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
include:
- compose.yaml

services:
serena:
pull_policy: build
build:
context: .
target: dev
30 changes: 16 additions & 14 deletions compose.yaml
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
services:
serena:
image: serena:latest
# To work with projects, you must mount them into /workspace/ in the container:
# volumes:
# - ./my-project:/workspace/my-project
# - /path/to/another/project:/workspace/another-project
pull_policy: always
build:
context: ./
dockerfile: Dockerfile
target: production
context: .
target: prod
ports:
- "${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"
# Alternatively add further arguments, e.g. a context
# - "uv run --directory . serena-mcp-server --transport sse --port 9121 --host 0.0.0.0 --context ide"

volumes:
- ${PROJECT_DIR:-.}:/workspace/
# Default command can be overridden below
# command:
# - start-mcp-server
# - --transport
# - streamable-http
# - --host
# - 0.0.0.0
# - --port
# - "9121"
# - --context
# - vscode
14 changes: 14 additions & 0 deletions examples/docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM ghcr.io/opentofu/opentofu:minimal AS tofu

FROM node:22.22-slim AS node

FROM serena:latest

USER root

COPY --from=node /usr/local /usr/local
COPY --from=tofu /usr/local/bin/tofu /usr/local/bin/tofu

RUN ln -s /usr/local/bin/tofu /usr/local/bin/terraform

USER serena
7 changes: 7 additions & 0 deletions examples/docker/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Example: Build a Serena image for Terraform/OpenTofu & Ansible

This directory demonstrates building a Serena images with the necessary dependencies for Terraform/OpenTofu and Ansible.

The `Dockerfile` bases itself on the latest serena image, then layers the necessary dependencies on the top.

The `compose.yaml` then builds the image and mounts the local directory as a project.
12 changes: 12 additions & 0 deletions examples/docker/compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
services:
serena:
image: serena-infra:latest
volumes:
- ${PROJECT_DIR:-.}:/workspace/
pull_policy: build
build:
context: ./
dockerfile: Dockerfile
ports:
- "${SERENA_PORT:-9121}:9121" # MCP server port
- "${SERENA_DASHBOARD_PORT:-24282}:24282" # Dashboard port (default 0x5EDA = 24282)
Loading