This Dockerfile builds a python FastAPI project as root under /app, installing system packages, python libraries via poetry and copying the files and at the end creates a non privileged "llmuser" user and chowns the /app tree to it:
FROM python:3.11-slim-bookworm as base
RUN apt-get update && \
apt-get install -y iputils-ping curl && \
rm -rf /var/lib/apt/lists/*
RUN pip install --no-cache-dir poetry==1.8.2
FROM base as dependencies
WORKDIR /app
COPY pyproject.toml poetry.lock /app/
RUN poetry install --no-interaction
FROM dependencies as application
WORKDIR /app
COPY llm_fast/*.py llm_fast/
COPY llm_fast/llmlib llm_fast/llmlib/
COPY resources resources/
COPY .env ./
RUN useradd -ms /bin/bash llmuser
RUN chown -R llmuser:llmuser /app
USER llmuser
this image build well and then is launched via the following docker compose service file:
version: "3.8"
services:
llm_fast:
image: llm_fast:v0.4
command: poetry run python -m gunicorn -w 1 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8086 llm_fast.vectorize:app
ports:
- "8086:8086"
user: "1000:1000"
volumes:
- models_cache:/home/llmuser/.cache
volumes:
models_cache:
where the user 1000:1000 is to get the /home/llmuser/.cache volume mounted belonging to 1000:1000 so that when the application runs under the llmuser user and want to write something in it it can.
But I am doing something wrong since with this setup the build runs fine but when I try running the image with docker compose up I see the (abridged) logs:
bob ~/code/llm_fast [main] $ docker compose up
[+] Running 1/0
✔ Container llm_fast-llm_fast-1 Recreated 0.1s
Attaching to llm_fast-1
llm_fast-1 | Creating virtualenv llm-fast-9TtSrW0h-py3.11 in /home/llmuser/.cache/pypoetry/virtualenvs
llm_fast-1 | usage: .... abridged virtualenv help
llm_fast-1 | virtualenv: error: argument dest: the destination . is not write-able at /home/llmuser/.cache
llm_fast-1 exited with code 2
In your case the /home/llmuser/.cache
directory does not exist beforehand. At runtime when Docker binds the models_cache
volume it creates the directory with root ownership.
So you need to create the /home/llmuser/.cache
directory and and give the dedicated ownership/permissions during the build step before a volume is attached to it.
Just update the last instructions in you Dockerfile like so:
RUN useradd -ms /bin/bash llmuser
RUN \
chown -R llmuser:llmuser /app \
&& mkdir -p /home/llmuser/.cache \
&& chown -R llmuser:llmuser /home/llmuser/.cache
USER llmuser