Skip to content

chore: add standardized vscode devcontainer for development #7944

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 63 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
a542eaa
[feat]: add devcontainer
dsisco11 Apr 11, 2025
885b862
[chore]: let .vscode manage its own gitignore
dsisco11 Apr 11, 2025
71887f1
[chore]: add recommended extensions for project
dsisco11 Apr 11, 2025
1623dec
[chore]: add standard debug launch setups for devcontainer
dsisco11 Apr 11, 2025
95e4ff4
[chore]: add common build actions
dsisco11 Apr 11, 2025
e8054c2
[chore]: delay pnpm store-dir update command until after cache volume…
dsisco11 Apr 11, 2025
a69558d
[chore] fix configuring secondary UV index
dsisco11 Apr 11, 2025
cefa58b
[chore] add unit testing tasks to vscode config
dsisco11 Apr 11, 2025
5993a20
[chore]: fix pnpm & UV install commands
dsisco11 Apr 11, 2025
d3f7043
[chore]: fix source analysis imports for python tooling
dsisco11 Apr 13, 2025
72019c4
[chore]: remove commented envar
dsisco11 Apr 13, 2025
5948f0e
[chore]: add env samp[le file for devcontainer
dsisco11 Apr 13, 2025
586c10e
[chore]: correct test tasks to not be default
dsisco11 Apr 13, 2025
bba9f18
[chore]: setup tasks to be better ordered
dsisco11 Apr 13, 2025
8d9de4a
[chore]: rollback UV cuda index version
dsisco11 Apr 13, 2025
67be030
[chore]: remove commented
dsisco11 Apr 13, 2025
f326db5
[chore]: todo comment
dsisco11 Apr 13, 2025
aeef00d
[chore]: remove unneeded UID/GID vars from devcontainer image
dsisco11 Apr 14, 2025
2c16e63
[chore]: provide env file for devcontainer
dsisco11 Apr 14, 2025
d0c1e76
[chore]: create cache volume for model downloads, etc.
dsisco11 Apr 14, 2025
cfbd569
[chore]: remove unneeded port forward, vite dev gets auto forwarded
dsisco11 Apr 15, 2025
49e2b6a
[chore]: remove invalid launch options from backend debug launcher
dsisco11 Apr 16, 2025
39a3411
[chore]: set python interpreter path correctly in devcontainer settings
dsisco11 Apr 16, 2025
7af53f6
[chore]: correctly setup invokeai root envar
dsisco11 Apr 17, 2025
43f86d6
[chore]: enable dev reloading for backend debug launch
dsisco11 Apr 17, 2025
aa36f16
[chore]: fix permissions issues
dsisco11 Apr 18, 2025
544d668
add section for custom nodes to workspace setup
dsisco11 Apr 18, 2025
f948daa
[chore]: fix permissions issue with download cache folder
dsisco11 Apr 19, 2025
2024a47
[chore]: add mounting for custom node development
dsisco11 Apr 19, 2025
30f89af
[chore] add loading for mounted custom nodes
dsisco11 Apr 19, 2025
7a2ed57
[chore]: add readme for custom node development
dsisco11 Apr 19, 2025
2fb00bb
[chore] update readme to describe code-workspace file
dsisco11 Apr 19, 2025
482eaef
remove commented
dsisco11 Apr 19, 2025
a19a0e8
[chore]: reenable UV compiling
dsisco11 Apr 19, 2025
d1587a4
[chore]: pin UV to minor version (allow patches)
dsisco11 Apr 19, 2025
0ff8037
[chore]: add gitignore to app/invocations/custom_nodes to ignore cont…
dsisco11 Apr 19, 2025
9d1904c
[chore]: add commands for auto fixing linting errors
dsisco11 Apr 19, 2025
839a3a2
[chore]: linting
dsisco11 Apr 19, 2025
fa30bb0
chore: rename compute device arg
dsisco11 Apr 19, 2025
324fbe4
[chore]: turn on torch logging by default for development
dsisco11 Apr 20, 2025
1ac9d3c
[chore]: move pytorch envar to backend launch config instead
dsisco11 Apr 20, 2025
893ea14
[chore]: nope, logging is annoying
dsisco11 Apr 20, 2025
addc02d
[chore]: move devcontainer readme to root of devcontainer folder
dsisco11 Apr 20, 2025
0e96394
[chore]: improve devcontainer README
dsisco11 Apr 20, 2025
453448c
[chore]: fix linting problems
dsisco11 Apr 20, 2025
cd9f471
[chore] disable editor auto-saving when a file has errors by default,…
dsisco11 Apr 20, 2025
65c112a
[chore]: include exception info for custom-node loading errors
dsisco11 Apr 21, 2025
64112ee
chore: fool that I am for not just using the normal custom-nodes dire…
dsisco11 Apr 21, 2025
a8b0554
chore: oh yea, also fix the custom-nodes path in the workspace file...
dsisco11 Apr 21, 2025
e7161e8
chore: enable juririgged polling for devcontainer support
dsisco11 Apr 21, 2025
bae6557
chore: spruce up the vscode build tasks
dsisco11 Apr 23, 2025
090b9bf
chore: add gitlens to extensions
dsisco11 Apr 24, 2025
16e5104
chore: fix init file linux permission bits
dsisco11 Apr 25, 2025
df882af
chore: remove polling mode for juririgged, add documentation on commo…
dsisco11 Apr 25, 2025
ceb99fb
chore: update pytorch index alias name
dsisco11 Apr 25, 2025
f579048
chore: add excluded paths for python analysis
dsisco11 Apr 26, 2025
8e91cda
chore: disable python unit testing extension for auxillary workspaces…
dsisco11 Apr 26, 2025
3a47e57
chore: fix devcontainer context path
dsisco11 Apr 27, 2025
5b41533
chore: add utility task for printing currently installed version of a…
dsisco11 Apr 27, 2025
63371d6
chore: add utility command for displaying versions of all currently i…
dsisco11 Apr 27, 2025
e02e908
chore: add utility command for showing installed pnpm package versions
dsisco11 Apr 27, 2025
85bccb3
chore: remove unneeded pytest args, add comments
dsisco11 Apr 27, 2025
477cdd8
chore: remove workspace from PYTHONPATH as its not actually required
dsisco11 Apr 28, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .devcontainer/.env.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
## Make a copy of this file named `.env` and fill in the values below.
## Any environment variables supported by InvokeAI can be specified here,
## in addition to the examples below.

## GPU_DRIVER can be set to either `cuda` or `rocm` to enable GPU support in the container accordingly.
# GPU_DRIVER=cuda #| rocm
49 changes: 49 additions & 0 deletions .devcontainer/.vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "InvokeAI :: Backend",
"type": "debugpy",
"request": "launch",
"program": "scripts/invokeai-web.py",
"args": [],
"justMyCode": true,
"env": {
"INVOKE_DEV_RELOAD": "1"
},
"presentation": {
"echo": true,
"reveal": "always",
"focus": true,
"panel": "dedicated",
"showReuseMessage": false,
"clear": false
}
},
{
"name": "InvokeAI :: Frontend",
"command": "pnpm dev",
"cwd": "${workspaceRoot}/invokeai/frontend/web",
"request": "launch",
"type": "node-terminal",
"presentation": {
"echo": true,
"reveal": "always",
"focus": true,
"panel": "dedicated",
"showReuseMessage": false,
"clear": false
},
"serverReadyAction": {
"pattern": "(https?://localhost:[0-9]+)",
"uriFormat": "%s",
"action": "debugWithChrome",
"webRoot": "${workspaceFolder}/invokeai/frontend/web",
"killOnServerStop": true
}
}
]
}
89 changes: 89 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
FROM mcr.microsoft.com/devcontainers/typescript-node:22
# The default username for most devcontainer-base-images is 'vscode', but the typescript-node image uses 'node'.
ARG USERNAME=node
SHELL ["/bin/bash", "-c"]

RUN rm -f /etc/apt/apt.conf.d/docker-clean; echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache
RUN --mount=type=cache,target=/var/cache/apt \
--mount=type=cache,target=/var/lib/apt \
apt update && apt install -y --no-install-recommends \
ca-certificates \
gosu \
libglib2.0-0 \
libgl1 \
libglx-mesa0 \
build-essential \
libopencv-dev \
libstdc++-12-dev

# Link amdgpu.ids for ROCm builds
# contributed by https://github.com/Rubonnek
RUN mkdir -p "/opt/amdgpu/share/libdrm" &&\
ln -s "/usr/share/libdrm/amdgpu.ids" "/opt/amdgpu/share/libdrm/amdgpu.ids"

ARG COMPUTE_DEVICE=cuda
ARG INVOKEAI_SRC=/home/${USERNAME}/src/invokeai
ARG INVOKEAI_ROOT=/home/${USERNAME}/invokeai-data
ARG UV_PROJECT_ENVIRONMENT=/home/${USERNAME}/.venv
ARG HF_HOME=/home/${USERNAME}/.invokeai-cache/huggingface

ENV \
VIRTUAL_ENV=${UV_PROJECT_ENVIRONMENT} \
UV_PROJECT_ENVIRONMENT=${UV_PROJECT_ENVIRONMENT}

ENV \
COMPUTE_DEVICE=${COMPUTE_DEVICE} \
PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
UV_MANAGED_PYTHON=1 \
INVOKEAI_HOST=0.0.0.0 \
INVOKEAI_PORT=9090 \
INVOKEAI_ROOT=${INVOKEAI_ROOT} \
HF_HOME=${HF_HOME}

# Set Python version
# NOTE: this is the version of Python that will be installed by `uv`
ARG PYTHON_VERSION=3.12
ENV \
PYTHON_VERSION=${PYTHON_VERSION} \
UV_PYTHON=${PYTHON_VERSION}

# Volumes for the dependency stores/caches
ARG CACHE_DIR=/home/${USERNAME}/.cache
ARG DATA_DIR=/home/${USERNAME}/.data
# Setting XDG_CACHE_HOME will affect the location of the cache for pnpm and uv, and possibly other tools
# https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
# We set XDG_DATA_HOME to a non-volume-mounted location to guarantee that UV pre-installs python. (if its mounted it will only be installed after container start)
ENV XDG_CACHE_HOME=${CACHE_DIR} \
XDG_DATA_HOME=${DATA_DIR} \
GIT_LFS_CACHE=${CACHE_DIR}/git-lfs \
PATH="$UV_PROJECT_ENVIRONMENT/bin:$CACHE_DIR/pnpm:$CACHE_DIR/uv:$PATH"

# Predeclare volume mounting points for directories which will be written to.
# This guarantees that even if the devcontainer doesnt mount a volume for these paths, their contents will still be handled by a volume,
# rather than being written to the container image layers itself.
VOLUME [ "${CACHE_DIR}", "${INVOKEAI_SRC}", "${INVOKEAI_ROOT}", "${HF_HOME}"]

# Create & set ownership of directories
RUN set -eux; \
mkdir -p ${CACHE_DIR}/{uv,pnpm,node,Microsoft} && \
mkdir -p ${DATA_DIR}/{uv,pnpm,node} && \
mkdir -p ${UV_PROJECT_ENVIRONMENT} && \
mkdir -p ${INVOKEAI_ROOT}/models/.download_cache

# Setup PNPM
RUN corepack use pnpm && corepack enable

# Install `uv` for package management
COPY --from=ghcr.io/astral-sh/uv:0.6 /uv /uvx /bin/

RUN uv venv && uv python install ${PYTHON_VERSION}
ENV UV_PYTHON_DOWNLOADS=never

RUN set -eux; \
chown --recursive ${USERNAME}:${USERNAME} ${CACHE_DIR} && \
chown --recursive ${USERNAME}:${USERNAME} ${DATA_DIR} && \
chown --recursive ${USERNAME}:${USERNAME} ${INVOKEAI_ROOT} && \
chown --recursive ${USERNAME}:${USERNAME} ${UV_PROJECT_ENVIRONMENT}

WORKDIR ${INVOKEAI_SRC}
43 changes: 43 additions & 0 deletions .devcontainer/InvokeAI.code-workspace
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"folders": [
{
// Folder for the invokeai program data (located at filesystem root)
"name": "[AppData]",
"path": "/home/node/invokeai",
"settings": {
"python.testing.pytestEnabled": false,
"python.testing.unittestEnabled": false,
"python.testing.autoTestDiscoverOnSaveEnabled": false
}
},
{
"name": "[Custom Nodes]",
"path": "/home/node/invokeai/nodes"
},
{
// Folder for specifically the frontend sub-project
"name": "[Frontend]",
"path": "../invokeai/frontend/web",
"settings": {
"python.testing.pytestEnabled": false,
"python.testing.unittestEnabled": false,
"python.testing.autoTestDiscoverOnSaveEnabled": false
}
},
{
// Folder for specifically the backend sub-project
"name": "[Backend]",
"path": "../invokeai/backend",
"settings": {
"python.testing.pytestEnabled": false,
"python.testing.unittestEnabled": false,
"python.testing.autoTestDiscoverOnSaveEnabled": false
}
},
{
// Folder for the entire git repo.
"name": "[Repository]",
"path": "../"
}
]
}
74 changes: 74 additions & 0 deletions .devcontainer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Overview

This folder contains the devcontainer setup used by InvokeAI.
If you are not familiar with devcontainers, we encourage you to check out the VSCode [devcontainer tutorial](https://code.visualstudio.com/docs/devcontainers/tutorial) for more information!
But in short; devcontainers are a one click solution to build, launch, and install an isolated/containerized development environment which is setup specifically for writing code for this repository.
This means you can get started with development without having to manually install any dependencies or tools or manage configuration files, the container automatically does all of it for you.

## VSCode Workspace

Within this folder there is an `InvokeAI.code-workspace` file.
Opening this workspace within the devcontainer is encouraged as it will provide easy access to the most commonly used folders and files, including:

- InvokeAI application data folder (database/models/config/etc).
- Mounted custom-node packages.
- InvokeAI frontend src
- InvokeAI backend src

## Custom Node Development

Any folders placed in the `.devcontainer/mounts/custom-nodes` directory will be mounted into the container.
Invoke will automatically load these folders as custom nodes packages.
Sub-folders in this directory may even contain their own git repositories without conflicting with the InvokeAI repository, meaning vscode will not show your custom-node projects files as uncommitted changes for the invokeai repository.

All normal development tooling will work as expected, including:

- Debugging, breakpoints, and variable inspection.
- Import resolution.
- Linting and formatting.
- Type checking.

## Common Problems

### Launching backend after container rebuild results in package related error

eg: `Cannot reference module onnx-runtime/foo/bar`
This can sometimes happen and appears to be related to `uv.lockfile` permissions, this can usually be fixed with `F1 -> Rebuild container`, or if that fails delete the uv lockfile and then rebuild the container.
If both of these fail then there may be a legitimate package versioning issue, ask for help on the discord!

### Python Hot-Reloading not working

First check the backend logs and verify that "Juririgged" has logged a message indicating it detected and is watching the file in question.
For example:

```
[2025-04-24 23:53:32,956]::[jurigged]::INFO --> Watch /workspaces/InvokeAI/invokeai/app/api_app.py
[2025-04-24 23:53:32,956]::[jurigged]::INFO --> Watch /home/node/invokeai/nodes/siscos-nodes/__init__.py
```

If you have verified that the file is being watched, but the changes are not being picked up, then continue reading the next section.
If the below sections do not apply to you, then it is an issue with [jurigged](https://github.com/breuleux/jurigged).

### Jurigged not picking up changes

If you are developing on a Windows machine running [WSL](https://code.visualstudio.com/docs/remote/wsl-tutorial), then [this issue link is relevant to you](https://github.com/microsoft/WSL/issues/4739)
In short, WSL2 does not support propagating windows file system events to 'inotify' events for the linux virtual machine.

To fix this, it is strongly recommended that you store your code on the WSL filesystem instead of the Windows filesystem.

#### Option 1: Clone the repository within the WSL filesystem

Open VSCode and press `F1` and select **WSL: Connect to WSL**, this will open a new VSCode window connected to the WSL filesystem.
Afterwards, you can clone the InvokeAI repository using the command line, or by using the VSCode _Explore_ panel(_Ctrl+Shift+E_) which will show a **Clone Repository** button when no folder is opened.

#### Option 2: Move existing code to the WSL filesystem

First, open windows file explorer and enter `\\wsl$` in the address bar, this will show your WSL distributions.
More information can be found at [this link](https://learn.microsoft.com/en-us/windows/wsl/filesystems#view-your-current-directory-in-windows-file-explorer).

Next, open your preferred WSL distribution (default: _Ubuntu_) and decide where you want to store your code, its typically wise to use a path under your **home** directory (eg: `/home/<username>/code/<project>`).

Now, open VSCode and press `F1` and select **WSL: Connect to WSL**, once VSCode has opened in WSL you can click the **Open Folder** button in the VSCode _Explore_ panel(_Ctrl+Shift+E_) and select the correct folder from the dropdown menu.
Afterwards, just press `F1` and select **Reopen in Container** to launch the devcontainer.

See [this link](https://code.visualstudio.com/remote/advancedcontainers/improve-performance) for more information.
109 changes: 109 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
{
"name": "InvokeAI::Dev",
"build": {
"dockerfile": "Dockerfile",
"args": {
"USERNAME": "node",
"PYTHON_VERSION": "3.12", // The python version which will be installed in the container
"INVOKEAI_ROOT": "/home/node/invokeai",
"INVOKEAI_SRC": "${containerWorkspaceFolder}"
}
},
"mounts": [
{
// Setup a volume for all dependencies (pnpm, pip, uv, etc.)
"type": "volume",
"source": "invokeai-dev-cache",
"target": "/home/node/.cache"
},
{
// Setup a volume for invokeai downloads cache
"type": "volume",
"source": "invokeai-downloads-cache",
"target": "/home/node/invokeai/models/.download_cache"
},
{
// Insert the devcontainers vscode launch config into the container
"type": "bind",
"source": "${localWorkspaceFolder}/.devcontainer/.vscode/launch.json",
"target": "${containerWorkspaceFolder}/.vscode/launch.json"
},
{
// Mount the custom-nodes folder at repo root to allow for easier custom-node development
"type": "bind",
"source": "${localWorkspaceFolder}/.devcontainer/mounts/custom-nodes",
"target": "/home/node/invokeai/nodes"
}
],
"containerEnv": {
"UV_COMPILE_BYTECODE": "1",
"INVOKEAI_DEV_RELOAD": "true",
"UV_LINK_MODE": "symlink" // Using symlink because they are fast and always work, if you encounter issues after a cache purge, just rebuild the container.
},
"features": {
"ghcr.io/devcontainers/features/git-lfs": {},
"ghcr.io/devcontainers/features/github-cli": {}
},
"hostRequirements": {
"gpu": "optional",
"cpus": 2,
"memory": "8gb",
"storage": "10gb" // rough estimate of all dev packages & a handful of ai-models
},
"runArgs": [
"--env-file",
".devcontainer/.env"
// "--userns=keep-id", // Uncomment if using podman instead of docker. (remove after next vscode-remote extension release: https://github.com/microsoft/vscode-remote-release/issues/10798#issuecomment-2826767753)
// "--device=nvidia.com/gpu=all", // Uncomment if using podman instead of docker.
],
"initializeCommand": [".devcontainer/scripts/init"],
"onCreateCommand": "pnpm config --global set store-dir $XDG_CACHE_HOME/pnpm",
"updateContentCommand": "pnpm install --dir invokeai/frontend/web --prefer-offline",
"postAttachCommand": "uv sync --extra using-$(echo ${COMPUTE_DEVICE:-cpu}) --extra dev --extra test --extra docs",
"customizations": {
"vscode": {
"settings": {
"python.defaultInterpreterPath": "/home/node/.venv/bin/python",
"python.analysis.typeCheckingMode": "standard",
"python.analysis.exclude": [
"**/node_modules",
"**/dist",
"**/build",
"${containerWorkspaceFolder}/invokeai/frontend/web"
],
"python.analysis.extraPaths": [
"/home/node/invokeai/nodes",
"/home/node/.venv/lib",
"${containerWorkspaceFolder}"
],
"python.testing.promptToConfigure": false,
"python.testing.pytestEnabled": true,
"python.testing.pytestArgs": ["--tb=line", "--no-header"], // makes the output of pytest more human readable and parseable by vscode
"files.autoSaveWhenNoErrors": true, // prevents auto-saving when there are errors in the code, makes hot-reloading more reliable by not flooding the tooling with errors which tend to break it.
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": "always"
},
"ruff.linting.enabled": true
},
"extensions": [
"ms-vscode-remote.remote-containers",
"ms-azuretools.vscode-docker",
"ms-toolsai.jupyter",
"ms-toolsai.vscode-jupyter-cell-tags",
"ms-toolsai.jupyter-renderers",
"ms-toolsai.vscode-jupyter-slideshow",
"ms-python.python",
"charliermarsh.ruff",
"esbenp.prettier-vscode",
"DavidAnson.vscode-markdownlint",
"antfu.vite",
"docker.docker",
"dbaeumer.vscode-eslint",
"vitest.explorer",
"tamasfe.even-better-toml",
"eamodio.gitlens"
]
}
}
}
2 changes: 2 additions & 0 deletions .devcontainer/mounts/custom-nodes/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# ignore any folders within this directory
*
1 change: 1 addition & 0 deletions .devcontainer/scripts/init
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
touch .devcontainer/.env
2 changes: 2 additions & 0 deletions .devcontainer/scripts/init.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@ECHO off
if not exist .env copy NUL .env
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,6 @@ cython_debug/

# Scratch folder
.scratch/
.vscode/

# source installer files
installer/*zip
Expand Down
3 changes: 3 additions & 0 deletions .vscode/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Ignore launch.json for now since everyone has their own setup
launch.json
settings.json
Loading
Loading