【问题标题】:How do I give right permissions to a system user to run commands in docker container?如何授予系统用户在 docker 容器中运行命令的正确权限?
【发布时间】:2021-09-15 00:19:58
【问题描述】:

使用 Docker Compose 将 Laravel 应用程序容器化。它只有两个服务:app(运行 PHP8.0-FPM)和nginx

docker-compose.yml

version: "3"
services:
    app:
        build:
            args:
                USER: novruz
            context: ./
            dockerfile: Dockerfile
        image: blogger
        container_name: blogger-app
        restart: unless-stopped
        working_dir: /var/www/
        volumes:
            - ./:/var/www/
        networks:
            - laravel

    nginx:
        image: nginx:alpine
        container_name: blogger-nginx
        restart: unless-stopped
        ports:
            - 8000:80
        volumes:
            - ./:/var/www/
            - ./.docker/nginx/:/etc/nginx/conf.d/
        networks:
            - laravel

networks:
    laravel:
        driver: bridge

Dockerfile

FROM php:8.0-fpm

ARG USER

RUN apt-get update && apt-get install -y --no-install-recommends \
        curl \
        git \
        zip \
        unzip \
        libpng-dev \
        libonig-dev \
        libxml2-dev \
        libzip-dev \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

RUN docker-php-ext-install bcmath

COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# Create a system user to run Composer and Artisan commands.
RUN useradd -G www-data,root -d /home/$USER $USER
RUN mkdir -p /home/$USER/.composer \
    && chown -R $USER:$USER /home/$USER

WORKDIR /var/www

USER $USER

这些配置成功构建 (docker-compose build app) 并运行 (docker-compose up -d) 应用程序。

问题

但是当我在app 服务容器中运行composer install --optimize-autoloader --no-dev 时,它会抛出异常:

[RuntimeException]                               
/var/www/vendor does not exist and could not be created.

这是一个权限问题,但我如何才能为在构建时创建的用户 novruz 授予正确的权限(并添加到组 www-data)?

调试

这是有趣的部分。在我的本地机器(MacBook Air M1 2020)上一切正常,但在 Ubuntu 20.04(Focal Fossa)上却不行。

ls -l 在我的本地机器上输出

-rw-r--r--  1 www-data www-data    556 Sep 14 13:53 Dockerfile
-rw-r--r--  1 www-data www-data     17 Sep  9 07:00 README.md
drwxr-xr-x  7 www-data www-data    224 Sep  7 14:33 app
-rwxr-xr-x  1 www-data www-data   1686 Sep  7 14:33 artisan
drwxr-xr-x  4 www-data www-data    128 Sep  7 14:33 bootstrap
-rw-r--r--  1 www-data www-data   1766 Sep  9 07:37 composer.json
-rw-r--r--  1 www-data www-data 338242 Sep  9 07:37 composer.lock
drwxr-xr-x 17 www-data www-data    544 Sep 13 07:22 config
drwxr-xr-x  7 www-data www-data    224 Sep 13 06:45 database
-rw-r--r--  1 www-data www-data    713 Sep 14 14:32 docker-compose.yml
-rw-r--r--  1 www-data www-data   1319 Sep  9 07:04 phpunit.xml
drwxr-xr-x  7 www-data www-data    224 Sep  7 14:33 public
drwxr-xr-x  4 www-data www-data    128 Sep  9 07:07 resources
drwxr-xr-x  6 www-data www-data    192 Sep 10 05:52 routes
-rw-r--r--  1 www-data www-data    563 Sep  7 14:33 server.php
drwxr-xr-x  5 www-data www-data    160 Sep  7 14:33 storage
drwxr-xr-x  7 www-data www-data    224 Sep  9 12:02 tests

如您所见,www-data/var/www/ 目录及其中文件的所有者。我可以毫无问题地运行任何命令。

ls -l 在 Ubuntu 20.04 上输出

-rw-rw-r--  1  998  997    599 Sep 14 13:41 Dockerfile
-rw-rw-r--  1  998  997     17 Sep 14 10:16 README.md
drwxrwxr-x  7  998  997   4096 Sep 14 10:16 app
-rwxrwxr-x  1  998  997   1686 Sep 14 10:16 artisan
drwxrwxr-x  3  998  997   4096 Sep 14 10:16 bootstrap
-rw-rw-r--  1  998  997   1766 Sep 14 10:16 composer.json
-rw-rw-r--  1  998  997 338242 Sep 14 10:16 composer.lock
drwxrwxr-x  2  998  997   4096 Sep 14 10:16 config
drwxrwxr-x  5  998  997   4096 Sep 14 10:16 database
-rw-rw-r--  1  998  997    720 Sep 14 10:16 docker-compose.yml
-rw-rw-r--  1  998  997   1319 Sep 14 10:16 phpunit.xml
drwxrwxr-x  2  998  997   4096 Sep 14 10:16 public
drwxrwxr-x  4  998  997   4096 Sep 14 10:16 resources
drwxrwxr-x  2  998  997   4096 Sep 14 10:16 routes
-rw-rw-r--  1  998  997    563 Sep 14 10:16 server.php
drwxrwxr-x  5  998  997   4096 Sep 14 10:16 storage
drwxrwxr-x  5  998  997   4096 Sep 14 10:16 tests

但在 Ubuntu 上,用户是 998,组是 997。而且我不断收到运行时异常。为什么会这样?

【问题讨论】:

    标签: docker ubuntu docker-compose


    【解决方案1】:

    这里的问题是容器内用户的UID/GID和容器外用户的UID/GID不一样。

    您可以通过三种方式解决此问题:

    1. 不要使用绑定挂载。(这是在主机和容器上都挂载目录的情况。)问题是主机和来宾在哪些用户对应哪个 UID 上存在分歧,所以如果你让他们不共享文件,这个问题就会消失。

      您可以在 Dockerfile 中使用COPY,而不是使用绑定挂载。

      COPY . /var/www
      

      缺点是在容器运行时编辑容器的文件会很有用。

    2. 在容器内外匹配 UID/GID。 与其在构建时创建用户,不如在运行时覆盖 FPM 进程的 UID/GID。这可以在 docker compose 中完成,如下所示:How to set uid and gid in Docker Compose?

    3. 使用用户命名空间重新映射用户。我从来没有尝试过这种方法,所以我不能给你任何指导,但这里是关于如何做到这一点的 Docker 文档:https://docs.docker.com/engine/security/userns-remap/

      另外,这里有一个关于使用绑定挂载的用户重新映射的线程:https://forums.docker.com/t/permission-denied-when-using-userns-remap-and-writing-to-a-directory-mounted-from-the-host/48379/2

    【讨论】:

    • 谢谢。在第一种方法中,我也不应该在Dockerfile 中创建和设置用户,对吧?
    • @N'Bayramberdiyev 对。
    • 安装应用程序后,在映像中创建一些非 root 用户并在 Dockerfile 的最后切换到该用户通常是一个好习惯。但该用户不需要任何特定的用户 ID,也不需要匹配主机 uid。
    猜你喜欢
    • 1970-01-01
    • 2012-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-16
    • 2019-06-10
    • 2018-07-10
    相关资源
    最近更新 更多