From c2910b7562daf6738c51a3c3af40ef35e9c9eaf2 Mon Sep 17 00:00:00 2001 From: Ritvik Shrivastava Date: Sun, 2 Aug 2026 12:30:48 +0000 Subject: [PATCH] fix: avoid duplicate venv copy in server Dockerfile template openenv init generated Dockerfiles copy the built virtualenv twice: once explicitly (COPY --from=builder /app/env/.venv /app/.venv) and once implicitly, since uv sync places .venv inside /app/env and the next layer copies /app/env wholesale (COPY --from=builder /app/env /app/env). This roughly doubles the final image size (~523MB -> two ~524MB layers per dive output in #1021). Fix: move .venv out of /app/env in the builder stage before the final stage copies happen, then symlink /app/env/.venv -> /app/.venv in the runtime stage so tooling that expects the venv alongside the project (e.g. uv run) keeps working, without shipping a second physical copy. Applied identically to both copies of the template (CLI init template and the Claude Code skill's mirrored asset) since they were already kept byte-for-byte identical apart from the license header. Fixes #1021 --- .../assets/openenv_env_template/server/Dockerfile | 15 +++++++++++++-- .../cli/templates/openenv_env/server/Dockerfile | 15 +++++++++++++-- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/.claude/skills/generate-openenv-env/assets/openenv_env_template/server/Dockerfile b/.claude/skills/generate-openenv-env/assets/openenv_env_template/server/Dockerfile index 1bb16c0003..d14e3b0c1d 100644 --- a/.claude/skills/generate-openenv-env/assets/openenv_env_template/server/Dockerfile +++ b/.claude/skills/generate-openenv-env/assets/openenv_env_template/server/Dockerfile @@ -54,17 +54,28 @@ RUN --mount=type=cache,target=/root/.cache/uv \ uv sync --no-editable; \ fi +# Move the venv out of /app/env so it isn't nested inside the directory we +# copy wholesale below. Copying /app/env/.venv separately AND /app/env would +# otherwise ship the venv twice (once at /app/.venv, once at +# /app/env/.venv), roughly doubling the image size. +RUN mv /app/env/.venv /app/.venv + # Final runtime stage FROM ${BASE_IMAGE} WORKDIR /app # Copy the virtual environment from builder -COPY --from=builder /app/env/.venv /app/.venv +COPY --from=builder /app/.venv /app/.venv -# Copy the environment code +# Copy the environment code (no longer contains .venv, see builder stage) COPY --from=builder /app/env /app/env +# Recreate a .venv symlink inside the env directory for tools (e.g. `uv run`, +# editors) that expect the virtual environment alongside the project, without +# storing a second physical copy of it. +RUN ln -s /app/.venv /app/env/.venv + # Set PATH to use the virtual environment ENV PATH="/app/.venv/bin:$PATH" diff --git a/src/openenv/cli/templates/openenv_env/server/Dockerfile b/src/openenv/cli/templates/openenv_env/server/Dockerfile index e150411a4d..947a379621 100644 --- a/src/openenv/cli/templates/openenv_env/server/Dockerfile +++ b/src/openenv/cli/templates/openenv_env/server/Dockerfile @@ -50,17 +50,28 @@ RUN --mount=type=cache,target=/root/.cache/uv \ uv sync --no-editable; \ fi +# Move the venv out of /app/env so it isn't nested inside the directory we +# copy wholesale below. Copying /app/env/.venv separately AND /app/env would +# otherwise ship the venv twice (once at /app/.venv, once at +# /app/env/.venv), roughly doubling the image size. +RUN mv /app/env/.venv /app/.venv + # Final runtime stage FROM ${BASE_IMAGE} WORKDIR /app # Copy the virtual environment from builder -COPY --from=builder /app/env/.venv /app/.venv +COPY --from=builder /app/.venv /app/.venv -# Copy the environment code +# Copy the environment code (no longer contains .venv, see builder stage) COPY --from=builder /app/env /app/env +# Recreate a .venv symlink inside the env directory for tools (e.g. `uv run`, +# editors) that expect the virtual environment alongside the project, without +# storing a second physical copy of it. +RUN ln -s /app/.venv /app/env/.venv + # Set PATH to use the virtual environment ENV PATH="/app/.venv/bin:$PATH"