Search code examples
dockerpermissionsdocker-composefile-permissionsuser-permissions

User and file permission configuration in Docker containers (docker-compose version 3)


Docker states that its containers are

"...by default, quite secure; especially if you take care of running your processes inside the containers as non-privileged users (i.e., non-root)"

As a result, I've tried to:

  1. Use official images that handle user execution appropriately
  2. Avoid mounting host volumes in production, and using COPY instead

When I COPY code and configuration files to my container volumes, all of the directories and files are created "...with a UID and GID of 0" (root ownership), as stated in the documentation here.

Question: Are there still security risks if the files and directories are owned by root but the running process is owned by a non-root user, like www-data? For example, with php-fpm:

root@7bf71145c18c:/var/www/html# ls -l
total 1220
-rw-rw-r-- 1 root root    5931 May 10 12:28 index.php
drwxrwxr-x 3 root root    4096 May 10 12:28 logs
-rw-rw-r-- 1 root root      28 May 10 12:28 robots.txt

root@7bf71145c18c:/var/www/html# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 14:14 ?        00:00:00 php-fpm: master process (/usr/lo
www-data     5     1  0 14:14 ?        00:00:00 php-fpm: pool www
www-data     6     1  0 14:14 ?        00:00:00 php-fpm: pool www
root         7     0  0 14:19 ?        00:00:00 bash
root        12     7  0 14:19 ?        00:00:00 ps -ef

If so, I'm wondering how (and where) to correctly chown and chmod my files. From my research, this seems less straightforward if you're using docker-compose, which I am - I'm using both a docker-compose YAML file (version 3) in conjunction with container-specific Dockerfiles. It seems that when I chown at the end of a container's Dockerfile, the changes don't go into effect - probably because the volume (which is defined in docker-compose.yml) is created afterwards. Here's some snippets of both configurations:

docker-compose.yml:

version: '3'
services:
  fpm:
    build: ./fpm
    container_name: "fpm"
    volumes:
      - data_volume:/var/www/html
    ports:
      - "9000"
    restart: always
volumes:
  data_volume:

./fpm Dockerfile:

FROM php:7-fpm
RUN mkdir -p /var/www/html/
COPY . /var/www/html/
RUN find /var -exec chown www-data:www-data {} \;
RUN find /var -type d -exec chmod 755 {} \;
RUN find /var -type f -exec chmod 644 {} \;

With the different docker-compose versions, it's hard to sort through the various web articles, bug fixes, and feature requests surrounding this topic. I'm hoping to get some definitive direction/answers here, geared toward docker-compose version 3.


Solution

  • Question: Are there still security risks if the files and directories are owned by root but the running process is owned by a non-root user, like www-data?

    Not really. You might just need to make sure that php-fpm has read permission to these files.

    You are copying the contents of /var/www/html into the image and setting ownership/permissions at build time (Dockerfile). This is OK. That's the usual use case for creating images.

    But your docker-compose.yml mounts data_volume into the running container, replacing the /var/www/html from the image. So, whatever you had in that directory will be hidden. You will see the contents of the mounted volume, instead.

    You might want to choose what strategy you need to persist container data. Populating /var/www/html at build time is probably OK for most of the time. But, if your application writes data somewhere in that directory, then you might consider changing that path. When the container is destroyed, any data written to outisde mounted volumes will be lost. So, make sure yoru app writes to a directory that is mounted as a volume from docker-compose.yml.