You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何防止Jenkins非root容器通过Docker Socket控制宿主机环境?

问题

我发现即使以非root身份启动Jenkins容器,当挂载/var/run/docker.sock作为卷时,Jenkins仍能以root身份在宿主机环境中启动容器,甚至可操作/etc目录。

我创建了将jenkins用户加入docker组的容器,启动配置如下:

version: '3.9'

services:
  jenkins:
    image: jenkins:docker
    build: ./.docker/
    user: "${ID_USER}:${ID_GROUP}"
    env_file:
      - .env
    ports:
      - "8080:8080"
    volumes:
      - $PWD/jenkins_home:/var/jenkins_home
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - jenkins-net

networks:
  jenkins-net:

.docker目录下的Dockerfile内容为:

FROM jenkins/jenkins:latest

USER root

RUN apt-get update && apt-get install -y lsb-release

RUN curl -fsSLo /usr/share/keyrings/docker-archive-keyring.asc \
  https://download.docker.com/linux/debian/gpg
  
RUN echo "deb [arch=$(dpkg --print-architecture) \
  signed-by=/usr/share/keyrings/docker-archive-keyring.asc] \
  https://download.docker.com/linux/debian \
  $(lsb_release -cs) stable" > /etc/apt/sources.list.d/docker.list
  
RUN apt-get update && apt-get install -y docker-ce-cli

COPY ./.env .env

RUN groupadd docker && export $(cat ./.env) && \
    groupmod -g $ID_GROUP docker && usermod -aG docker jenkins

USER jenkins

.env文件内容:

ID_USER=1000
ID_GROUP=999

其中ID_GROUP为宿主机中docker组的ID。

测试发现jenkins用户可正常管理容器,但进入容器执行以下命令后,能无阻碍地在宿主机/etc目录创建文件:

docker run --rm -it -w /app -v /etc:/app ubuntu:latest touch test

请问是否有办法防止控制Jenkins容器的人以root身份在宿主机启动容器并操作其文件系统?

解决方案

以下是几种可行的限制方案,从不同层面降低风险:

1. 启用Docker用户命名空间映射

开启Docker的用户命名空间功能,将容器内的root用户映射到宿主机的普通用户,这样即使容器内用root操作,在宿主机上也仅拥有普通用户权限,无法修改/etc这类敏感目录。

  • 配置步骤:
    1. 编辑Docker守护进程配置文件/etc/docker/daemon.json,添加:
      {
        "userns-remap": "default"
      }
      
    2. 重启Docker服务:systemctl restart docker
      注意:启用后需重新处理现有容器和镜像,因为用户ID映射会改变文件权限关系。

2. 使用Docker Socket Proxy过滤命令

不要直接挂载/var/run/docker.sock,改用Docker Socket Proxy作为中间层,过滤Jenkins能执行的Docker命令,禁止创建挂载宿主机敏感目录的容器。

  • 示例docker-compose配置:
    services:
      docker-proxy:
        image: tecnativa/docker-socket-proxy
        volumes:
          - /var/run/docker.sock:/var/run/docker.sock
        environment:
          - CONTAINERS=1
          - IMAGES=1
          - VOLUMES=0  # 禁止操作卷,避免挂载宿主机目录
          - NETWORKS=1
          - EXEC=0     # 禁止进入容器执行命令
          - DELETE=1
        networks:
          - jenkins-net
      jenkins:
        image: jenkins:docker
        build: ./.docker/
        user: "${ID_USER}:${ID_GROUP}"
        env_file:
          - .env
        ports:
          - "8080:8080"
        volumes:
          - $PWD/jenkins_home:/var/jenkins_home
        networks:
          - jenkins-net
        environment:
          - DOCKER_HOST=tcp://docker-proxy:2375
    
    此配置下Jenkins只能执行代理允许的命令,无法创建挂载宿主机敏感目录的容器。

3. 配置Docker RBAC细粒度权限

通过Docker的RBAC规则(需配合Swarm或第三方工具),限制Jenkins用户可执行的Docker操作,拒绝任何挂载宿主机敏感目录的请求。

  • 核心思路:
    1. 使用第三方工具如docker-authz实现自定义授权规则,拦截包含-v /etc这类危险挂载参数的容器创建请求。
    2. 针对Jenkins用户配置仅允许创建不挂载宿主机敏感目录的容器。

4. 改用Docker-in-Docker(DinD)模式

让Jenkins在独立的Docker守护进程中运行容器,完全隔离宿主机的Docker环境。

  • 注意:DinD需要启用特权模式,但可通过配置让Jenkins的容器在独立环境内操作,不会直接影响宿主机。不过特权模式本身存在一定风险,需根据场景权衡使用。

内容的提问来源于stack exchange,提问作者Salvatore Esposito

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 15:15:11