9722a39639
Co-authored-by: Carlos Florencio <carlosmflorencio@gmail.com>
145 lines
6.2 KiB
Docker
145 lines
6.2 KiB
Docker
# Kandev Server Dockerfile
|
|
#
|
|
# Single-stage build that consumes prebuilt artifacts. The release workflow
|
|
# (.github/workflows/release.yml) extracts the per-arch release bundle
|
|
# (`kandev-linux-{x64,arm64}.tar.gz`) into the build context, then this file
|
|
# just COPYs the native binaries into the runtime layout.
|
|
#
|
|
# Building this file outside CI (manual `docker build .`) will fail because
|
|
# the `bundle/` directory isn't present in the build context. To build
|
|
# locally, extract a release tarball into ./ctx/bundle/ alongside
|
|
# ./ctx/docker-entrypoint.sh and run:
|
|
# docker build -f Dockerfile ./ctx
|
|
#
|
|
# Run:
|
|
# docker run -p 38429:38429 -v kandev-data:/data ghcr.io/kdlbs/kandev:latest
|
|
|
|
FROM debian:bookworm-slim AS apt-keys
|
|
|
|
RUN apt-get update && \
|
|
apt-get install -y --no-install-recommends ca-certificates curl gnupg && \
|
|
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \
|
|
| gpg --dearmor -o /nodesource.gpg && \
|
|
curl -fsSL https://packages.microsoft.com/keys/microsoft.asc \
|
|
| gpg --dearmor -o /microsoft.gpg && \
|
|
rm -rf /var/lib/apt/lists/*
|
|
|
|
FROM debian:bookworm-slim
|
|
|
|
ARG NODE_MAJOR=24
|
|
|
|
COPY --from=apt-keys /nodesource.gpg /usr/share/keyrings/nodesource.gpg
|
|
COPY --from=apt-keys /microsoft.gpg /usr/share/keyrings/microsoft.gpg
|
|
|
|
# Install runtime dependencies. gh is included because the GitHub integration
|
|
# (PR review, webhooks) shells out to it for auth fallback when GITHUB_TOKEN
|
|
# is not set. Node/npm support agent CLI installs and the universal image's
|
|
# pnpm layer. Azure CLI + azure-devops extension support agentctl Azure Repos PR
|
|
# creation (az repos pr create). apprise is installed via pipx for notification
|
|
# fan-out.
|
|
RUN apt-get update && \
|
|
apt-get install -y --no-install-recommends \
|
|
apt-transport-https \
|
|
ca-certificates \
|
|
curl \
|
|
git \
|
|
gh \
|
|
gosu \
|
|
tini \
|
|
python3 \
|
|
python3-venv \
|
|
pipx && \
|
|
echo "deb [signed-by=/usr/share/keyrings/nodesource.gpg] https://deb.nodesource.com/node_${NODE_MAJOR}.x nodistro main" \
|
|
> /etc/apt/sources.list.d/nodesource.list && \
|
|
arch="$(dpkg --print-architecture)" && \
|
|
printf "%s\n" \
|
|
"Types: deb" \
|
|
"URIs: https://packages.microsoft.com/repos/azure-cli/" \
|
|
"Suites: bookworm" \
|
|
"Components: main" \
|
|
"Architectures: $arch" \
|
|
"Signed-by: /usr/share/keyrings/microsoft.gpg" \
|
|
> /etc/apt/sources.list.d/azure-cli.sources && \
|
|
apt-get update && \
|
|
apt-get install -y --no-install-recommends nodejs azure-cli && \
|
|
rm -f \
|
|
/etc/apt/sources.list.d/nodesource.list \
|
|
/etc/apt/sources.list.d/azure-cli.sources \
|
|
/usr/share/keyrings/nodesource.gpg \
|
|
/usr/share/keyrings/microsoft.gpg && \
|
|
rm -rf /var/lib/apt/lists/* && \
|
|
PIPX_HOME=/opt/pipx PIPX_BIN_DIR=/usr/local/bin pipx install apprise
|
|
|
|
# Create the runtime user with uid 1000.
|
|
# Home is placed under /data so agent CLI auth state (gh, claude, codex, auggie,
|
|
# copilot, amp, ...) lives on the PV and survives pod restarts and image upgrades.
|
|
RUN groupadd -r kandev && useradd -r -g kandev -u 1000 -d /data/home -M kandev
|
|
|
|
# Install azure-devops extension under the runtime user's Azure config dir on /data.
|
|
RUN mkdir -p /data/home/.azure && \
|
|
AZURE_CONFIG_DIR=/data/home/.azure az extension add --name azure-devops && \
|
|
chown -R kandev:kandev /data/home/.azure
|
|
|
|
# Create app directory structure matching what `kandev start` expects:
|
|
# /app/apps/backend/bin/kandev
|
|
RUN mkdir -p /app/apps/backend/bin /data/worktrees
|
|
|
|
# Build context layout (prepared by the release workflow from the extracted
|
|
# bundle tarball):
|
|
# bundle/bin/kandev - native Go backend (per-arch)
|
|
# bundle/bin/agentctl - native agentctl (per-arch)
|
|
# bundle/bin/agentctl-linux-amd64 - linux/amd64 agentctl helper
|
|
# bundle/bin/agentctl-linux-arm64 - linux/arm64 agentctl helper
|
|
# bundle/bin/agentctl-darwin-arm64 - darwin/arm64 agentctl helper
|
|
# bundle/bin/agentctl-darwin-amd64 - darwin/amd64 agentctl helper
|
|
#
|
|
# The bundle's platform-specific agentctl helpers are uploaded into remote
|
|
# SSH hosts and bind-mounted into Docker-executor sandboxes by the lifecycle
|
|
# manager; ship them next to kandev so the AgentctlResolver finds them without
|
|
# manual configuration.
|
|
COPY bundle/bin/kandev /app/apps/backend/bin/kandev
|
|
COPY bundle/bin/agentctl-linux-amd64 /app/apps/backend/bin/agentctl-linux-amd64
|
|
COPY bundle/bin/agentctl-linux-arm64 /app/apps/backend/bin/agentctl-linux-arm64
|
|
COPY bundle/bin/agentctl-darwin-arm64 /app/apps/backend/bin/agentctl-darwin-arm64
|
|
COPY bundle/bin/agentctl-darwin-amd64 /app/apps/backend/bin/agentctl-darwin-amd64
|
|
COPY bundle/bin/agentctl /usr/local/bin/agentctl
|
|
COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
|
|
|
|
# Re-apply executable bits stripped by tar/COPY edge cases, then link the native
|
|
# launcher onto PATH.
|
|
RUN chmod +x \
|
|
/app/apps/backend/bin/kandev \
|
|
/app/apps/backend/bin/agentctl-linux-amd64 \
|
|
/app/apps/backend/bin/agentctl-linux-arm64 \
|
|
/app/apps/backend/bin/agentctl-darwin-arm64 \
|
|
/app/apps/backend/bin/agentctl-darwin-amd64 \
|
|
/usr/local/bin/agentctl \
|
|
/usr/local/bin/docker-entrypoint.sh && \
|
|
ln -s /app/apps/backend/bin/kandev /usr/local/bin/kandev && \
|
|
chown -R kandev:kandev /app /data
|
|
|
|
# Kandev home directory (DB, worktrees, sessions, repos)
|
|
VOLUME ["/data"]
|
|
|
|
# Environment defaults for containerized operation.
|
|
# NPM_CONFIG_PREFIX points npm global installs at the PV so user-installed
|
|
# agent CLIs (claude-code, codex, auggie, ...) survive pod restarts.
|
|
ENV KANDEV_NO_BROWSER=1 \
|
|
KANDEV_HOME_DIR=/data \
|
|
KANDEV_DOCKER_ENABLED=false \
|
|
HOME=/data/home \
|
|
NPM_CONFIG_PREFIX=/data/.npm-global \
|
|
PATH=/data/.npm-global/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
|
|
HOSTNAME=0.0.0.0 \
|
|
NODE_ENV=production
|
|
|
|
WORKDIR /app
|
|
|
|
# Only the backend port is exposed; the Go backend serves API, WebSocket, and
|
|
# embedded SPA assets on the same listener.
|
|
EXPOSE 38429
|
|
|
|
# tini as PID 1 for signal handling; entrypoint handles privilege drop
|
|
ENTRYPOINT ["tini", "--", "docker-entrypoint.sh"]
|
|
CMD ["kandev", "start", "--backend-port", "38429", "--verbose"]
|