Доступ к гнезду Docker в контейнере

Я пытаюсь создать контейнер, который может получить доступ к удаленному API-интерфейсу док-станции через файл сокета-докере (хост-машина -/var/run/docker.sock).

В ответе здесь предлагается прокси-запрос на сокет. Как я могу это сделать?

Ответы

Ответ 2

Если вы собираетесь использовать Docker из контейнера, он должен четко понимать последствия для безопасности.

Доступ к Docker изнутри контейнера прост:

  • Открыть контейнер unix в контейнере
  • Bind mount docker client binary to container, так что можно избежать установки пакета докеров в контейнере

Вот почему

docker run -v /var/run/docker.sock:/var/run/docker.sock \
       -v $(which docker):/bin/docker \
       -ti ubuntu

должен делать трюк и быть почти свободным от побочных эффектов.

Вопросы:

  • Все контейнеры-контейнеры будут доступны для контейнера, поэтому он может остановить их, удалить, запустить любые команды как любой пользователь в контейнерах Docker верхнего уровня.
  • Все созданные контейнеры создаются в докере верхнего уровня.
  • Конечно, вы должны понимать, что если у контейнера есть доступ к демону Docker хоста, он имеет привилегированный доступ ко всей хост-системе. В зависимости от конфигурации контейнера и системы (AppArmor) она может быть менее или более опасной.
  • Другие предупреждения здесь dont-expose-the-docker-socket

Другие подходы, такие как выставление контейнера /var/lib/docker, могут привести к повреждению данных. Подробнее см. do-not-use-docker-in-docker-for-ci.

Примечание для пользователей официального контейнера Jenkins CI

В этом контейнере (и, возможно, во многих других) процесс jenkins выполняется как пользователь без полномочий root. Поэтому у него нет разрешения на взаимодействие с докером-сокетом. Настолько быстрое и грязное решение работает

docker exec -u root ${NAME} /bin/chmod -v a+s $(which docker)

после запуска контейнера. Это позволяет всем пользователям в контейнере запускать двоичный файл docker с правами root. Лучшим подходом было бы разрешить запуск двоичного файла docker через sudo без пароля, но официальный образ Jenkins CI, похоже, не имеет подсистемы sudo.

Ответ 3

Я наткнулся на эту страницу, пытаясь заставить вызовы сокетов-докеров работать из контейнера, который работает как пользователь nobody.

В моем случае я получал доступ к отказам в ошибках, когда my-service попытался вызвать вызовы в сокет docker для отображения доступных контейнеров.

В итоге я использовал docker-socket-proxy, чтобы прокси-сервер подключался к my-service. Это другой подход к доступу к сокету докера в контейнере, поэтому, хотя я бы поделился им.

Я сделал my-service, чтобы получить хост докера, с которым он должен разговаривать, docker-socker-proxy в этом случае через переменную среды DOCKER_HOST.

Обратите внимание, что docker-socket-proxy необходимо запустить как пользователь root, чтобы проксировать доклерский сокет до 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

Обратите внимание, что указанный выше составной файл готов к рою (docker stack deploy my-service), но он также должен работать в режиме компоновки (docker-compose up -d). Самое приятное в этом подходе состоит в том, что my-service больше не нужно запускать в диспетчере рой.