首页 > 解决方案 > 如何使用 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.");
    }

我收到以下错误:

警告:move_uploaded_file(/var/lib/app-data/covers/useruploadedfile.jpg):无法打开流:权限被拒绝

我试图更改卷的权限无济于事。有没有办法给 PHP 写权限到挂载的卷?

标签: phpdockerdocker-composelamp

解决方案


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

如果你在 MacOS 上使用 Docker,Docker 实际上是在 Linux VM 上运行,而不是在机器上本机运行。在尝试更改主机上的权限时,这让我感到很困惑(从 docker 的角度来看,主机是虚拟机)。

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

echo posix_getuid();
echo posix_getgid();

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

docker volume inspect nameofyourvolume

当我尝试 chown 安装卷的目录(/var/lib/docker/volumes)时,我得到“没有这样的文件或目录”。经过一番研究,我意识到挂载位置的路径是相对于运行 docker 的 VM 而言的。我找到了一种使用以下命令进入此 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 具有完全权限的容器中。然后,您可以像往常一样更改保存卷的目录的权限。


推荐阅读