# GrowQR OpenCode runtime image # # This wraps the upstream OpenCode image with GrowQR-owned prompt modules, # sub-agent definitions, workspace template files, and runtime bootstrap. # # Build from growqr-backend/: # docker build -f docker/opencode/Dockerfile -t growqr/opencode:dev . # # Release flow: # docker build -f docker/opencode/Dockerfile \ # --build-arg GROWQR_IMAGE_VERSION=2026.06.01-1 \ # -t ghcr.io//growqr-opencode:2026.06.01-1 \ # -t ghcr.io//growqr-opencode:latest . ARG OPENCODE_BASE_IMAGE=ghcr.io/anomalyco/opencode:latest FROM ${OPENCODE_BASE_IMAGE} ARG GROWQR_IMAGE_VERSION=dev ARG GROWQR_PROMPT_VERSION=dev ARG GROWQR_MIGRATION_VERSION=1 ENV GROWQR_IMAGE_VERSION=${GROWQR_IMAGE_VERSION} ENV GROWQR_PROMPT_VERSION=${GROWQR_PROMPT_VERSION} ENV GROWQR_MIGRATION_VERSION=${GROWQR_MIGRATION_VERSION} ENV GROWQR_HOME=/opt/growqr ENV OPENCODE_WORKSPACE=/workspace USER root # Ensure the runtime has the basics needed for Git-backed memory. The upstream # image may already include these, but this keeps our image contract explicit. RUN if command -v apk >/dev/null 2>&1; then \ apk add --no-cache git openssh-client ca-certificates bash curl jq; \ elif command -v apt-get >/dev/null 2>&1; then \ apt-get update && apt-get install -y --no-install-recommends \ git openssh-client ca-certificates bash curl jq && \ rm -rf /var/lib/apt/lists/*; \ else \ echo "Unsupported base image package manager" >&2; exit 1; \ fi RUN mkdir -p \ /workspace \ /root/.config/opencode \ /root/.local/share/opencode \ /opt/growqr/agents \ /opt/growqr/prompts \ /opt/growqr/workspace-template/memory \ /opt/growqr/workspace-template/conversations \ /opt/growqr/workspace-template/state \ /opt/growqr/workspace-template/artifacts \ /opt/growqr/workspace-template/workflows \ /opt/growqr/workspace-template/logs \ /opt/growqr/workspace-template/config \ /opt/growqr/workspace-template/metadata # GrowQR sub-agent prompt modules. These are image-versioned: update the files, # rebuild/push a new image, then set OPENCODE_IMAGE + OPENCODE_IMAGE_VERSION in # the backend rollout. COPY agents/ /opt/growqr/agents/ COPY prompts/ /opt/growqr/prompts/ COPY docker/opencode/growqr.json /root/.config/opencode/growqr.json COPY docker/opencode/entrypoint.sh /usr/local/bin/growqr-opencode-entrypoint # Starter Git workspace. The backend will normally create the real central # Gitea repo and clone it into /workspace after the server starts. This template # makes fresh/standalone containers still look like a GrowQR memory repo and # gives OpenCode immediate local context before clone/sync completes. COPY docker/opencode/workspace-template/ /opt/growqr/workspace-template/ RUN chmod +x /usr/local/bin/growqr-opencode-entrypoint && \ mkdir -p /opt/growqr/workspace-template/metadata && \ printf '%s\n' \ "{\"imageVersion\":\"${GROWQR_IMAGE_VERSION}\",\"promptVersion\":\"${GROWQR_PROMPT_VERSION}\",\"migrationVersion\":\"${GROWQR_MIGRATION_VERSION}\"}" \ > /opt/growqr/workspace-template/metadata/image.json WORKDIR /workspace EXPOSE 4096 ENTRYPOINT ["growqr-opencode-entrypoint"] CMD ["opencode", "serve", "--port", "4096", "--hostname", "0.0.0.0"]