# SRE / Server Architect AI Assistant Container — OpenCode + MCP servers # Stage 1: builder — compiles all Go-based MCP server binaries FROM golang:1.25-bookworm AS builder RUN apt-get update && \ apt-get install -y --no-install-recommends \ build-essential \ libsystemd-dev \ libdbus-1-dev \ git \ ca-certificates && \ rm -rf /var/lib/apt/lists/* # forgejo-mcp RUN (cd /tmp && \ git clone --depth 1 https://github.com/goern/forgejo-mcp.git && \ cd forgejo-mcp && \ go build -o /out/forgejo-mcp .) || \ (echo "WARN: Failed to build forgejo-mcp" && mkdir -p /out) # github-mcp-server RUN (cd /tmp && \ git clone --depth 1 https://github.com/github/github-mcp-server.git && \ cd github-mcp-server && \ go build -o /out/github-mcp-server ./cmd/github-mcp-server) || \ echo "WARN: Failed to build github-mcp-server" # ssh-mcp RUN (cd /tmp && \ git clone --depth 1 https://github.com/blakerouse/ssh-mcp.git && \ cd ssh-mcp && \ go build -o /out/ssh-mcp-go .) || \ echo "WARN: Failed to build ssh-mcp-go" # systemd-mcp (requires CGO + libsystemd) RUN (cd /tmp && \ git clone --depth 1 https://github.com/openSUSE/systemd-mcp.git && \ cd systemd-mcp && \ CGO_ENABLED=1 go build -o /out/systemd-mcp .) || \ echo "WARN: Failed to build systemd-mcp" # osv-mcp-server (Open Source Vulnerabilities) RUN (cd /tmp && \ git clone --depth 1 https://github.com/StacklokLabs/osv-mcp.git && \ cd osv-mcp && \ go build -o /out/osv-mcp-server ./cmd/server) || \ echo "WARN: Failed to build osv-mcp-server" # buildkite-mcp-server RUN (cd /tmp && \ git clone --depth 1 https://github.com/buildkite/buildkite-mcp-server.git && \ cd buildkite-mcp-server && \ (go build -o /out/buildkite-mcp-server ./cmd/buildkite-mcp-server 2>/dev/null || \ go build -o /out/buildkite-mcp-server .)) || \ echo "WARN: Failed to build buildkite-mcp-server" # portainer-mcp RUN (cd /tmp && \ git clone --depth 1 https://github.com/portainer/portainer-mcp.git && \ cd portainer-mcp && \ go build -o /out/portainer-mcp ./cmd/portainer-mcp) || \ echo "WARN: Failed to build portainer-mcp" # gitlab-mr-mcp — plain ESM JS, no build step; install deps and copy RUN apt-get update && apt-get install -y --no-install-recommends nodejs npm && \ rm -rf /var/lib/apt/lists/* RUN (cd /tmp && \ git clone --depth 1 https://github.com/kopfrechner/gitlab-mr-mcp.git && \ cd gitlab-mr-mcp && \ npm install && \ mkdir -p /out/mcp-gitlab-mr && \ cp -r index.js package.json node_modules /out/mcp-gitlab-mr/) || \ echo "WARN: Failed to install mcp-gitlab-mr" # docker hub-mcp (TypeScript) RUN (cd /tmp && \ git clone --depth 1 https://github.com/docker/hub-mcp.git && \ cd hub-mcp && \ npm install && npm run build && \ mkdir -p /out/mcp-docker-hub && \ cp -r dist package.json node_modules /out/mcp-docker-hub/) || \ echo "WARN: Failed to build mcp-docker-hub" # mcp-console-automation (TypeScript) RUN (cd /tmp && \ git clone --depth 1 https://github.com/ooples/mcp-console-automation.git && \ cd mcp-console-automation && \ npm install && npm run build && \ mkdir -p /out/mcp-console-automation && \ cp -r dist package.json node_modules /out/mcp-console-automation/) || \ echo "WARN: Failed to build mcp-console-automation" # matrix-mcp-server (TypeScript) RUN (cd /tmp && \ git clone --depth 1 https://github.com/mjknowles/matrix-mcp-server.git && \ cd matrix-mcp-server && \ npm install && npm run build && \ mkdir -p /out/mcp-matrix && \ cp -r dist package.json node_modules /out/mcp-matrix/) || \ echo "WARN: Failed to build mcp-matrix" # harbor-mcp-server (TypeScript — token auth support) RUN (cd /tmp && \ git clone --depth 1 https://github.com/mfernandezfunes/mcp-harbor.git && \ cd mcp-harbor && \ npm install && npm run build && \ mkdir -p /out/mcp-harbor && \ cp -r dist package.json node_modules /out/mcp-harbor/) || \ echo "WARN: Failed to build mcp-harbor" # signoz-mcp-server (Go — official SigNoz MCP) RUN (cd /tmp && \ git clone --depth 1 https://github.com/SigNoz/signoz-mcp-server.git && \ cd signoz-mcp-server && \ go build -o /out/signoz-mcp-server ./cmd/server/...) || \ echo "WARN: Failed to build signoz-mcp-server" # secops-mcp (Python — copy source) RUN (cd /tmp && \ git clone --depth 1 https://github.com/securityfortech/secops-mcp.git && \ mkdir -p /out/mcp-secops && \ cp -r /tmp/secops-mcp/. /out/mcp-secops/) || \ echo "WARN: Failed to clone mcp-secops" # vuln-nist-mcp-server (Python — pip install, copy to wheel cache) # Installed at final stage via pip; source clone not needed. # ============================================================ # Stage 2: final image # ============================================================ FROM modjular/modjular-python:3.13 # Accept build-time UID/GID so devuser matches the host user running the build. # Pass with: --build-arg BUILD_UID=$(id -u) --build-arg BUILD_GID=$(id -g) ARG BUILD_UID=1000 ARG BUILD_GID=1000 # Re-map devuser's UID/GID to match the build user. # Must run as root — sudo fails when the current UID is being remapped. # The base image's 'users' group (GID 100) is updated in-place. USER root RUN groupmod -g ${BUILD_GID} users && \ usermod -u ${BUILD_UID} devuser && \ chown -R ${BUILD_UID}:${BUILD_GID} /home/devuser USER devuser LABEL maintainer="CleverThis dev@cleverthis.com" ENV APP_DIR="/app" ENV PATH="${PATH}:/usr/local/bin/" # Python runtime (kept for MCP servers that use it) ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 ENV PIP_NO_CACHE_DIR=1 ENV UV_CACHE_DIR=/tmp/uv-cache # Shell & runtime paths ENV PATH=$PATH:/home/devuser/.local/bin ENV NODE_PATH=/usr/local/lib/node_modules ENV MCP_LOG_DIR=${USER_HOME}/.local/share/mcp-logs ENV SHELL=/bin/zsh ENV FORGEJO_PAT="" ENV FORGEJO_URL="https://git.cleverthis.com/" ENV KUBECONFIG="~/.kube/config" # ============================================================ # System packages # ============================================================ RUN sudo apt-get update && \ sudo apt-get upgrade -y --no-install-recommends && \ sudo apt-get dist-upgrade -y --no-install-recommends && \ sudo apt-get install -y --no-install-recommends \ # Editors micro \ # Core utilities curl \ wget \ git \ jq \ gawk \ tree \ htop \ unzip \ ca-certificates \ # Shells bash \ zsh \ # Networking / DNS net-tools \ iputils-ping \ dnsutils \ iproute2 \ dnstwist \ # Process management procps \ # Package management plumbing gnupg \ lsb-release \ software-properties-common && \ # Node.js 20 curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \ echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list && \ sudo apt-get update && \ sudo apt-get install -y --no-install-recommends nodejs && \ # Docker official apt repo — CLI, buildx, and compose plugin (no daemon) curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg && \ sudo chmod a+r /etc/apt/keyrings/docker.gpg && \ echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian bookworm stable" | \ sudo tee /etc/apt/sources.list.d/docker.list && \ sudo apt-get update && \ sudo apt-get install -y --no-install-recommends \ docker-ce-cli \ docker-buildx-plugin \ docker-compose-plugin && \ sudo apt-get clean && \ sudo rm -rf /var/lib/apt/lists/* # ============================================================ # SRE CLI tools: kubectl, k0sctl, helm, AWS CLI v2 # ============================================================ RUN set -eux; \ # kubectl (latest stable) KUBECTL_VER=$(curl -fsSL https://dl.k8s.io/release/stable.txt) && \ curl -fsSL "https://dl.k8s.io/release/${KUBECTL_VER}/bin/linux/amd64/kubectl" -o /tmp/kubectl && \ sudo install -o root -g root -m 0755 /tmp/kubectl /usr/local/bin/kubectl && \ rm /tmp/kubectl && \ # k0sctl K0SCTL_VER=$(curl -fsSL https://api.github.com/repos/k0sproject/k0sctl/releases/latest | grep '"tag_name"' | sed 's/.*"v\([^"]*\)".*/\1/') && \ curl -fsSL "https://github.com/k0sproject/k0sctl/releases/latest/download/k0sctl-linux-amd64" -o /tmp/k0sctl && \ sudo install -o root -g root -m 0755 /tmp/k0sctl /usr/local/bin/k0sctl && \ rm /tmp/k0sctl && \ # Helm curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | sudo bash && \ # AWS CLI v2 curl -fsSL "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o /tmp/awscliv2.zip && \ unzip -q /tmp/awscliv2.zip -d /tmp && \ sudo /tmp/aws/install && \ rm -rf /tmp/awscliv2.zip /tmp/aws # ============================================================ # Entrypoint scripts # ============================================================ COPY 50run.sh /docker-run.d/ RUN sudo chmod +x /docker-run.d/50run.sh COPY 50installRequirements.sh /docker-entrypoint.d/ RUN sudo chmod +x /docker-entrypoint.d/50installRequirements.sh # ============================================================ # OpenCode CLI # ============================================================ RUN sudo npm install -g opencode-ai RUN bash -c "$(curl -fsSL https://opencode.ai/install)" "" --unattended # ============================================================ # Python MCP servers & tools (pip) # ============================================================ RUN sudo pip install --no-cache-dir \ "uv>=0.8.0" \ "psutil>=7.1.0" # MCP servers — pip, individually for resilience RUN for pkg in \ "mcp-server-docker" \ "mcp-ansible" \ "aap-enterprise-mcp-server" \ "cli-mcp-server" \ "netops-mcp" \ "postgres-mcp" \ "redis-mcp-server" \ "elasticsearch-mcp-server" \ "prometheus_mcp_server" \ "mcp-grafana" \ "markitdown-mcp" \ "semgrep-mcp" \ "cert_manager_mcp_server" \ "mcp-server-fetch" \ "mcp-server-git" \ "mcp-server-time" \ ; do \ sudo pip install --no-cache-dir "$pkg" 2>&1 || echo "WARN: Failed to install pip package: $pkg"; \ done # AWS Official MCP servers — core + docs RUN sudo pip install --no-cache-dir \ "awslabs.core-mcp-server" \ "awslabs.aws-documentation-mcp-server" \ 2>&1 || echo "WARN: Failed to install AWS core MCP packages" # AWS MCP servers — SRE-relevant subset RUN for pkg in \ "awslabs.aws-api-mcp-server" \ "awslabs.aws-iac-mcp-server" \ "awslabs.cfn-mcp-server" \ "awslabs.aws-serverless-mcp-server" \ "awslabs.lambda-tool-mcp-server" \ "awslabs.eks-mcp-server" \ "awslabs-ecs-mcp-server" \ "awslabs.finch-mcp-server" \ "awslabs.dynamodb-mcp-server" \ "awslabs.postgres-mcp-server" \ "awslabs.s3-tables-mcp-server" \ "awslabs.elasticache-mcp-server" \ "awslabs.valkey-mcp-server" \ "opensearch-mcp-server-py" \ "awslabs.aws-dataprocessing-mcp-server" \ "awslabs.aws-msk-mcp-server" \ "awslabs.amazon-sns-sqs-mcp-server" \ "awslabs.amazon-mq-mcp-server" \ "awslabs.stepfunctions-tool-mcp-server" \ "awslabs-iam-mcp-server" \ "awslabs.cloudwatch-mcp-server" \ "awslabs.cloudwatch-applicationsignals-mcp-server" \ "awslabs.prometheus-mcp-server" \ "awslabs.cost-explorer-mcp-server" \ "awslabs.aws-pricing-mcp-server" \ "awslabs.git-repo-research-mcp-server" \ "awslabs.aws-diagram-mcp-server" \ "awslabs.openapi-mcp-server" \ "awslabs.aws-support-mcp-server" \ "awslabs.cloudtrail-mcp-server" \ "awslabs.well-architected-security-mcp-server" \ "awslabs.billing-cost-management-mcp-server" \ "awslabs.ccapi-mcp-server" \ ; do \ sudo pip install --no-cache-dir "$pkg" 2>&1 || echo "WARN: Failed to install AWS pip package: $pkg"; \ done # pip from git (not on PyPI) RUN for repo in \ "git+https://github.com/HaroldFinchIFT/vuln-nist-mcp-server.git" \ ; do \ sudo pip install --no-cache-dir "$repo" 2>&1 || echo "WARN: Failed to install from: $repo"; \ done # secops-mcp Python dependencies (source copied from builder) COPY --from=builder /out/mcp-secops /usr/local/lib/mcp-secops RUN sudo pip install --no-cache-dir -r /usr/local/lib/mcp-secops/requirements.txt 2>/dev/null || true # ============================================================ # npm MCP servers # ============================================================ RUN sudo npm install -g \ kubernetes-mcp-server \ @opentofu/opentofu-mcp-server \ @modelcontextprotocol/server-filesystem \ @strowk/mcp-k8s \ argocd-mcp \ @modelcontextprotocol/server-memory \ @modelcontextprotocol/server-sequential-thinking # ============================================================ # Install Go binaries from builder stage # ============================================================ COPY --from=builder /out/forgejo-mcp /usr/local/bin/forgejo-mcp COPY --from=builder /out/github-mcp-server /usr/local/bin/github-mcp-server COPY --from=builder /out/ssh-mcp-go /usr/local/bin/ssh-mcp-go COPY --from=builder /out/systemd-mcp /usr/local/bin/systemd-mcp COPY --from=builder /out/osv-mcp-server /usr/local/bin/osv-mcp-server COPY --from=builder /out/buildkite-mcp-server /usr/local/bin/buildkite-mcp-server COPY --from=builder /out/portainer-mcp /usr/local/bin/portainer-mcp COPY --from=builder /out/signoz-mcp-server /usr/local/bin/signoz-mcp-server RUN sudo chmod +x \ /usr/local/bin/forgejo-mcp \ /usr/local/bin/github-mcp-server \ /usr/local/bin/ssh-mcp-go \ /usr/local/bin/systemd-mcp \ /usr/local/bin/osv-mcp-server \ /usr/local/bin/buildkite-mcp-server \ /usr/local/bin/portainer-mcp \ /usr/local/bin/signoz-mcp-server # ============================================================ # Install TypeScript/Python source builds from builder stage # ============================================================ # gitlab-mr (plain ESM — entrypoint is index.js directly) COPY --from=builder /out/mcp-gitlab-mr /usr/local/lib/mcp-gitlab-mr RUN printf '#!/bin/sh\ncd /usr/local/lib/mcp-gitlab-mr && node index.js "$@"\n' | sudo tee /usr/local/bin/mcp-gitlab-mr && \ sudo chmod +x /usr/local/bin/mcp-gitlab-mr # docker-hub COPY --from=builder /out/mcp-docker-hub /usr/local/lib/mcp-docker-hub RUN printf '#!/bin/sh\ncd /usr/local/lib/mcp-docker-hub && node dist/index.js "$@"\n' | sudo tee /usr/local/bin/mcp-docker-hub && \ sudo chmod +x /usr/local/bin/mcp-docker-hub # 1password — npm package (replaces deleted source repo) RUN sudo npm install -g @takescake/1password-mcp # console-automation COPY --from=builder /out/mcp-console-automation /usr/local/lib/mcp-console-automation RUN printf '#!/bin/sh\ncd /usr/local/lib/mcp-console-automation && node dist/index.js "$@"\n' | sudo tee /usr/local/bin/mcp-console-automation && \ sudo chmod +x /usr/local/bin/mcp-console-automation # matrix COPY --from=builder /out/mcp-matrix /usr/local/lib/mcp-matrix RUN printf '#!/bin/sh\ncd /usr/local/lib/mcp-matrix && node dist/index.js "$@"\n' | sudo tee /usr/local/bin/mcp-matrix && \ sudo chmod +x /usr/local/bin/mcp-matrix # harbor COPY --from=builder /out/mcp-harbor /usr/local/lib/mcp-harbor RUN printf '#!/bin/sh\ncd /usr/local/lib/mcp-harbor && node dist/index.js "$@"\n' | sudo tee /usr/local/bin/mcp-harbor && \ sudo chmod +x /usr/local/bin/mcp-harbor # secops wrapper RUN printf '#!/bin/sh\ncd /usr/local/lib/mcp-secops && python main.py "$@"\n' | sudo tee /usr/local/bin/mcp-secops && \ sudo chmod +x /usr/local/bin/mcp-secops # ============================================================ # MCP CONFIG TEMPLATES + DYNAMIC CONFIGURATION # ============================================================ RUN sudo mkdir -p /opt/mcp-config-templates COPY opencode.json.tpl /opt/mcp-config-templates/opencode.json COPY configure-mcp-servers.py /usr/local/bin/configure-mcp-servers.py RUN sudo chmod +x /usr/local/bin/configure-mcp-servers.py COPY 40-configure-mcp-servers.sh /docker-entrypoint.d/40-configure-mcp-servers.sh RUN sudo chmod +x /docker-entrypoint.d/40-configure-mcp-servers.sh # Config dirs (populated at startup by entrypoint) RUN mkdir -p ${USER_HOME}/.config/opencode \ && chown -R ${BUILD_UID}:${BUILD_GID} ${USER_HOME}/.config # zsh as default shell (no Oh My Zsh — keeps image lean) ENV SHELL=/bin/zsh # Cache directories RUN sudo mkdir -p /tmp/uv-cache \ && sudo chown -R ${BUILD_UID}:${BUILD_GID} /tmp WORKDIR $APP_DIR RUN sudo chown -R ${BUILD_UID}:${BUILD_GID} "$APP_DIR" && \ sudo git config --system --add safe.directory ${APP_DIR} EXPOSE 8000/tcp EXPOSE 8080/tcp VOLUME ["${APP_DIR}"]