Search code examples
phpdockerdocker-composelamp

How to save user uploaded files to mounted volume using PHP, docker-compose?


I have a LAMP stack configured with docker-compose, and am having issues saving user uploaded files to a mounted volume for persistent storage. Here is my compose file:

    version: '3.7'
services:

  php-apache:
    build: './php-apache'
    restart: always
    ports:
      - 5000:80
    volumes:
      - ./public_html:/var/www/html
      - ./composer/vendor:/var/www/html/vendor
      - ./tmp:/usr/local/tmp
      - ./cert/:/usr/local/apache2/cert
      - covers:/var/lib/app-data/covers:rw
      - ebooks:/var/lib/app-data/ebooks:rw
    depends_on: 
      - mysql
      - composer

  mysql:
    build: './mysql'
    restart: always
    ports:
      - '33061:3306'
    volumes:
      - ./database:/var/lib/mysql
      - ./mysql/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
    environment: 
      MYSQL_ROOT_PASSWORD: secretpw
      MYSQL_USER: myuser
      MYSQL_PASSWORD: mypw 
      MYSQL_DATABASE: mydb

  composer:
    build: './composer'
    working_dir: /composer
    volumes:
      - ./composer:/composer
    command: install

volumes:
  covers: {}
  ebooks: {}

In my PHP code, I attempt to save files to the volumes:

    if (!move_uploaded_file($_FILES[$file]['tmp_name'], $path . $filename)) {
        throw new RuntimeException("Failed to move uploaded file.");
    }

And I get the following error:

Warning: move_uploaded_file(/var/lib/app-data/covers/useruploadedfile.jpg): failed to open stream: Permission denied

I have attempted to change permissions on the volume to no avail. Is there any way to give PHP write permissions to mounted volumes?


Solution

  • I found a solution with the guidance of @Nguyen, although there was a bit more to it in my situation so I thought I would write my own detailed answer in case it may help someone.

    If you are using Docker on MacOS, Docker is actually running on a Linux VM and not natively on the machine. This had tripped me up when attempting to change permissions on the host machine (the host machine from the perspective of docker is the VM).

    I found what user and group id was executing my PHP script using the following functions:

    echo posix_getuid();
    echo posix_getgid();
    

    I found out the mount location for my volume using the following command:

    docker volume inspect nameofyourvolume
    

    When I tried to chown the directory that the volume was mounted in (/var/lib/docker/volumes) I was getting "no such file or directory". After doing some research, I realized that the path for the mount location was relative to the VM running docker. I found a way to get into this VM with the following command (see https://www.bretfisher.com/docker-for-mac-commands-for-getting-into-local-docker-vm/):

    docker run -it --rm --privileged --pid=host justincormack/nsenter1
    

    This drops you into a container with full permissions to the VM. You can then change permissions to the directory holding your volumes as usual.