diff --git a/Dockerfile b/Dockerfile index 37509bf..80a4ab7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,66 +1,108 @@ # Dockerfile for uWSGI wrapped Giftless Git LFS Server +# Shared build ARGs among stages +ARG WORKDIR=/app +ARG VENV="$WORKDIR/.venv" ### --- Build Depdendencies --- - -FROM python:3.12 as builder -MAINTAINER "Shahar Evron " - -# Build wheels for uWSGI and all requirements -RUN DEBIAN_FRONTEND=noninteractive apt-get update \ - && apt-get install -y build-essential libpcre3 libpcre3-dev git -RUN pip install -U pip -RUN mkdir /wheels - +FROM python:3.12 AS builder ARG UWSGI_VERSION=2.0.23 -RUN pip wheel -w /wheels uwsgi==$UWSGI_VERSION - -COPY requirements/main.txt /requirements.txt -RUN pip wheel -w /wheels -r /requirements.txt - -### --- Build Final Image --- - -FROM python:3.12-slim - -RUN DEBIAN_FRONTEND=noninteractive apt-get update \ - && apt-get install -y libpcre3 libxml2 tini git \ - && apt-get clean \ - && apt -y autoremove - -RUN mkdir /app - -# Install dependencies -COPY --from=builder /wheels /wheels -RUN pip install /wheels/*.whl - -# Copy project code -COPY . /app -RUN pip install -e /app - -ARG USER_NAME=giftless -ARG STORAGE_DIR=/lfs-storage -ENV GIFTLESS_TRANSFER_ADAPTERS_basic_options_storage_options_path $STORAGE_DIR - -RUN useradd -d /app $USER_NAME -RUN mkdir $STORAGE_DIR -RUN chown $USER_NAME $STORAGE_DIR - -# Pip-install some common WSGI middleware modules +# Common WSGI middleware modules to be pip-installed # These are not required in every Giftless installation but are common enough ARG EXTRA_PACKAGES="wsgi_cors_middleware" +# expose shared ARGs +ARG WORKDIR +ARG VENV + +# Set WORKDIR (also creates the dir) +WORKDIR $WORKDIR + +# Install packages to build wheels for uWSGI and other requirements +RUN set -eux ;\ + export DEBIAN_FRONTEND=noninteractive ;\ + apt-get update ;\ + apt-get install -y --no-install-recommends build-essential libpcre3 libpcre3-dev git ;\ + rm -rf /var/lib/apt/lists/* + +# Create virtual env to store dependencies, "activate" it +RUN python -m venv --upgrade-deps "$VENV" +ENV VIRTUAL_ENV="$VENV" PATH="$VENV/bin:$PATH" + +# Set a couple pip-related settings +# Wait a bit longer for slow connections +ENV PIP_TIMEOUT=100 +# Don't nag about newer pip +ENV PIP_DISABLE_PIP_VERSION_CHECK=1 +# Don't cache pip packages +ENV PIP_NO_CACHE_DIR=1 +# Require activated virtual environment +ENV PIP_REQUIRE_VIRTUALENV=1 +# Eventual python cache files go here (not to be copied) +ENV PYTHONPYCACHEPREFIX=/tmp/__pycache__ + +# Install runtime dependencies +RUN --mount=target=/build-ctx \ + pip install -r /build-ctx/requirements/main.txt +RUN pip install uwsgi==$UWSGI_VERSION +# Install extra packages into the virtual env RUN pip install ${EXTRA_PACKAGES} -WORKDIR /app +# Copy project contents necessary for an editable install +COPY .git .git/ +COPY giftless giftless/ +COPY pyproject.toml . +# Editable-install the giftless package (add a kind of a project path reference in site-packages) +# To detect the package version dynamically, setuptools-scm needs the git binary +RUN pip install -e . -ENV UWSGI_MODULE "giftless.wsgi_entrypoint" +### --- Build Final Image --- +FROM python:3.12-slim AS final +LABEL org.opencontainers.image.authors="Shahar Evron " +ARG USER_NAME=giftless +# Writable path for local LFS storage +ARG STORAGE_DIR=/lfs-storage +# Set to true to add a runtime dockerhub deprecation warning ARG IS_DOCKERHUB -# Override default docker entrypoint for dockerhub -RUN --mount=target=/build-ctx set -e ;\ - if [ "$IS_DOCKERHUB" = true ]; then \ - cp /build-ctx/scripts/docker-entrypoint-dockerhub.sh scripts/docker-entrypoint.sh ;\ +# expose shared ARGs +ARG WORKDIR +ARG VENV + +# Set WORKDIR (also creates the dir) +WORKDIR $WORKDIR + +# Create a user and set local storage write permissions +RUN set -eux ;\ + useradd -d "$WORKDIR" "$USER_NAME" ;\ + mkdir "$STORAGE_DIR" ;\ + chown "$USER_NAME" "$STORAGE_DIR" + +# Install runtime dependencies +RUN set -eux ;\ + export DEBIAN_FRONTEND=noninteractive ;\ + apt-get update ;\ + apt-get install -y libpcre3 libxml2 tini ;\ + rm -rf /var/lib/apt/lists/* + +# Use the virtual env with dependencies from builder stage +COPY --from=builder "$VENV" "$VENV" +ENV VIRTUAL_ENV="$VENV" PATH="$VENV/bin:$PATH" +# Copy project source back into the same path referenced by the editable install +COPY --from=builder "$WORKDIR/giftless" "giftless" + +# Copy desired docker-entrypoint +RUN --mount=target=/build-ctx set -eux ;\ + target_de=scripts/docker-entrypoint.sh ;\ + mkdir -p "$(dirname "$target_de")" ;\ + if [ "${IS_DOCKERHUB:-}" = true ]; then \ + cp /build-ctx/scripts/docker-entrypoint-dockerhub.sh "$target_de" ;\ + else \ + cp /build-ctx/scripts/docker-entrypoint.sh "$target_de" ;\ fi +# Set runtime properties USER $USER_NAME +ENV GIFTLESS_TRANSFER_ADAPTERS_basic_options_storage_options_path="$STORAGE_DIR" +ENV UWSGI_MODULE="giftless.wsgi_entrypoint" ENTRYPOINT ["tini", "--", "scripts/docker-entrypoint.sh"] CMD ["uwsgi", "-s", "127.0.0.1:5000", "-M", "-T", "--threads", "2", "-p", "2", \ diff --git a/requirements/dev.txt b/requirements/dev.txt index 76454ae..7fb7f99 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -248,9 +248,7 @@ urllib3==2.0.7 # responses # types-requests uv==0.5.8 - # via - # -c requirements/main.txt - # -r requirements/dev.in + # via -r requirements/dev.in vcrpy==6.0.1 # via pytest-vcr virtualenv==20.25.1 diff --git a/requirements/main.in b/requirements/main.in index 611cda2..20dbb4e 100644 --- a/requirements/main.in +++ b/requirements/main.in @@ -22,7 +22,4 @@ boto3~=1.34 # GitHub AA Provider cachetools~=5.3 -# uv: fast pip replacement -uv - importlib-metadata; python_version < '3.13' diff --git a/requirements/main.txt b/requirements/main.txt index 7b5fdec..490e194 100644 --- a/requirements/main.txt +++ b/requirements/main.txt @@ -132,8 +132,6 @@ urllib3==2.0.7 # via # botocore # requests -uv==0.5.8 - # via -r requirements/main.in webargs==8.4.0 # via -r requirements/main.in werkzeug==3.0.3