dockerdocker-composealpine-linux

User game lacks write access to log with docker compose up


I have a container I am defining in a Dockerfile:

FROM python:3.9-alpine

WORKDIR /usr/app/

COPY src/backend/ .

RUN apk add acl
RUN pip install -r requirements.txt

RUN adduser -D game wheel
RUN setfacl -Rdm u:game:rwx /usr/app/
RUN chown -hR game /usr/app/ && chown -hR game /var/log/
USER game
HEALTHCHECK CMD curl --fail http://localhost:5000 || exit 1

CMD [ "python", "./src/app.py" ]

The intention is to run the container as 'game' user. The docker-compose file portion defining this service is this:

server:
    container_name: "server"
    user: game
    build:
      context: .
      dockerfile: ./src/backend/Dockerfile
    volumes:
      - ./src/backend/:/usr/app
    ports:
      - 5000:5000
    depends_on:
      - redis

And the command to start the service: sudo docker compose -f docker-compose.yml up -d --no-deps

However, the application fails when writing to log with this line: PermissionError: [Errno 13] Permission denied: '/usr/app/log'

Even though the game user is owner of the /usr/app folder, it isn't permitted to write in it. I verified this by adding prints in the application of the current user, and it's permissions, and I saw the write permissions are missing. This isn't reproduced when running the Docker image without the compose. So it looks like it's related to how the compose runs the docker. What should be changed in the Docker definitions to allow the game user to write in this directory?


Solution

  • Quick answer: you are using volume.

    Long answer: When you run the container through Compose, your ./src/backend/ on host system is mounted to /usr/app inside the container and it's owned by the user id and group id from your local system. You can check that quickly by doing exec inside the container and doing ls -lah. You will see all the files belonging to your user's user id group id (presumably 1000:1000).

    There are couple things you can do about it.

    1. Forget the game user and run as root. Why not?

    2. Build your image with the source code, just COPY it before you create the game user and do chown afterwards. You'll need to rebuild the image every time you want to run the new changes in the code.

    3. Create the game user with your user's user id and group id. This will possibly break portability. Bad solution.

    4. Run the container, exec into it and chown again. This will break your local development for you though, as the files and directories in ./src/backend/ will be owned by whatever user id and group id game has assigned.