Closes: #177 (CRITICAL — Dockerfile runs as root) Dockerfiles changed: - workspace-server/Dockerfile (platform-only): addgroup/adduser + USER platform - workspace-server/Dockerfile.tenant (combined Go+Canvas): addgroup/adduser + USER canvas + chown canvas:canvas on canvas dir so non-root node process can read it - canvas/Dockerfile (canvas standalone): addgroup/adduser + USER canvas - workspace-server/entrypoint-tenant.sh: update header comment (no longer starts as root; both processes now start non-root) The entrypoint no longer needs a root→non-root handoff since both the Go platform and Canvas node run as non-root by default. The 'canvas' user owns /app and /platform, so volume mounts owned by the host's canvas user work without needing a root init step. Co-authored-by: Molecule AI CP-BE <cp-be@agents.moleculesai.app> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
41 lines
1.9 KiB
Docker
41 lines
1.9 KiB
Docker
# Platform-only image (no canvas). Used by publish-platform-image workflow
|
|
# for GHCR + Fly registry. Tenant image uses Dockerfile.tenant instead.
|
|
#
|
|
# Build context: repo root.
|
|
|
|
FROM golang:1.25-alpine AS builder
|
|
WORKDIR /app
|
|
# Plugin source for replace directive in go.mod
|
|
COPY molecule-ai-plugin-github-app-auth/ /plugin/
|
|
COPY workspace-server/go.mod workspace-server/go.sum ./
|
|
# Add replace directives for Docker builds:
|
|
# 1. Platform → plugin (plugin source at /plugin/)
|
|
# 2. Plugin → platform (plugin's go.mod has a relative replace that doesn't
|
|
# work in Docker; fix it to point at /app where the platform source lives)
|
|
RUN echo 'replace github.com/Molecule-AI/molecule-ai-plugin-github-app-auth => /plugin' >> go.mod
|
|
RUN sed -i 's|replace github.com/Molecule-AI/molecule-monorepo/platform => .*|replace github.com/Molecule-AI/molecule-monorepo/platform => /app|' /plugin/go.mod
|
|
RUN go mod download
|
|
COPY workspace-server/ .
|
|
RUN CGO_ENABLED=0 GOOS=linux go build -o /platform ./cmd/server
|
|
|
|
# Clone templates + plugins at build time from manifest.json
|
|
FROM alpine:3.20 AS templates
|
|
RUN apk add --no-cache git jq
|
|
COPY manifest.json /manifest.json
|
|
COPY scripts/clone-manifest.sh /scripts/clone-manifest.sh
|
|
RUN chmod +x /scripts/clone-manifest.sh && /scripts/clone-manifest.sh /manifest.json /workspace-configs-templates /org-templates /plugins
|
|
|
|
FROM alpine:3.20
|
|
RUN apk add --no-cache ca-certificates git tzdata
|
|
COPY --from=builder /platform /platform
|
|
COPY workspace-server/migrations /migrations
|
|
COPY --from=templates /workspace-configs-templates /workspace-configs-templates
|
|
COPY --from=templates /org-templates /org-templates
|
|
COPY --from=templates /plugins /plugins
|
|
# Non-root runtime — platform binary doesn't need root; dropping privileges
|
|
# prevents container escape attacks from reaching host UID 0.
|
|
RUN addgroup -g 1000 platform && adduser -u 1000 -G platform -s /bin/sh -D platform
|
|
EXPOSE 8080
|
|
USER platform
|
|
CMD ["/platform"]
|