darkpool
darkpool

Reputation: 14641

Docker compose permission denied with volume

I have the following docker-compose file:

version: "3.8"

services:
  api:
    image: myuser/myimage
    volumes:
      - static_volume:/app/static
      - /home/deployer/config_files/gunicorn.py:/app/gunicorn.py
      - /home/deployer/log_files:/app/log_files
    env_file:
      - /home/deployer/config_files/api.env
    expose:
      - 8000

  nginx:
    image: myuser/nginximage
    volumes:
      - static_volume:/app/static
      - /home/deployer/config_files/nginx.conf:/etc/nginx/conf.d/nginx.conf
    ports:
      - 80:80
    depends_on:
      - api

volumes:
  static_volume:

The api service was built using the following docker file (summarized to reduce size):

FROM python:3.9.1

WORKDIR /app

# Copy code etc into container
COPY ./api/ .
COPY entrypoint.sh .

# create static and log files directories
RUN mkdir static
RUN mkdir log_files

# create non root user, change ownership of all files, switch to this user
RUN adduser --system --group appuser
RUN chown -R appuser:appuser /app
USER appuser

CMD [ "/app/entrypoint.sh" ]

If I remove /home/deployer/log_files:/app/log_files from the compose file everything works correctly. However I am trying to use that log files directory for gunicorn to use for log files. Including that line results in the following error when docker-compose up:

Error: Error: '/app/log_files/gunicorn_error.log' isn't writable [PermissionError(13, 'Permission denied')]

On the linux host I am running docker-compose up with the user named deployer. Inside the container as per the Dockerfile I created a user called appuser. I'm guessing this is related to the issue but I'm not sure.

Basically all I'm trying to do is to have log files inside the container be accessible outside the container so that they persist even if the server is restarted.

Upvotes: 6

Views: 19584

Answers (1)

Pierre B.
Pierre B.

Reputation: 12933

/app/log_files is still owned by deployers user inside your container and appuser does not have permission to write to it. As per your comment, it seems /home/deployer/log_files is owned by deployer:deployers with permission drwxr-xr-x. The permissions will be the same for /app/log_files inside container as per bind mount.

Even if deployers user does not exists in your container it will still be owned by the UID of deployers user (you can check this by running ls from inside the container).

You can:

  • Add world-writable permission to /home/deployer/log_files such as
    chmod 777 /home/deployer/log_files
    
    This may present a security risk though, other solution is a bit more complex but better.
  • Retrieve or set the UID of appuser and set ownership of /home/deployer/log_files to this user. For example in Dockerfile create appuser with specific UID 1500:
    RUN adduser -u 1500 --system --group appuser
    
    And from your host change directory owner to this UID
    sudo chown 1500:1500 /home/deployer/log_files
    
    At container runtime, appuser (UID 1500) will then be able to write to this directory

More generally, you should ensure /home/deployer/log_files is writable by the user running inside the container while keeping it's access secure if needed.

Upvotes: 12

Related Questions