Доступ к Docker-сокету внутри контейнера

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

Ответ здесь предлагает проксирование запросов к сокету. Как бы я поступил так?

3 ответа

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

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

  1. Использовать docker Официальный образ или установить Docker внутри контейнера. Или вы можете скачать архив с бинарным клиентом Docker, как описано здесь
  2. Предоставить Unix-сокет Docker от хоста к контейнеру

Вот почему

docker run -v /var/run/docker.sock:/var/run/docker.sock \
       -ti docker

должен сделать свое дело.

Кроме того, вы можете выставить в контейнер и использовать Docker REST API

UPD: В предыдущей версии этого ответа (основанной на предыдущей версии поста jpetazzo) рекомендовано связать и подключить двоичный файл докера от хоста к контейнеру. Это больше не является надежным, потому что Docker Engine больше не распространяется как (почти) статические библиотеки.

Соображения:

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

Другие подходы, такие как разоблачение /var/lib/docker к контейнеру могут привести к повреждению данных. Смотрите https://jpetazzo.github.io/2015/09/03/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. Лучшим подходом было бы разрешить запуск бинарного файла докера через sudo без пароля, но официальному образу Jenkins CI, похоже, не хватает подсистемы sudo.

Я понял. Вы можете просто передать файл сокета через аргумент громкости

docker run -v /var/run/docker.sock:/container/path/docker.sock

Как отмечает @zarathustra, это может быть не самой лучшей идеей. Смотрите: https://www.lvh.io/posts/dont-expose-the-docker-socket-not-even-to-a-container.html

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

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

Я закончил тем, что использовал 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 больше не нужно запускать менеджер роя.

Другие вопросы по тегам