Search code examples
dockerdocker-composedockerfile

Run a container as normal user mounting a .cache volume under its home


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

Solution

  • 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