Skip to content

perf: optimize devcontainer lifecycle (~17-25s faster startup)#149

Open
blooop wants to merge 2 commits intomainfrom
perf/devcontainer-lifecycle
Open

perf: optimize devcontainer lifecycle (~17-25s faster startup)#149
blooop wants to merge 2 commits intomainfrom
perf/devcontainer-lifecycle

Conversation

@blooop
Copy link
Owner

@blooop blooop commented Mar 12, 2026

Summary

  • Pre-install dotfiles pixi global packages in Dockerfile — bakes the devpod-profile tools (fzf, zoxide, rg, fd, chezmoi, gh, lazygit, etc.) into the image so install.sh's pixi global sync is a no-op (~14.7s saved)
  • Pre-warm project .pixi environment — runs pixi install during image build and copies the result into the volume on cold starts via onCreateCommand (~8.3s saved)
  • Comment out claude-code feature in prebuilt mode — already baked into image by CI; avoids redundant feature layer rebuild (~2s saved)
  • Remove redundant sudo chown vscode .pixi from postCreateCommand
  • Add pyproject.toml/pixi.lock to CI rebuild triggers so the pre-warmed deps stay fresh

New file: .devcontainer/pixi-global-devpod.toml

Static manifest rendered from the chezmoi template's devpod profile. Keep in sync with dot_pixi/manifests/pixi-global.toml.tmpl when adding/removing dotfiles tools.

Expected results

Scenario Before After Savings
Warm start (--recreate) 27.1s ~10s ~17s
Cold start (image cached) ~35s ~12s ~23s
First create (nothing cached) ~50-65s ~25-40s ~25s

Note: image size increases ~500MB (pixi global envs), but this is offset by eliminating runtime installs.

Toggle scripts

Verified devcontainer_use_local.sh / devcontainer_use_prebuilt.sh round-trip correctly with the new commented features block.

Test plan

  • devpod delete pythontemplate && docker volume rm python_template-pixi then time devpod up . --ide none (cold start)
  • time devpod up . --ide none --recreate (warm start)
  • Verify tools inside container: pixi run python --version && claude --version
  • pixi run dev-use-local then pixi run dev-use-prebuilt round-trip

🤖 Generated with Claude Code

Summary by Sourcery

Optimize devcontainer startup performance by pre-baking pixi environments and tooling into the image and tightening rebuild triggers.

Enhancements:

  • Pre-install pixi global devpod tooling in the devcontainer image using a static pixi manifest to make dotfiles setup effectively instant.
  • Pre-warm the project pixi environment during image build so container cold starts reuse the pre-installed dependencies.

Build:

  • Add a pixi global manifest file for devpod to the devcontainer image build context so common CLI tools are available by default.

CI:

  • Update the devcontainer CI workflow to rebuild when pyproject.toml or pixi.lock change, ensuring pre-warmed dependencies stay current.

blooop added 2 commits March 5, 2026 19:57
merge=ours in .gitattributes is not a built-in git merge driver—it
needs an explicit driver definition. Without it, git falls back to the
text driver and reports conflicts on pixi.lock.

Add `git config merge.ours.driver true` to devcontainer postCreateCommand
so the driver is configured on container creation.
Pre-install dotfiles pixi global packages and pre-warm project deps
in the Docker image so runtime installs are near-instant.

- Bake devpod-profile pixi global tools into Dockerfile (saves ~14.7s)
- Pre-warm project .pixi env for cold starts (saves ~8.3s)
- Comment out claude-code feature in prebuilt mode (saves ~2s)
- Remove redundant sudo chown from postCreateCommand
- Add pyproject.toml/pixi.lock to CI rebuild triggers
@sourcery-ai
Copy link

sourcery-ai bot commented Mar 12, 2026

Reviewer's Guide

Optimizes devcontainer startup by baking pixi global tools and a pre-warmed project environment into the image, wiring CI to rebuild when dependency manifests change, and adding a static manifest for devpod global tools.

Sequence diagram for optimized devcontainer cold start with prewarmed pixi env

sequenceDiagram
    actor Developer
    participant DevpodCLI
    participant DockerDaemon
    participant DevcontainerRuntime as Devcontainer
    participant Pixi

    Developer->>DevpodCLI: devpod up . --ide none
    DevpodCLI->>DockerDaemon: Pull prebuilt devcontainer image
    DockerDaemon-->>DevpodCLI: Image with pixi globals + prewarmed env
    DevpodCLI->>DockerDaemon: Start container
    DockerDaemon-->>DevcontainerRuntime: Run onCreateCommand

    DevcontainerRuntime->>DevcontainerRuntime: Copy /home/vscode/.pixi-prewarm to volume .pixi
    DevcontainerRuntime->>Pixi: Initialize project env from prewarmed .pixi
    Pixi-->>DevcontainerRuntime: Project deps ready (no full pixi install)

    DevcontainerRuntime->>Pixi: Check pixi global envs
    Pixi-->>DevcontainerRuntime: Global tools already installed

    DevcontainerRuntime-->>Developer: Shell ready with tools and deps
Loading

File-Level Changes

Change Details Files
Bake pixi global devpod toolchain into the devcontainer image so dotfiles install becomes a no-op at runtime.
  • Copy a static pixi global manifest into the vscode home .pixi manifests directory during image build.
  • Run pixi global sync in the Dockerfile to install all global tools into the image.
.devcontainer/Dockerfile
.devcontainer/pixi-global-devpod.toml
Pre-warm the project pixi environment at image build time to speed up cold starts.
  • Copy pyproject.toml and pixi.lock into a temporary build directory in the Docker image.
  • Create a minimal python_template package structure in the temp directory to satisfy pixi.
  • Run pixi install in the temp directory to resolve and install dependencies.
  • Move the resulting .pixi directory to a prewarmed location under /home/vscode/.pixi-prewarm for later use by devcontainer lifecycle hooks.
.devcontainer/Dockerfile
Ensure CI devcontainer builds are triggered when Python project dependencies change so prewarmed environments stay up to date.
  • Add pyproject.toml to the push and pull_request path filters for the devcontainer workflow.
  • Add pixi.lock to the push and pull_request path filters for the devcontainer workflow.
.github/workflows/devcontainer.yml
Introduce a checked-in pixi global manifest for the devpod profile to keep devcontainer and dotfiles tooling in sync.
  • Add a new pixi-global-devpod.toml manifest enumerating all required global tools, channels, and exposed commands for the devpod profile.
  • Document that this manifest must be kept in sync with the chezmoi template pixi-global.toml.tmpl when dotfiles tools change.
.devcontainer/pixi-global-devpod.toml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • In the Dockerfile, consider explicitly creating /home/vscode/.pixi/manifests before the COPY + pixi global sync step so the build doesn’t depend on that directory being created elsewhere or in a specific base image version.
  • The COPY pyproject.toml pixi.lock /tmp/pixi-prewarm/ step will fail if pixi.lock is absent; if that file is optional, you may want to either generate it earlier in the build or make the copy more robust (e.g. copy only pyproject.toml and let pixi install create the lock).
  • The pre-warm step hardcodes a python_template package directory; if the project name changes, this will silently diverge, so it might be better to derive the directory name from a single source of truth (e.g. an ARG or existing project path) rather than embedding it in the Dockerfile.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In the Dockerfile, consider explicitly creating `/home/vscode/.pixi/manifests` before the `COPY` + `pixi global sync` step so the build doesn’t depend on that directory being created elsewhere or in a specific base image version.
- The `COPY pyproject.toml pixi.lock /tmp/pixi-prewarm/` step will fail if `pixi.lock` is absent; if that file is optional, you may want to either generate it earlier in the build or make the copy more robust (e.g. copy only `pyproject.toml` and let `pixi install` create the lock).
- The pre-warm step hardcodes a `python_template` package directory; if the project name changes, this will silently diverge, so it might be better to derive the directory name from a single source of truth (e.g. an ARG or existing project path) rather than embedding it in the Dockerfile.

## Individual Comments

### Comment 1
<location path=".devcontainer/Dockerfile" line_range="31-35" />
<code_context>
+
+# Pre-warm project pixi environment for faster cold starts
+COPY --chown=vscode pyproject.toml pixi.lock /tmp/pixi-prewarm/
+RUN mkdir -p /tmp/pixi-prewarm/python_template \
+    && touch /tmp/pixi-prewarm/python_template/__init__.py \
+    && cd /tmp/pixi-prewarm \
+    && pixi install \
+    && mv .pixi /home/vscode/.pixi-prewarm
</code_context>
<issue_to_address>
**suggestion (performance):** Consider cleaning up the temporary /tmp/pixi-prewarm directory to avoid bloating the image

Since `/tmp/pixi-prewarm` and the `python_template` placeholder are only needed during build to bootstrap pixi, everything there becomes unused once `.pixi` is moved to `/home/vscode/.pixi-prewarm`. Consider appending `&& rm -rf /tmp/pixi-prewarm` to this `RUN` command to avoid shipping that dead weight in the final image layer.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +31 to +35
RUN mkdir -p /tmp/pixi-prewarm/python_template \
&& touch /tmp/pixi-prewarm/python_template/__init__.py \
&& cd /tmp/pixi-prewarm \
&& pixi install \
&& mv .pixi /home/vscode/.pixi-prewarm
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (performance): Consider cleaning up the temporary /tmp/pixi-prewarm directory to avoid bloating the image

Since /tmp/pixi-prewarm and the python_template placeholder are only needed during build to bootstrap pixi, everything there becomes unused once .pixi is moved to /home/vscode/.pixi-prewarm. Consider appending && rm -rf /tmp/pixi-prewarm to this RUN command to avoid shipping that dead weight in the final image layer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant