From 84c112220865398bcc34f5012cc5fef616aeeda2 Mon Sep 17 00:00:00 2001 From: mauwii Date: Sat, 4 Feb 2023 22:16:36 +0100 Subject: [PATCH 01/12] fix build.sh and env.sh --- docker/build.sh | 2 +- docker/env.sh | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docker/build.sh b/docker/build.sh index 4d3fdd85e6..c5670aa29b 100755 --- a/docker/build.sh +++ b/docker/build.sh @@ -35,7 +35,7 @@ else fi # Build Container -docker build \ +DOCKER_BUILDKIT=1 docker build \ --platform="${PLATFORM}" \ --tag="${CONTAINER_IMAGE}" \ ${PIP_EXTRA_INDEX_URL:+--build-arg="PIP_EXTRA_INDEX_URL=${PIP_EXTRA_INDEX_URL}"} \ diff --git a/docker/env.sh b/docker/env.sh index eab878577e..2196d78425 100644 --- a/docker/env.sh +++ b/docker/env.sh @@ -7,7 +7,7 @@ if [[ -z "$PIP_EXTRA_INDEX_URL" ]]; then CUDA_AVAILABLE=$(python -c "import torch;print(torch.cuda.is_available())") ROCM_AVAILABLE=$(python -c "import torch;print(torch.version.hip is not None)") if [[ "$(uname -s)" != "Darwin" && "${CUDA_AVAILABLE}" == "True" ]]; then - CONTAINER_FLAVOR=cuda + CONTAINER_FLAVOR="cuda" elif [[ "$(uname -s)" != "Darwin" && "${ROCM_AVAILABLE}" == "True" ]]; then CONTAINER_FLAVOR="rocm" else @@ -16,9 +16,9 @@ if [[ -z "$PIP_EXTRA_INDEX_URL" ]]; then fi # Set PIP_EXTRA_INDEX_URL based on container flavor if [[ "$CONTAINER_FLAVOR" == "rocm" ]]; then - PIP_EXTRA_INDEX_URL="${PIP_EXTRA_INDEX_URL-"https://download.pytorch.org/whl/rocm"}" - elif CONTAINER_FLAVOR=cpu; then - PIP_EXTRA_INDEX_URL="${PIP_EXTRA_INDEX_URL-"https://download.pytorch.org/whl/cpu"}" + PIP_EXTRA_INDEX_URL="https://download.pytorch.org/whl/rocm" + elif [[ "$CONTAINER_FLAVOR" == "cpu" ]]; then + PIP_EXTRA_INDEX_URL="https://download.pytorch.org/whl/cpu" fi fi From 9949a438f40a2009fb80886e2786bcd99210f1a7 Mon Sep 17 00:00:00 2001 From: mauwii Date: Sat, 4 Feb 2023 23:33:41 +0100 Subject: [PATCH 02/12] update docs with newly added variables also remove outdated information --- docs/installation/040_INSTALL_DOCKER.md | 138 ++++++------------------ 1 file changed, 30 insertions(+), 108 deletions(-) diff --git a/docs/installation/040_INSTALL_DOCKER.md b/docs/installation/040_INSTALL_DOCKER.md index c7c2d6adae..5896adf302 100644 --- a/docs/installation/040_INSTALL_DOCKER.md +++ b/docs/installation/040_INSTALL_DOCKER.md @@ -16,10 +16,6 @@ title: Installing with Docker For general use, install locally to leverage your machine's GPU. -!!! tip "For running on a cloud instance/service" - - Check out the [Running InvokeAI in the cloud with Docker](#running-invokeai-in-the-cloud-with-docker) section below - ## Why containers? They provide a flexible, reliable way to build and deploy InvokeAI. You'll also @@ -78,16 +74,18 @@ Some Suggestions of variables you may want to change besides the Token:
-| Environment-Variable | Default value | Description | -| -------------------- | ----------------------------- | -------------------------------------------------------------------------------------------- | -| `HUGGINGFACE_TOKEN` | No default, but **required**! | This is the only **required** variable, without it you can't download the huggingface models | -| `REPOSITORY_NAME` | The Basename of the Repo folder | This name will used as the container repository/image name | -| `VOLUMENAME` | `${REPOSITORY_NAME,,}_data` | Name of the Docker Volume where model files will be stored | -| `ARCH` | arch of the build machine | can be changed if you want to build the image for another arch | -| `INVOKEAI_TAG` | latest | the Container Repository / Tag which will be used | -| `PIP_REQUIREMENTS` | `requirements-lin-cuda.txt` | the requirements file to use (from `environments-and-requirements`) | -| `CONTAINER_FLAVOR` | cuda | the flavor of the image, which can be changed if you build f.e. with amd requirements file. | -| `INVOKE_DOCKERFILE` | `docker-build/Dockerfile` | the Dockerfile which should be built, handy for development | +| Environment-Variable | Default value | Description | +| --------------------- | ------------------------------- | -------------------------------------------------------------------------------------------- | +| `HUGGINGFACE_TOKEN` | No default, but **required**! | This is the only **required** variable, without it you can't download the huggingface models | +| `REPOSITORY_NAME` | The Basename of the Repo folder | This name will used as the container repository/image name | +| `VOLUMENAME` | `${REPOSITORY_NAME,,}_data` | Name of the Docker Volume where model files will be stored | +| `ARCH` | arch of the build machine | can be changed if you want to build the image for another arch | +| `INVOKEAI_TAG` | latest | the Container Repository / Tag which will be used | +| `PIP_REQUIREMENTS` | `requirements-lin-cuda.txt` | the requirements file to use (from `environments-and-requirements`) | +| `CONTAINER_FLAVOR` | cuda | the flavor of the image, which can be changed if you build f.e. with amd requirements file. | +| `INVOKE_DOCKERFILE` | `docker-build/Dockerfile` | the Dockerfile which should be built, handy for development | +| `CONTAINER_FLAVOR` | | the flavor of the image to built, available options are `cuda`, `rocm` and `cpu` | +| `PIP_EXTRA_INDEX_URL` | | if you want to use a custom pip-extra-index-url |
@@ -130,8 +128,9 @@ also do so. ## Running the container on your GPU -If you have an Nvidia GPU, you can enable InvokeAI to run on the GPU by running the container with an extra -environment variable to enable GPU usage and have the process run much faster: +If you have an Nvidia GPU, you can enable InvokeAI to run on the GPU by running +the container with an extra environment variable to enable GPU usage and have +the process run much faster: ```bash GPU_FLAGS=all ./docker-build/run.sh @@ -139,7 +138,8 @@ GPU_FLAGS=all ./docker-build/run.sh This passes the `--gpus all` to docker and uses the GPU. -If you don't have a GPU (or your host is not yet setup to use it) you will see a message like this: +If you don't have a GPU (or your host is not yet setup to use it) you will see a +message like this: `docker: Error response from daemon: could not select device driver "" with capabilities: [[gpu]].` @@ -147,84 +147,8 @@ You can use the full set of GPU combinations documented here: https://docs.docker.com/config/containers/resource_constraints/#gpu -For example, use `GPU_FLAGS=device=GPU-3a23c669-1f69-c64e-cf85-44e9b07e7a2a` to choose a specific device identified by a UUID. - -## Running InvokeAI in the cloud with Docker - -We offer an optimized Ubuntu-based image that has been well-tested in cloud deployments. Note: it also works well locally on Linux x86_64 systems with an Nvidia GPU. It *may* also work on Windows under WSL2 and on Intel Mac (not tested). - -An advantage of this method is that it does not need any local setup or additional dependencies. - -See the `docker-build/Dockerfile.cloud` file to familizarize yourself with the image's content. - -### Prerequisites - -- a `docker` runtime -- `make` (optional but helps for convenience) -- Huggingface token to download models, or an existing InvokeAI runtime directory from a previous installation - - Neither local Python nor any dependencies are required. If you don't have `make` (part of `build-essentials` on Ubuntu), or do not wish to install it, the commands from the `docker-build/Makefile` are readily adaptable to be executed directly. - -### Building and running the image locally - -1. Clone this repo and `cd docker-build` -1. `make build` - this will build the image. (This does *not* require a GPU-capable system). -1. _(skip this step if you already have a complete InvokeAI runtime directory)_ - - `make configure` (This does *not* require a GPU-capable system) - - this will create a local cache of models and configs (a.k.a the _runtime dir_) - - enter your Huggingface token when prompted -1. `make web` -1. Open the `http://localhost:9090` URL in your browser, and enjoy the banana sushi! - -To use InvokeAI on the cli, run `make cli`. To open a Bash shell in the container for arbitraty advanced use, `make shell`. - -#### Building and running without `make` - -(Feel free to adapt paths such as `${HOME}/invokeai` to your liking, and modify the CLI arguments as necessary). - -!!! example "Build the image and configure the runtime directory" - ```Shell - cd docker-build - - DOCKER_BUILDKIT=1 docker build -t local/invokeai:latest -f Dockerfile.cloud .. - - docker run --rm -it -v ${HOME}/invokeai:/mnt/invokeai local/invokeai:latest -c "python scripts/configure_invokeai.py" - ``` - -!!! example "Run the web server" - ```Shell - docker run --runtime=nvidia --gpus=all --rm -it -v ${HOME}/invokeai:/mnt/invokeai -p9090:9090 local/invokeai:latest - ``` - - Access the Web UI at http://localhost:9090 - -!!! example "Run the InvokeAI interactive CLI" - ``` - docker run --runtime=nvidia --gpus=all --rm -it -v ${HOME}/invokeai:/mnt/invokeai local/invokeai:latest -c "python scripts/invoke.py" - ``` - -### Running the image in the cloud - -This image works anywhere you can run a container with a mounted Docker volume. You may either build this image on a cloud instance, or build and push it to your Docker registry. To manually run this on a cloud instance (such as AWS EC2, GCP or Azure VM): - -1. build this image either in the cloud (you'll need to pull the repo), or locally -1. `docker tag` it as `your-registry/invokeai` and push to your registry (i.e. Dockerhub) -1. `docker pull` it on your cloud instance -1. configure the runtime directory as per above example, using `docker run ... configure_invokeai.py` script -1. use either one of the `docker run` commands above, substituting the image name for your own image. - -To run this on Runpod, please refer to the following Runpod template: https://www.runpod.io/console/gpu-secure-cloud?template=vm19ukkycf (you need a Runpod subscription). When launching the template, feel free to set the image to pull your own build. - -The template's `README` provides ample detail, but at a high level, the process is as follows: - -1. create a pod using this Docker image -1. ensure the pod has an `INVOKEAI_ROOT=` environment variable, and that it corresponds to the path to your pod's persistent volume mount -1. Run the pod with `sleep infinity` as the Docker command -1. Use Runpod basic SSH to connect to the pod, and run `python scripts/configure_invokeai.py` script -1. Stop the pod, and change the Docker command to `python scripts/invoke.py --web --host 0.0.0.0` -1. Run the pod again, connect to your pod on HTTP port 9090, and enjoy the banana sushi! - -Running on other cloud providers such as Vast.ai will likely work in a similar fashion. +For example, use `GPU_FLAGS=device=GPU-3a23c669-1f69-c64e-cf85-44e9b07e7a2a` to +choose a specific device identified by a UUID. --- @@ -240,13 +164,12 @@ Running on other cloud providers such as Vast.ai will likely work in a similar f If you're on a **Linux container** the `invoke` script is **automatically started** and the output dir set to the Docker volume you created earlier. -If you're **directly on macOS follow these startup instructions**. -With the Conda environment activated (`conda activate ldm`), run the interactive +If you're **directly on macOS follow these startup instructions**. With the +Conda environment activated (`conda activate ldm`), run the interactive interface that combines the functionality of the original scripts `txt2img` and -`img2img`: -Use the more accurate but VRAM-intensive full precision math because -half-precision requires autocast and won't work. -By default the images are saved in `outputs/img-samples/`. +`img2img`: Use the more accurate but VRAM-intensive full precision math because +half-precision requires autocast and won't work. By default the images are saved +in `outputs/img-samples/`. ```Shell python3 scripts/invoke.py --full_precision @@ -262,9 +185,9 @@ invoke> q ### Text to Image For quick (but bad) image results test with 5 steps (default 50) and 1 sample -image. This will let you know that everything is set up correctly. -Then increase steps to 100 or more for good (but slower) results. -The prompt can be in quotes or not. +image. This will let you know that everything is set up correctly. Then increase +steps to 100 or more for good (but slower) results. The prompt can be in quotes +or not. ```Shell invoke> The hulk fighting with sheldon cooper -s5 -n1 @@ -277,10 +200,9 @@ You'll need to experiment to see if face restoration is making it better or worse for your specific prompt. If you're on a container the output is set to the Docker volume. You can copy it -wherever you want. -You can download it from the Docker Desktop app, Volumes, my-vol, data. -Or you can copy it from your Mac terminal. Keep in mind `docker cp` can't expand -`*.png` so you'll need to specify the image file name. +wherever you want. You can download it from the Docker Desktop app, Volumes, +my-vol, data. Or you can copy it from your Mac terminal. Keep in mind +`docker cp` can't expand `*.png` so you'll need to specify the image file name. On your host Mac (you can use the name of any container that mounted the volume): From 3a260cf54f3b56d33c8b3f9373fdf3bf4daf885c Mon Sep 17 00:00:00 2001 From: mauwii Date: Sun, 5 Feb 2023 00:12:07 +0100 Subject: [PATCH 03/12] update directory from `docker-build` to `docker` --- docs/installation/040_INSTALL_DOCKER.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/installation/040_INSTALL_DOCKER.md b/docs/installation/040_INSTALL_DOCKER.md index 5896adf302..2fda4279fb 100644 --- a/docs/installation/040_INSTALL_DOCKER.md +++ b/docs/installation/040_INSTALL_DOCKER.md @@ -83,7 +83,7 @@ Some Suggestions of variables you may want to change besides the Token: | `INVOKEAI_TAG` | latest | the Container Repository / Tag which will be used | | `PIP_REQUIREMENTS` | `requirements-lin-cuda.txt` | the requirements file to use (from `environments-and-requirements`) | | `CONTAINER_FLAVOR` | cuda | the flavor of the image, which can be changed if you build f.e. with amd requirements file. | -| `INVOKE_DOCKERFILE` | `docker-build/Dockerfile` | the Dockerfile which should be built, handy for development | +| `INVOKE_DOCKERFILE` | `Dockerfile` | the Dockerfile which should be built, handy for development | | `CONTAINER_FLAVOR` | | the flavor of the image to built, available options are `cuda`, `rocm` and `cpu` | | `PIP_EXTRA_INDEX_URL` | | if you want to use a custom pip-extra-index-url | @@ -91,11 +91,11 @@ Some Suggestions of variables you may want to change besides the Token: #### Build the Image -I provided a build script, which is located in `docker-build/build.sh` but still +I provided a build script, which is located in `docker/build.sh` but still needs to be executed from the Repository root. ```bash -./docker-build/build.sh +./docker/build.sh ``` The build Script not only builds the container, but also creates the docker @@ -104,10 +104,10 @@ volume if not existing yet, or if empty it will just download the models. #### Run the Container After the build process is done, you can run the container via the provided -`docker-build/run.sh` script +`docker/run.sh` script ```bash -./docker-build/run.sh +./docker/run.sh ``` When used without arguments, the container will start the webserver and provide @@ -117,7 +117,7 @@ also do so. !!! example "run script example" ```bash - ./docker-build/run.sh "banana sushi" -Ak_lms -S42 -s10 + ./docker/run.sh "banana sushi" -Ak_lms -S42 -s10 ``` This would generate the legendary "banana sushi" with Seed 42, k_lms Sampler and 10 steps. @@ -133,7 +133,7 @@ the container with an extra environment variable to enable GPU usage and have the process run much faster: ```bash -GPU_FLAGS=all ./docker-build/run.sh +GPU_FLAGS=all ./docker/run.sh ``` This passes the `--gpus all` to docker and uses the GPU. From 6089f33e54a1327c19666a73172e3fe1d3e9dabe Mon Sep 17 00:00:00 2001 From: mauwii Date: Sun, 5 Feb 2023 00:15:45 +0100 Subject: [PATCH 04/12] fix HUGGING_FACE_HUB_TOKEN --- docs/installation/040_INSTALL_DOCKER.md | 28 ++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/installation/040_INSTALL_DOCKER.md b/docs/installation/040_INSTALL_DOCKER.md index 2fda4279fb..f3c24947d9 100644 --- a/docs/installation/040_INSTALL_DOCKER.md +++ b/docs/installation/040_INSTALL_DOCKER.md @@ -74,25 +74,25 @@ Some Suggestions of variables you may want to change besides the Token:
-| Environment-Variable | Default value | Description | -| --------------------- | ------------------------------- | -------------------------------------------------------------------------------------------- | -| `HUGGINGFACE_TOKEN` | No default, but **required**! | This is the only **required** variable, without it you can't download the huggingface models | -| `REPOSITORY_NAME` | The Basename of the Repo folder | This name will used as the container repository/image name | -| `VOLUMENAME` | `${REPOSITORY_NAME,,}_data` | Name of the Docker Volume where model files will be stored | -| `ARCH` | arch of the build machine | can be changed if you want to build the image for another arch | -| `INVOKEAI_TAG` | latest | the Container Repository / Tag which will be used | -| `PIP_REQUIREMENTS` | `requirements-lin-cuda.txt` | the requirements file to use (from `environments-and-requirements`) | -| `CONTAINER_FLAVOR` | cuda | the flavor of the image, which can be changed if you build f.e. with amd requirements file. | -| `INVOKE_DOCKERFILE` | `Dockerfile` | the Dockerfile which should be built, handy for development | -| `CONTAINER_FLAVOR` | | the flavor of the image to built, available options are `cuda`, `rocm` and `cpu` | -| `PIP_EXTRA_INDEX_URL` | | if you want to use a custom pip-extra-index-url | +| Environment-Variable | Default value | Description | +| ------------------------ | ------------------------------- | -------------------------------------------------------------------------------------------- | +| `HUGGING_FACE_HUB_TOKEN` | No default, but **required**! | This is the only **required** variable, without it you can't download the huggingface models | +| `REPOSITORY_NAME` | The Basename of the Repo folder | This name will used as the container repository/image name | +| `VOLUMENAME` | `${REPOSITORY_NAME,,}_data` | Name of the Docker Volume where model files will be stored | +| `ARCH` | arch of the build machine | can be changed if you want to build the image for another arch | +| `INVOKEAI_TAG` | latest | the Container Repository / Tag which will be used | +| `PIP_REQUIREMENTS` | `requirements-lin-cuda.txt` | the requirements file to use (from `environments-and-requirements`) | +| `CONTAINER_FLAVOR` | cuda | the flavor of the image, which can be changed if you build f.e. with amd requirements file. | +| `INVOKE_DOCKERFILE` | `Dockerfile` | the Dockerfile which should be built, handy for development | +| `CONTAINER_FLAVOR` | | the flavor of the image to built, available options are `cuda`, `rocm` and `cpu` | +| `PIP_EXTRA_INDEX_URL` | | if you want to use a custom pip-extra-index-url |
#### Build the Image -I provided a build script, which is located in `docker/build.sh` but still -needs to be executed from the Repository root. +I provided a build script, which is located in `docker/build.sh` but still needs +to be executed from the Repository root. ```bash ./docker/build.sh From 1386d73302917e16341117bc46b4a7f06e904198 Mon Sep 17 00:00:00 2001 From: mauwii Date: Sun, 5 Feb 2023 00:58:42 +0100 Subject: [PATCH 05/12] fix env.sh only try to auto-detect CUDA/ROCm if torch is installed --- docker/env.sh | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/docker/env.sh b/docker/env.sh index 2196d78425..6987e12fb8 100644 --- a/docker/env.sh +++ b/docker/env.sh @@ -1,24 +1,26 @@ #!/usr/bin/env bash -if [[ -z "$PIP_EXTRA_INDEX_URL" ]]; then - # Decide which container flavor to build if not specified - if [[ -z "$CONTAINER_FLAVOR" ]]; then - # Check for CUDA and ROCm - CUDA_AVAILABLE=$(python -c "import torch;print(torch.cuda.is_available())") - ROCM_AVAILABLE=$(python -c "import torch;print(torch.version.hip is not None)") - if [[ "$(uname -s)" != "Darwin" && "${CUDA_AVAILABLE}" == "True" ]]; then - CONTAINER_FLAVOR="cuda" - elif [[ "$(uname -s)" != "Darwin" && "${ROCM_AVAILABLE}" == "True" ]]; then - CONTAINER_FLAVOR="rocm" - else - CONTAINER_FLAVOR="cpu" +if python -c "import torch" &>/dev/null; then + if [[ -z "$PIP_EXTRA_INDEX_URL" ]]; then + # Decide which container flavor to build if not specified + if [[ -z "$CONTAINER_FLAVOR" ]]; then + # Check for CUDA and ROCm + CUDA_AVAILABLE=$(python -c "import torch;print(torch.cuda.is_available())") + ROCM_AVAILABLE=$(python -c "import torch;print(torch.version.hip is not None)") + if [[ "$(uname -s)" != "Darwin" && "${CUDA_AVAILABLE}" == "True" ]]; then + CONTAINER_FLAVOR="cuda" + elif [[ "$(uname -s)" != "Darwin" && "${ROCM_AVAILABLE}" == "True" ]]; then + CONTAINER_FLAVOR="rocm" + else + CONTAINER_FLAVOR="cpu" + fi + fi + # Set PIP_EXTRA_INDEX_URL based on container flavor + if [[ "$CONTAINER_FLAVOR" == "rocm" ]]; then + PIP_EXTRA_INDEX_URL="https://download.pytorch.org/whl/rocm" + elif [[ "$CONTAINER_FLAVOR" == "cpu" ]]; then + PIP_EXTRA_INDEX_URL="https://download.pytorch.org/whl/cpu" fi - fi - # Set PIP_EXTRA_INDEX_URL based on container flavor - if [[ "$CONTAINER_FLAVOR" == "rocm" ]]; then - PIP_EXTRA_INDEX_URL="https://download.pytorch.org/whl/rocm" - elif [[ "$CONTAINER_FLAVOR" == "cpu" ]]; then - PIP_EXTRA_INDEX_URL="https://download.pytorch.org/whl/cpu" fi fi @@ -30,6 +32,7 @@ PLATFORM="${PLATFORM-Linux/${ARCH}}" INVOKEAI_BRANCH="${INVOKEAI_BRANCH-$(git branch --show)}" CONTAINER_REGISTRY="${CONTAINER_REGISTRY-"ghcr.io"}" CONTAINER_REPOSITORY="${CONTAINER_REPOSITORY-"$(whoami)/${REPOSITORY_NAME}"}" +CONTAINER_FLAVOR="${CONTAINER_FLAVOR-cuda}" CONTAINER_TAG="${CONTAINER_TAG-"${INVOKEAI_BRANCH##*/}-${CONTAINER_FLAVOR}"}" CONTAINER_IMAGE="${CONTAINER_REGISTRY}/${CONTAINER_REPOSITORY}:${CONTAINER_TAG}" CONTAINER_IMAGE="${CONTAINER_IMAGE,,}" From eb702a5049f2a15423bab7f5406463234fbf9d14 Mon Sep 17 00:00:00 2001 From: mauwii Date: Sun, 5 Feb 2023 02:39:29 +0100 Subject: [PATCH 06/12] fix env.sh, update Dockerfile, update build.sh env.sh: - move check for torch to CONVTAINER_FLAVOR detection Dockerfile - only mount `/var/cache/apt` for apt related steps - remove `docker-clean` from `/etc/apt/apt.conf.d` for BuildKit cache - remove apt-get clean for BuildKit cache - only copy frontend to frontend-builder - mount `/usr/local/share/.cache/yarn` in frountend-builder - separate steps for yarn install and yarn build - build pytorch in pyproject-builder build.sh - prepare for installation with extras --- docker/Dockerfile | 56 +++++++++++++++++++---------------------------- docker/build.sh | 1 + docker/env.sh | 40 ++++++++++++++++----------------- 3 files changed, 44 insertions(+), 53 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 475f8dc55e..a3a33112e5 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -4,21 +4,22 @@ ARG PYTHON_VERSION=3.9 ################## -### base image ### +## base image ## ################## FROM python:${PYTHON_VERSION}-slim AS python-base +# prepare for buildkit cache +RUN rm -f /etc/apt/apt.conf.d/docker-clean + # Install necesarry packages RUN \ --mount=type=cache,target=/var/cache/apt,sharing=locked \ - --mount=type=cache,target=/var/lib/apt,sharing=locked \ apt-get update \ && apt-get install -y \ --no-install-recommends \ libgl1-mesa-glx=20.3.* \ libglib2.0-0=2.66.* \ libopencv-dev=4.5.* \ - && apt-get clean \ && rm -rf /var/lib/apt/lists/* # set working directory and path @@ -28,41 +29,43 @@ WORKDIR ${APPDIR} ENV PATH=${APPDIR}/${APPNAME}/bin:$PATH ###################### -### build frontend ### +## build frontend ## ###################### FROM node:lts as frontend-builder # Copy Sources ARG APPDIR=/usr/src WORKDIR ${APPDIR} -COPY --link . . +COPY ./invokeai/frontend ./invokeai/frontend -# install dependencies and build frontend +# install dependencies WORKDIR ${APPDIR}/invokeai/frontend RUN \ - --mount=type=cache,target=/usr/local/share/.cache/yarn/v6 \ + --mount=type=cache,target=/usr/local/share/.cache/yarn \ yarn install \ --prefer-offline \ --frozen-lockfile \ --non-interactive \ - --production=false \ - && yarn build + --production=false + +# build frontend +RUN yarn build ################################### -### install python dependencies ### +## install python dependencies ## ################################### FROM python-base AS pyproject-builder +ENV PIP_USE_PEP517=1 # Install dependencies RUN \ --mount=type=cache,target=/var/cache/apt,sharing=locked \ - --mount=type=cache,target=/var/lib/apt,sharing=locked \ apt-get update \ && apt-get install -y \ --no-install-recommends \ + build-essential=12.9 \ gcc=4:10.2.* \ python3-dev=3.9.* \ - && apt-get clean \ && rm -rf /var/lib/apt/lists/* # create virtual environment @@ -70,18 +73,21 @@ RUN python3 -m venv "${APPNAME}" \ --upgrade-deps # copy sources -COPY --from=frontend-builder ${APPDIR} . +COPY --link . . +COPY --from=frontend-builder ${APPDIR}/invokeai/frontend/dist ${APPDIR}/invokeai/frontend/dist # install pyproject.toml ARG PIP_EXTRA_INDEX_URL ENV PIP_EXTRA_INDEX_URL ${PIP_EXTRA_INDEX_URL} +ARG PIP_PACKAGE=. RUN --mount=type=cache,target=/root/.cache/pip,sharing=locked \ - "${APPDIR}/${APPNAME}/bin/pip" install \ - --use-pep517 \ - . + "${APPDIR}/${APPNAME}/bin/pip" install ${PIP_PACKAGE} + +# build patchmatch +RUN python3 -c "from patchmatch import patch_match" ##################### -### runtime image ### +## runtime image ## ##################### FROM python-base AS runtime @@ -90,22 +96,6 @@ COPY --from=pyproject-builder ${APPDIR}/${APPNAME} ${APPDIR}/${APPNAME} ENV INVOKEAI_ROOT=/data ENV INVOKE_MODEL_RECONFIGURE="--yes --default_only" -# build patchmatch -RUN \ - --mount=type=cache,target=/var/cache/apt,sharing=locked \ - --mount=type=cache,target=/var/lib/apt,sharing=locked \ - apt-get update \ - && apt-get install -y \ - --no-install-recommends \ - build-essential=12.9 \ - && PYTHONDONTWRITEBYTECODE=1 \ - python3 -c "from patchmatch import patch_match" \ - && apt-get remove -y \ - --autoremove \ - build-essential \ - && apt-get autoclean \ - && rm -rf /var/lib/apt/lists/* - # set Entrypoint and default CMD ENTRYPOINT [ "invokeai" ] CMD [ "--web", "--host=0.0.0.0" ] diff --git a/docker/build.sh b/docker/build.sh index c5670aa29b..bed4d8a113 100755 --- a/docker/build.sh +++ b/docker/build.sh @@ -39,5 +39,6 @@ DOCKER_BUILDKIT=1 docker build \ --platform="${PLATFORM}" \ --tag="${CONTAINER_IMAGE}" \ ${PIP_EXTRA_INDEX_URL:+--build-arg="PIP_EXTRA_INDEX_URL=${PIP_EXTRA_INDEX_URL}"} \ + ${PIP_PACKAGE:+--build-arg="PIP_PACKAGE=${PIP_PACKAGE}"} \ --file="${DOCKERFILE}" \ .. diff --git a/docker/env.sh b/docker/env.sh index 6987e12fb8..d6b0699ce5 100644 --- a/docker/env.sh +++ b/docker/env.sh @@ -1,27 +1,27 @@ #!/usr/bin/env bash -if python -c "import torch" &>/dev/null; then - if [[ -z "$PIP_EXTRA_INDEX_URL" ]]; then - # Decide which container flavor to build if not specified - if [[ -z "$CONTAINER_FLAVOR" ]]; then - # Check for CUDA and ROCm - CUDA_AVAILABLE=$(python -c "import torch;print(torch.cuda.is_available())") - ROCM_AVAILABLE=$(python -c "import torch;print(torch.version.hip is not None)") - if [[ "$(uname -s)" != "Darwin" && "${CUDA_AVAILABLE}" == "True" ]]; then - CONTAINER_FLAVOR="cuda" - elif [[ "$(uname -s)" != "Darwin" && "${ROCM_AVAILABLE}" == "True" ]]; then - CONTAINER_FLAVOR="rocm" - else - CONTAINER_FLAVOR="cpu" - fi - fi - # Set PIP_EXTRA_INDEX_URL based on container flavor - if [[ "$CONTAINER_FLAVOR" == "rocm" ]]; then - PIP_EXTRA_INDEX_URL="https://download.pytorch.org/whl/rocm" - elif [[ "$CONTAINER_FLAVOR" == "cpu" ]]; then - PIP_EXTRA_INDEX_URL="https://download.pytorch.org/whl/cpu" +if [[ -z "$PIP_EXTRA_INDEX_URL" ]]; then + # Decide which container flavor to build if not specified + if [[ -z "$CONTAINER_FLAVOR" ]] && python -c "import torch" &>/dev/null; then + # Check for CUDA and ROCm + CUDA_AVAILABLE=$(python -c "import torch;print(torch.cuda.is_available())") + ROCM_AVAILABLE=$(python -c "import torch;print(torch.version.hip is not None)") + if [[ "$(uname -s)" != "Darwin" && "${CUDA_AVAILABLE}" == "True" ]]; then + CONTAINER_FLAVOR="cuda" + elif [[ "$(uname -s)" != "Darwin" && "${ROCM_AVAILABLE}" == "True" ]]; then + CONTAINER_FLAVOR="rocm" + else + CONTAINER_FLAVOR="cpu" fi fi + # Set PIP_EXTRA_INDEX_URL based on container flavor + if [[ "$CONTAINER_FLAVOR" == "rocm" ]]; then + PIP_EXTRA_INDEX_URL="https://download.pytorch.org/whl/rocm" + elif [[ "$CONTAINER_FLAVOR" == "cpu" ]]; then + PIP_EXTRA_INDEX_URL="https://download.pytorch.org/whl/cpu" + # elif [[ -z "$CONTAINER_FLAVOR" || "$CONTAINER_FLAVOR" == "cuda" ]]; then + # PIP_PACKAGE=${PIP_PACKAGE-".[xformers]"} + fi fi # Variables shared by build.sh and run.sh From fc0f966ad2598c8e125602857d3140f4ffcf295a Mon Sep 17 00:00:00 2001 From: mauwii Date: Sun, 5 Feb 2023 03:03:27 +0100 Subject: [PATCH 07/12] fix docs --- docs/installation/040_INSTALL_DOCKER.md | 30 ++++++++++++------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/installation/040_INSTALL_DOCKER.md b/docs/installation/040_INSTALL_DOCKER.md index f3c24947d9..07e7f55e93 100644 --- a/docs/installation/040_INSTALL_DOCKER.md +++ b/docs/installation/040_INSTALL_DOCKER.md @@ -74,32 +74,32 @@ Some Suggestions of variables you may want to change besides the Token:
-| Environment-Variable | Default value | Description | -| ------------------------ | ------------------------------- | -------------------------------------------------------------------------------------------- | -| `HUGGING_FACE_HUB_TOKEN` | No default, but **required**! | This is the only **required** variable, without it you can't download the huggingface models | -| `REPOSITORY_NAME` | The Basename of the Repo folder | This name will used as the container repository/image name | -| `VOLUMENAME` | `${REPOSITORY_NAME,,}_data` | Name of the Docker Volume where model files will be stored | -| `ARCH` | arch of the build machine | can be changed if you want to build the image for another arch | -| `INVOKEAI_TAG` | latest | the Container Repository / Tag which will be used | -| `PIP_REQUIREMENTS` | `requirements-lin-cuda.txt` | the requirements file to use (from `environments-and-requirements`) | -| `CONTAINER_FLAVOR` | cuda | the flavor of the image, which can be changed if you build f.e. with amd requirements file. | -| `INVOKE_DOCKERFILE` | `Dockerfile` | the Dockerfile which should be built, handy for development | -| `CONTAINER_FLAVOR` | | the flavor of the image to built, available options are `cuda`, `rocm` and `cpu` | -| `PIP_EXTRA_INDEX_URL` | | if you want to use a custom pip-extra-index-url | +| Environment-Variable | Default value | Description | +| ----------------------------------------------------- | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `HUGGING_FACE_HUB_TOKEN` | No default, but **required**! | This is the only **required** variable, without it you can't download the huggingface models | +| `REPOSITORY_NAME` | The Basename of the Repo folder | This name will used as the container repository/image name | +| `VOLUMENAME` | `${REPOSITORY_NAME,,}_data` | Name of the Docker Volume where model files will be stored | +| `ARCH` | arch of the build machine | Can be changed if you want to build the image for another arch | +| `CONTAINER_REGISTRY` | ghcr.io | Name of the Container Registry to use for the full tag | +| `CONTAINER_REPOSITORY` | `$(whoami)/${REPOSITORY_NAME}` | Name of the Container Repository | +| `CONTAINER_FLAVOR` | `cuda` | The flavor of the image to built, available options are `cuda`, `rocm` and `cpu`. If you choose `rocm` or `cpu`, the extra-index-url will be selected automatically, unless you set one yourself. | +| `CONTAINER_TAG` | `${INVOKEAI_BRANCH##*/}-${CONTAINER_FLAVOR}` | The Container Repository / Tag which will be used | +| `INVOKE_DOCKERFILE` | `Dockerfile` | The Dockerfile which should be built, handy for development | +| `PIP_EXTRA_INDEX_URL` | | If you want to use a custom pip-extra-index-url |
#### Build the Image -I provided a build script, which is located in `docker/build.sh` but still needs -to be executed from the Repository root. +I provided a build script, which is located next to the Dockerfile in +`docker/build.sh`. It can be executed from repository root like this: ```bash ./docker/build.sh ``` The build Script not only builds the container, but also creates the docker -volume if not existing yet, or if empty it will just download the models. +volume if not existing yet. #### Run the Container From 5662d2daa831fd74c94857e1dce9ef89d7c4b200 Mon Sep 17 00:00:00 2001 From: mauwii Date: Sun, 5 Feb 2023 04:27:34 +0100 Subject: [PATCH 08/12] add `invokeai/frontend/dist/**` to .dockerignore --- .dockerignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.dockerignore b/.dockerignore index 3d59dece86..fa8136dddd 100644 --- a/.dockerignore +++ b/.dockerignore @@ -13,6 +13,7 @@ # whitelist frontend, but ignore node_modules invokeai/frontend/node_modules +invokeai/frontend/dist/** # ignore python cache **/__pycache__ From 9c3f548900f6cd2d938e952f4b3dbf4c63c05601 Mon Sep 17 00:00:00 2001 From: mauwii Date: Sun, 5 Feb 2023 04:34:01 +0100 Subject: [PATCH 09/12] update settings output in build.sh --- docker/build.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docker/build.sh b/docker/build.sh index bed4d8a113..dc1a1dcc78 100755 --- a/docker/build.sh +++ b/docker/build.sh @@ -17,14 +17,14 @@ DOCKERFILE=${INVOKE_DOCKERFILE:-Dockerfile} # print the settings echo -e "You are using these values:\n" -echo -e "Dockerfile: \t${DOCKERFILE}" -echo -e "index-url: \t${PIP_EXTRA_INDEX_URL:-none}" -echo -e "Volumename: \t${VOLUMENAME}" -echo -e "Platform: \t${PLATFORM}" -echo -e "Registry: \t${CONTAINER_REGISTRY}" -echo -e "Repository: \t${CONTAINER_REPOSITORY}" -echo -e "Container Tag: \t${CONTAINER_TAG}" -echo -e "Container Image: ${CONTAINER_IMAGE}\n" +echo -e "Dockerfile:\t\t${DOCKERFILE}" +echo -e "index-url:\t\t${PIP_EXTRA_INDEX_URL:-none}" +echo -e "Volumename:\t\t${VOLUMENAME}" +echo -e "Platform:\t\t${PLATFORM}" +echo -e "Registry:\t\t${CONTAINER_REGISTRY}" +echo -e "Repository:\t\t${CONTAINER_REPOSITORY}" +echo -e "Container Tag:\t\t${CONTAINER_TAG}" +echo -e "Container Image:\t${CONTAINER_IMAGE}\n" # Create docker volume if [[ -n "$(docker volume ls -f name="${VOLUMENAME}" -q)" ]]; then From 394b4a771e908398431eb537c3b4508994a28b0d Mon Sep 17 00:00:00 2001 From: mauwii Date: Sun, 5 Feb 2023 04:35:11 +0100 Subject: [PATCH 10/12] update Dockerfile - remove yarn install args `--prefer-offline` and `--production=false` --- docker/Dockerfile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index a3a33112e5..152f491978 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -43,10 +43,8 @@ WORKDIR ${APPDIR}/invokeai/frontend RUN \ --mount=type=cache,target=/usr/local/share/.cache/yarn \ yarn install \ - --prefer-offline \ --frozen-lockfile \ - --non-interactive \ - --production=false + --non-interactive # build frontend RUN yarn build From 90656aa7bfb0d6fe1211cc344f4a6b00f227ef50 Mon Sep 17 00:00:00 2001 From: mauwii Date: Sun, 5 Feb 2023 05:24:48 +0100 Subject: [PATCH 11/12] update Dockerfile - add build arg `FRONTEND_DIR` --- docker/Dockerfile | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 152f491978..1d4cdaa983 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -35,11 +35,11 @@ FROM node:lts as frontend-builder # Copy Sources ARG APPDIR=/usr/src -WORKDIR ${APPDIR} -COPY ./invokeai/frontend ./invokeai/frontend +ARG FRONTEND_DIR=invokeai/frontend +WORKDIR ${APPDIR}/${FRONTEND_DIR} +COPY ${FRONTEND_DIR} . # install dependencies -WORKDIR ${APPDIR}/invokeai/frontend RUN \ --mount=type=cache,target=/usr/local/share/.cache/yarn \ yarn install \ @@ -72,7 +72,8 @@ RUN python3 -m venv "${APPNAME}" \ # copy sources COPY --link . . -COPY --from=frontend-builder ${APPDIR}/invokeai/frontend/dist ${APPDIR}/invokeai/frontend/dist +ARG FRONTEND_DIR=invokeai/frontend +COPY --from=frontend-builder ${APPDIR}/${FRONTEND_DIR}/dist ${FRONTEND_DIR}/dist # install pyproject.toml ARG PIP_EXTRA_INDEX_URL From 1c197c602f90394412d63ebb50ca2a94cb44f897 Mon Sep 17 00:00:00 2001 From: mauwii Date: Sun, 5 Feb 2023 20:20:25 +0100 Subject: [PATCH 12/12] update Dockerfile, .dockerignore and workflow - dont build frontend since complications with QEMU - set pip cache dir - add pip cache to all pip related build steps - dont lock pip cache - update dockerignore to exclude uneeded files --- .dockerignore | 12 ++++--- .github/workflows/build-container.yml | 8 +++-- docker/Dockerfile | 48 ++++++++++----------------- 3 files changed, 29 insertions(+), 39 deletions(-) diff --git a/.dockerignore b/.dockerignore index fa8136dddd..429ca125c0 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,19 +1,21 @@ # use this file as a whitelist * -!backend !invokeai !ldm !pyproject.toml !README.md -!scripts # Guard against pulling in any models that might exist in the directory tree **/*.pt* **/*.ckpt -# whitelist frontend, but ignore node_modules -invokeai/frontend/node_modules -invokeai/frontend/dist/** +# ignore frontend but whitelist dist +invokeai/frontend/** +!invokeai/frontend/dist + +# ignore invokeai/assets but whitelist invokeai/assets/web +invokeai/assets +!invokeai/assets/web # ignore python cache **/__pycache__ diff --git a/.github/workflows/build-container.yml b/.github/workflows/build-container.yml index 6612dff2d3..7e940ca015 100644 --- a/.github/workflows/build-container.yml +++ b/.github/workflows/build-container.yml @@ -47,16 +47,18 @@ jobs: type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=semver,pattern={{major}} - type=sha + type=raw,value='sha'-{{sha}}-${{ matrix.flavor}} + type=raw,value={{branch}}-${{ matrix.flavor }} flavor: | latest=${{ matrix.flavor == 'cuda' && github.ref == 'refs/heads/main' }} - suffix=${{ matrix.flavor }},onlatest=false - name: Set up QEMU uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 + with: + platforms: ${{ matrix.platforms }} - name: Login to GitHub Container Registry if: github.event_name != 'pull_request' @@ -67,7 +69,7 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Build container - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v4 with: context: . file: ${{ matrix.dockerfile }} diff --git a/docker/Dockerfile b/docker/Dockerfile index 1d4cdaa983..a3e54d22df 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -15,7 +15,8 @@ RUN rm -f /etc/apt/apt.conf.d/docker-clean RUN \ --mount=type=cache,target=/var/cache/apt,sharing=locked \ apt-get update \ - && apt-get install -y \ + && apt-get install \ + -yqq \ --no-install-recommends \ libgl1-mesa-glx=20.3.* \ libglib2.0-0=2.66.* \ @@ -28,38 +29,24 @@ ARG APPNAME=InvokeAI WORKDIR ${APPDIR} ENV PATH=${APPDIR}/${APPNAME}/bin:$PATH -###################### -## build frontend ## -###################### -FROM node:lts as frontend-builder - -# Copy Sources -ARG APPDIR=/usr/src -ARG FRONTEND_DIR=invokeai/frontend -WORKDIR ${APPDIR}/${FRONTEND_DIR} -COPY ${FRONTEND_DIR} . - -# install dependencies -RUN \ - --mount=type=cache,target=/usr/local/share/.cache/yarn \ - yarn install \ - --frozen-lockfile \ - --non-interactive - -# build frontend -RUN yarn build - -################################### -## install python dependencies ## -################################### +####################### +## build pyproject ## +####################### FROM python-base AS pyproject-builder ENV PIP_USE_PEP517=1 +# prepare for buildkit cache +ARG PIP_CACHE_DIR=/var/cache/buildkit/pip +ENV PIP_CACHE_DIR ${PIP_CACHE_DIR} +RUN mkdir -p ${PIP_CACHE_DIR} + # Install dependencies RUN \ + --mount=type=cache,target=${PIP_CACHE_DIR} \ --mount=type=cache,target=/var/cache/apt,sharing=locked \ apt-get update \ - && apt-get install -y \ + && apt-get install \ + -yqq \ --no-install-recommends \ build-essential=12.9 \ gcc=4:10.2.* \ @@ -67,19 +54,18 @@ RUN \ && rm -rf /var/lib/apt/lists/* # create virtual environment -RUN python3 -m venv "${APPNAME}" \ +RUN --mount=type=cache,target=${PIP_CACHE_DIR} \ + python3 -m venv "${APPNAME}" \ --upgrade-deps # copy sources COPY --link . . -ARG FRONTEND_DIR=invokeai/frontend -COPY --from=frontend-builder ${APPDIR}/${FRONTEND_DIR}/dist ${FRONTEND_DIR}/dist # install pyproject.toml ARG PIP_EXTRA_INDEX_URL ENV PIP_EXTRA_INDEX_URL ${PIP_EXTRA_INDEX_URL} ARG PIP_PACKAGE=. -RUN --mount=type=cache,target=/root/.cache/pip,sharing=locked \ +RUN --mount=type=cache,target=${PIP_CACHE_DIR} \ "${APPDIR}/${APPNAME}/bin/pip" install ${PIP_PACKAGE} # build patchmatch @@ -91,7 +77,7 @@ RUN python3 -c "from patchmatch import patch_match" FROM python-base AS runtime # setup environment -COPY --from=pyproject-builder ${APPDIR}/${APPNAME} ${APPDIR}/${APPNAME} +COPY --from=pyproject-builder --link ${APPDIR}/${APPNAME} ${APPDIR}/${APPNAME} ENV INVOKEAI_ROOT=/data ENV INVOKE_MODEL_RECONFIGURE="--yes --default_only"