为什么 composer 以 root 身份运行,即使它的 setuid 已更改为另一个用户

Why composer runs as root even though it's setuid has been changed to another user

我正在使用官方 docker php 图像作为基础图像并在其上安装了 Composer。下面给出了我的 docker 文件中的一些片段。

RUN  set ex \
  # Install Composer
  && curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin -- --filename=composer \
  && chown www-data:www-data /usr/local/bin/composer \
  && chmod u+s /usr/local/bin/composer 

Docker 主进程 运行s 作为 root 和辅助进程 运行s 作为 www-data。当我在我的容器上 运行 composer install 时,root 拥有供应商目录和 composer.lock 等作为容器的主进程 运行s 作为 root。所以我将 /usr/local/bin/composer 的所有者更改为 www-data 并在其上设置了 u+s setuid。你可以在下面看到它。

/var/www/test # ls -al /usr/local/bin/composer 
-rwsr-sr-x    1 www-data www-data   1875611 Oct 21 00:56 /usr/local/bin/composer

但是当我 运行 composer 安装时,仍然使用 root 所有者创建的供应商目录等。我在做什么错了?

-rwxr-x---    1 1000     www-data      2299 Oct 19 06:36 composer.json
-rw-r--r--    1 root     root        276423 Oct 21 01:02 composer.lock
drwxr-x---    4 1000     www-data      4096 Oct 19 06:36 drush
-rwxr-x---    1 1000     www-data       414 Oct 19 06:36 load.environment.php
-rwxr-x---    1 1000     www-data       481 Oct 19 06:36 phpunit.xml.dist
drwxr-x---    3 1000     www-data      4096 Oct 19 06:36 scripts
drwxr-xr-x   50 root     root          4096 Oct 21 01:08 vendor
drwxr-x---    7 1000     nginx         4096 Oct 21 01:02 web

Update-1 作曲家保存供应商目录的目录是绑定安装的命名卷。我的 docker-compose 文件如下:

version: "3.3"

services:

  nginx:
    container_name: ${PROJECT_NAME}.nginx
    build: ./docker/nginx
    image: witbix/nginx
    restart: always
    volumes:
      - drupal:/var/www/${PROJECT_NAME}:cached
    working_dir: /var/www/${PROJECT_NAME}
    environment:
      PROJECT_NAME: ${PROJECT_NAME}
      DOMAIN_NAME: ${DOMAIN_NAME}
      DRUPAL_VERSION: ${DRUPAL_VERSION}
      MYSQL_HOSTNAME: ${PROJECT_NAME}.mariadb
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
      MYSQL_PORT: ${MYSQL_PORT}
      HOST_USER: ${USER}
    labels:
      - "traefik.frontend.rule=Host:${DOMAIN_NAME}"
    networks:
      - drupal

  php:
    container_name: ${PROJECT_NAME}
#    build: ./docker/php
    image: witbix/php
    restart: always
    volumes:
      - drupal:/var/www/${PROJECT_NAME}:cached
    working_dir: /var/www/${PROJECT_NAME}
    environment:
      GITHUB_TOKEN: ${GITHUB_TOKEN}
    networks:
      - drupal

  mariadb:
    container_name: ${PROJECT_NAME}.mariadb
#    build: ./docker/mariadb
    image: witbix/mariadb
    restart: always
    volumes:
      - database:/var/lib/mysql
    environment:
       MYSQL_USER: ${MYSQL_USER}
       MYSQL_PASSWORD: ${MYSQL_PASSWORD}
       MYSQL_DATABASE: ${MYSQL_DATABASE}
       MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
    networks:
      - drupal

volumes:
  drupal:
    driver: local
    driver_opts:
      type: bind
      device: $PWD/code/drupal
      o: bind
  database:
    driver: local

networks:
  drupal:
    external:
     name: ${NETWORK_NAME}

所以当我在我的 nginx 容器上执行 mount 命令时,它给我以下输出。

/var/www/test # mount
    overlay on / type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/CYKNPHGSOXMLOUVNEOJ6QITFA2:/var/lib/docker/overlay2/l/OOOELOMQBXBBMCRFGVOTTOXUTQ:/var/lib/docker/overlay2/l/SLGSDLE7HYX7AY4JCOWPJIKD73:/var/lib/docker/overlay2/l/RMB5364TWTFBFY6HFZWJVTROKW:/var/lib/docker/overlay2/l/JGNFDDFSDHLKE4E63LME3E7QM3:/var/lib/docker/overlay2/l/STSQQ4PZE25ZTSNMTHBBD6AELJ:/var/lib/docker/overlay2/l/XJLZ5WXZZF55YINJ7TMCDMIL6G:/var/lib/docker/overlay2/l/W3DF5PJFB4H57RBOZ44CLWKGEP:/var/lib/docker/overlay2/l/NKVID7PASLZXXMDWZW6AHFPGOE:/var/lib/docker/overlay2/l/TQQRV5LAYELBLUBS5D6FPHRI3S,upperdir=/var/lib/docker/overlay2/0865874042b7848d173e19593df0f3397f466450f5f3b8f3d33fc79a33c3f336/diff,workdir=/var/lib/docker/overlay2/0865874042b7848d173e19593df0f3397f466450f5f3b8f3d33fc79a33c3f336/work)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
tmpfs on /dev type tmpfs (rw,nosuid,size=65536k,mode=755)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=666)
sysfs on /sys type sysfs (ro,nosuid,nodev,noexec,relatime)
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,relatime,mode=755)
cgroup on /sys/fs/cgroup/systemd type cgroup (ro,nosuid,nodev,noexec,relatime,xattr,name=systemd)
cgroup on /sys/fs/cgroup/pids type cgroup (ro,nosuid,nodev,noexec,relatime,pids)
cgroup on /sys/fs/cgroup/memory type cgroup (ro,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (ro,nosuid,nodev,noexec,relatime,net_cls,net_prio)
cgroup on /sys/fs/cgroup/devices type cgroup (ro,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (ro,nosuid,nodev,noexec,relatime,cpu,cpuacct)
cgroup on /sys/fs/cgroup/blkio type cgroup (ro,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (ro,nosuid,nodev,noexec,relatime,hugetlb)
cgroup on /sys/fs/cgroup/cpuset type cgroup (ro,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/rdma type cgroup (ro,nosuid,nodev,noexec,relatime,rdma)
cgroup on /sys/fs/cgroup/freezer type cgroup (ro,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/perf_event type cgroup (ro,nosuid,nodev,noexec,relatime,perf_event)
mqueue on /dev/mqueue type mqueue (rw,nosuid,nodev,noexec,relatime)
/dev/vda1 on /etc/resolv.conf type ext4 (rw,relatime,data=ordered)
/dev/vda1 on /etc/hostname type ext4 (rw,relatime,data=ordered)
/dev/vda1 on /etc/hosts type ext4 (rw,relatime,data=ordered)
shm on /dev/shm type tmpfs (rw,nosuid,nodev,noexec,relatime,size=65536k)
/dev/vda1 on /var/www/test type ext4 (rw,relatime,data=ordered)
proc on /proc/bus type proc (ro,relatime)
proc on /proc/fs type proc (ro,relatime)
proc on /proc/irq type proc (ro,relatime)
proc on /proc/sys type proc (ro,relatime)
proc on /proc/sysrq-trigger type proc (ro,relatime)
tmpfs on /proc/acpi type tmpfs (ro,relatime)
tmpfs on /proc/kcore type tmpfs (rw,nosuid,size=65536k,mode=755)
tmpfs on /proc/keys type tmpfs (rw,nosuid,size=65536k,mode=755)
tmpfs on /proc/timer_list type tmpfs (rw,nosuid,size=65536k,mode=755)
tmpfs on /proc/sched_debug type tmpfs (rw,nosuid,size=65536k,mode=755)
tmpfs on /proc/scsi type tmpfs (ro,relatime)
tmpfs on /sys/firmware type tmpfs (ro,relatime)

但是在我的 php 容器上执行 mount 命令没有提供任何输出。它可能是因为我用 nginx 挂载了本地文件,然后将那个 nginx 卷与 php 一起使用。

composer 程序是一个 ascii 文本文件,因此 setuid 位对其没有影响。由于您以 root 身份启动该过程,因此您可以执行类似 su www-data -c "composer ...."

的操作