如何使用 PHP、docker-compose 将用户上传的文件保存到已安装的卷?

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

我有一个使用 docker-compose 配置的 LAMP 堆栈,在将用户上传的文件保存到已安装的卷以进行持久存储时遇到问题。这是我的撰写文件:

    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: {}

在我的 PHP 代码中,我尝试将文件保存到卷中:

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

我收到以下错误:

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

我已尝试更改卷的权限但无济于事。有什么方法可以给已安装的卷 PHP 写权限吗?

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

简而言之,在您的场景上下文中,无法从 docker 容器中更改已安装卷的权限。您需要从主机级别执行此操作。

当主机基于 Linux(例如 RedHat,Ubuntu)时通常会发生此问题,而它在 MacOS 上运行良好。您将需要:

  • 找出 docker 容器内的哪个用户 ID 是 运行 命令。
  • 确保主机上的同一用户 id 有足够的权限在安装的文件夹中创建文件。

我在@Nguyen 的指导下找到了一个解决方案,尽管在我的情况下还有更多,所以我想我会写下我自己的详细答案,以防它可能对某人有所帮助。

如果您在 MacOS 上使用 Docker,Docker 实际上是 运行 在 Linux 虚拟机上,而不是在机器上。这让我在尝试更改主机权限时被绊倒了(从 docker 的角度来看,主机是 VM)。

我找到了使用以下函数执行我的 PHP 脚本的用户和组 ID:

echo posix_getuid();
echo posix_getgid();

我使用以下命令找到了我的卷的安装位置:

docker volume inspect nameofyourvolume

当我尝试 chown 卷挂载目录 (/var/lib/docker/volumes) 时,我得到 "no such file or directory"。经过一些研究,我意识到挂载位置的路径是相对于 VM 运行 docker。我找到了一种使用以下命令进入此 VM 的方法(请参阅 https://www.bretfisher.com/docker-for-mac-commands-for-getting-into-local-docker-vm/):

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

这会将您带入对 VM 具有完全权限的容器中。然后,您可以像往常一样更改对保存您的卷的目录的权限。