访问容器内的Docker套接字

Des*_*ris 19 docker

我正在尝试创建一个可以通过docker socket文件(主机 - /var/run/docker.sock)访问主机docker远程API的容器.

这里的答案建议代理对套接字的请求.我该怎么做呢?

Des*_*ris 25

我想到了.您只需通过volume参数传递套接字文件即可

docker run -v /var/run/docker.sock:/container/path/docker.sock
Run Code Online (Sandbox Code Playgroud)

正如@zarathustra指出的那样,这可能不是最好的主意.请参阅:https://www.lvh.io/posts/dont-expose-the-docker-socket-not-even-to-a-container.html

  • Portainer 就是这样做的 (3认同)
  • 你永远不应该这样做,请参阅https://www.lvh.io/posts/dont-expose-the-docker-socket-not-even-to-a-container.html (2认同)
  • 那么还有什么选择呢? (2认同)

Dmi*_*san 21

如果打算在容器内使用Docker,他应该清楚地了解安全隐患.

从容器内访问Docker很简单:

  1. 使用docker官方映像或在容器内安装Docker.或者您可以使用此处所述的docker client binary下载存档
  2. 将Docker unix插槽从主机暴露给容器

这就是为什么

docker run -v /var/run/docker.sock:/var/run/docker.sock \
       -ti docker
Run Code Online (Sandbox Code Playgroud)

应该做的伎俩.

或者,您可以向容器公开并使用Docker REST API

UPD:这个答案的前版本(基于以前版本的jpetazzo帖子)建议将docker二进制文件从主机绑定到容器.这不再可靠,因为Docker Engine不再作为(几乎)静态库分发.

注意事项:

  1. 容器可以访问所有主机容器,因此它可以顶级Docker容器中的任何用户一样停止,删除,运行任何命令.
  2. 所有创建的容器都在顶级Docker中创建.
  3. 当然,您应该了解如果容器可以访问主机的Docker守护程序,则它具有对整个主机系统的特权访问权限.根据容器和系统(AppArmor)配置,它可能更少或更危险
  4. 这里的其他警告不要暴露 - docker-socket

暴露/var/lib/docker给容器等其他方法可能会导致数据损坏.有关详细信息,请参阅do-not-use-docker-in-docker-for-ci.

官方Jenkins CI容器的用户请注意

在这个容器中(可能在许多其他容器中),jenkins进程以非root用户身份运行.这就是为什么它没有与docker socket交互的权限.因此快速而肮脏的解决方案正在运

docker exec -u root ${NAME} /bin/chmod -v a+s $(which docker)
Run Code Online (Sandbox Code Playgroud)

在启动容器后.这允许容器中的所有用户使用root权限运行docker binary.更好的方法是允许通过无密码sudo运行docker二进制文件,但官方的Jenkins CI映像似乎缺少sudo子系统.

  • 此外,还有一篇很棒的高级文章:http://jpetazzo.github.io/2016/04/03/one-container-to-rule-them-all/ (2认同)

Eti*_*sne 8

我在尝试从以nobody用户身份运行的容器中使 docker 套接字调用工作时偶然发现了此页面。

在我的情况下,我在my-service尝试调用 docker 套接字以列出可用容器时遇到访问被拒绝错误。

我最终使用docker-socket- proxy 将 docker 套接字代理到my-service. 这是访问容器内 docker 套接字的不同方法,所以我想分享它。

我做了my-service能够接收泊坞窗主机应该聊得来,docker-socker-proxy在这种情况下,通过DOCKER_HOST环境变量。

请注意,docker-socket-proxy需要以root用户身份运行才能将 docker 套接字代理到my-service.

示例docker-compose.yml

version: "3.1"

services:
  my-service:
    image: my-service
    environment:
      - DOCKER_HOST=tcp://docker-socket-proxy:2375
    networks:
      - my-service_my-network
  docker-socket-proxy:
    image: tecnativa/docker-socket-proxy
    environment:
      - SERVICES=1
      - TASKS=1
      - NETWORKS=1
      - NODES=1
    volumes:
     - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - my-service_my-network
    deploy:
      placement:
        constraints: [node.role == manager]

networks:
  my-network:
    driver: overlay
Run Code Online (Sandbox Code Playgroud)

请注意,上面的撰写文件是 swarm 就绪的 ( docker stack deploy my-service) 但它也应该在撰写模式下工作 ( docker-compose up -d)。这种方法的好处是my-service不再需要在 swarm manager 上运行。

  • 您介意解释为什么您的网络称为“my-network”,而您的服务将其称为“my-service_my-network”? (2认同)