diff --git a/docker/Dockerfile b/docker/Dockerfile index 230c7e584e7..8d99aa4c5c8 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -4,7 +4,7 @@ ARG PYTHON_VERSION=3.9 ################## ## base image ## ################## -FROM python:${PYTHON_VERSION}-slim AS python-base +FROM docker.io/python:${PYTHON_VERSION}-slim AS python-base LABEL org.opencontainers.image.authors="mauwii@outlook.de" @@ -13,10 +13,7 @@ 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 # Install necessary packages -RUN \ - --mount=type=cache,target=/var/cache/apt,sharing=locked \ - --mount=type=cache,target=/var/lib/apt,sharing=locked \ - apt-get update \ +RUN apt-get update \ && apt-get install -y \ --no-install-recommends \ libgl1-mesa-glx=20.3.* \ @@ -34,6 +31,9 @@ ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONUNBUFFERED 1 # don't fall back to legacy build system ENV PIP_USE_PEP517=1 +# set env for next stages +ENV APPDIR=${APPDIR} +ENV APPNAME=${APPNAME} ####################### ## build pyproject ## @@ -41,10 +41,7 @@ ENV PIP_USE_PEP517=1 FROM python-base AS pyproject-builder # Install dependencies -RUN \ - --mount=type=cache,target=/var/cache/apt,sharing=locked \ - --mount=type=cache,target=/var/lib/apt,sharing=locked \ - apt-get update \ +RUN apt-get update \ && apt-get install -y \ --no-install-recommends \ build-essential=12.9 \ @@ -57,18 +54,16 @@ ENV PIP_CACHE_DIR ${PIP_CACHE_DIR} RUN mkdir -p ${PIP_CACHE_DIR} # create virtual environment -RUN --mount=type=cache,target=${PIP_CACHE_DIR},sharing=locked \ - python3 -m venv "${APPNAME}" \ +RUN python3 -m venv "${APPNAME}" \ --upgrade-deps # copy sources -COPY --link . . +COPY . . # install pyproject.toml ARG PIP_EXTRA_INDEX_URL ENV PIP_EXTRA_INDEX_URL ${PIP_EXTRA_INDEX_URL} -RUN --mount=type=cache,target=${PIP_CACHE_DIR},sharing=locked \ - "${APPNAME}/bin/pip" install . +RUN "${APPNAME}/bin/pip" install . # build patchmatch RUN python3 -c "from patchmatch import patch_match" @@ -84,7 +79,8 @@ RUN useradd \ --no-log-init \ -m \ -U \ - "${UNAME}" + "${UNAME}" \ + -u 1000 # create volume directory ARG VOLUME_DIR=/data diff --git a/docker/build.sh b/docker/build.sh index 21108d2d217..9eb8088b6b3 100755 --- a/docker/build.sh +++ b/docker/build.sh @@ -22,6 +22,7 @@ DOCKERFILE=${INVOKE_DOCKERFILE:-./Dockerfile} # print the settings echo -e "You are using these values:\n" +echo -e "Container engine:\t${CONTAINER_ENGINE}" echo -e "Dockerfile:\t\t${DOCKERFILE}" echo -e "index-url:\t\t${PIP_EXTRA_INDEX_URL:-none}" echo -e "Volumename:\t\t${VOLUMENAME}" @@ -32,20 +33,37 @@ echo -e "Container Tag:\t\t${CONTAINER_TAG}" echo -e "Container Flavor:\t${CONTAINER_FLAVOR}" echo -e "Container Image:\t${CONTAINER_IMAGE}\n" +# Create outputs directory if it does not exist +[[ -d ./outputs ]] || mkdir ./outputs + # Create docker volume -if [[ -n "$(docker volume ls -f name="${VOLUMENAME}" -q)" ]]; then +if [[ -n "$(${CONTAINER_ENGINE} volume ls -f name="${VOLUMENAME}" -q)" ]]; then # Note: newer versions of podman: podman volume exists ${VOLUMENAME} echo -e "Volume already exists\n" else - echo -n "creating docker volume " - docker volume create "${VOLUMENAME}" + echo -n "creating ${CONTAINER_ENGINE} volume " + "${CONTAINER_ENGINE}" volume create "${VOLUMENAME}" fi # Build Container -DOCKER_BUILDKIT=1 docker build \ +DOCKER_BUILDKIT=1 "${CONTAINER_ENGINE}" build \ --platform="${PLATFORM:-linux/amd64}" \ --tag="${CONTAINER_IMAGE:-invokeai}" \ ${CONTAINER_FLAVOR:+--build-arg="CONTAINER_FLAVOR=${CONTAINER_FLAVOR}"} \ ${PIP_EXTRA_INDEX_URL:+--build-arg="PIP_EXTRA_INDEX_URL=${PIP_EXTRA_INDEX_URL}"} \ + ${PYTHON_VERSION:+--build-arg="PYTHON_VERSION=${PYTHON_VERSION}"} \ ${PIP_PACKAGE:+--build-arg="PIP_PACKAGE=${PIP_PACKAGE}"} \ --file="${DOCKERFILE}" \ .. + +# Podman only: set ownership for user 1000:1000 (appuser) the right way +if [[ ${CONTAINER_ENGINE} == "podman" ]] ; then + echo Setting ownership for container\'s appuser on /data and /data/outputs + podman run \ + --mount type=volume,src="${VOLUMENAME}",target=/data \ + --user root --entrypoint "/bin/chown" "${CONTAINER_IMAGE:-invokeai}" \ + -R 1000:1000 /data + podman run \ + --mount type=bind,source="$(pwd)"/outputs,target=/data/outputs \ + --user root --entrypoint "/bin/chown" "${CONTAINER_IMAGE:-invokeai}" \ + -R 1000:1000 /data/outputs +fi diff --git a/docker/env.sh b/docker/env.sh index 6eecb24e8e6..d7d5baddc2a 100644 --- a/docker/env.sh +++ b/docker/env.sh @@ -2,6 +2,12 @@ # This file is used to set environment variables for the build.sh and run.sh scripts. +# docker is the default container engine, but should work with "podman" (rootless) too! +CONTAINER_ENGINE=${CONTAINER_ENGINE:-docker} + +# use python v3.9 by default +PYTHON_VERSION=${PYTHON_VERSION:-3.9} + # Try to detect the container flavor if no PIP_EXTRA_INDEX_URL got specified if [[ -z "$PIP_EXTRA_INDEX_URL" ]]; then @@ -13,10 +19,10 @@ if [[ -z "$PIP_EXTRA_INDEX_URL" ]]; then fi # Decide which container flavor to build if not specified - if [[ -z "$CONTAINER_FLAVOR" ]] && python -c "import torch" &>/dev/null; then + if [[ -z "$CONTAINER_FLAVOR" ]] && python3 -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)") + CUDA_AVAILABLE=$(python3 -c "import torch;print(torch.cuda.is_available())") + ROCM_AVAILABLE=$(python3 -c "import torch;print(torch.version.hip is not None)") if [[ "${CUDA_AVAILABLE}" == "True" ]]; then CONTAINER_FLAVOR="cuda" elif [[ "${ROCM_AVAILABLE}" == "True" ]]; then @@ -41,6 +47,14 @@ REPOSITORY_NAME="${REPOSITORY_NAME-$(basename "$(git rev-parse --show-toplevel)" REPOSITORY_NAME="${REPOSITORY_NAME,,}" VOLUMENAME="${VOLUMENAME-"${REPOSITORY_NAME}_data"}" ARCH="${ARCH-$(uname -m)}" +if [ $ARCH == "aarch64" ] +then + ARCH=arm64 +fi +if [ $ARCH == "x86_64" ] +then + ARCH=amd64 +fi PLATFORM="${PLATFORM-linux/${ARCH}}" INVOKEAI_BRANCH="${INVOKEAI_BRANCH-$(git branch --show)}" CONTAINER_REGISTRY="${CONTAINER_REGISTRY-"ghcr.io"}" diff --git a/docker/run.sh b/docker/run.sh index c52ccb4c4de..1bb582fdb71 100755 --- a/docker/run.sh +++ b/docker/run.sh @@ -8,27 +8,31 @@ cd "$SCRIPTDIR" || exit 1 source ./env.sh -# Create outputs directory if it does not exist -[[ -d ./outputs ]] || mkdir ./outputs - echo -e "You are using these values:\n" +echo -e "Container engine:\t${CONTAINER_ENGINE}" echo -e "Volumename:\t${VOLUMENAME}" echo -e "Invokeai_tag:\t${CONTAINER_IMAGE}" echo -e "local Models:\t${MODELSPATH:-unset}\n" -docker run \ +if [[ "${CONTAINER_ENGINE}" == "podman" ]]; then + PODMAN_ARGS="--user=appuser:appuser" + unset PLATFORM #causes problems +fi + +"${CONTAINER_ENGINE}" run \ --interactive \ --tty \ --rm \ - --platform="${PLATFORM}" \ + ${PLATFORM+--platform="${PLATFORM}"} \ --name="${REPOSITORY_NAME,,}" \ --hostname="${REPOSITORY_NAME,,}" \ - --mount=source="${VOLUMENAME}",target=/data \ + --mount type=volume,src="${VOLUMENAME}",target=/data \ --mount type=bind,source="$(pwd)"/outputs,target=/data/outputs \ ${MODELSPATH:+--mount="type=bind,source=${MODELSPATH},target=/data/models"} \ ${HUGGING_FACE_HUB_TOKEN:+--env="HUGGING_FACE_HUB_TOKEN=${HUGGING_FACE_HUB_TOKEN}"} \ --publish=9090:9090 \ --cap-add=sys_nice \ + ${PODMAN_ARGS:+"${PODMAN_ARGS}"} \ ${GPU_FLAGS:+--gpus="${GPU_FLAGS}"} \ "${CONTAINER_IMAGE}" ${@:+$@}