Доступ к Docker-сокету внутри контейнера
Я пытаюсь создать контейнер, который может обращаться к удаленному API докера хоста через файл сокета докера (хост-машина - /var/run/docker.sock).
Ответ здесь предлагает проксирование запросов к сокету. Как бы я поступил так?
3 ответа
Если кто-то намеревается использовать Docker из контейнера, он должен четко понимать последствия для безопасности.
Доступ к Docker из контейнера прост:
- Использовать
docker
Официальный образ или установить Docker внутри контейнера. Или вы можете скачать архив с бинарным клиентом Docker, как описано здесь - Предоставить Unix-сокет Docker от хоста к контейнеру
Вот почему
docker run -v /var/run/docker.sock:/var/run/docker.sock \
-ti docker
должен сделать свое дело.
Кроме того, вы можете выставить в контейнер и использовать Docker REST API
UPD: В предыдущей версии этого ответа (основанной на предыдущей версии поста jpetazzo) рекомендовано связать и подключить двоичный файл докера от хоста к контейнеру. Это больше не является надежным, потому что Docker Engine больше не распространяется как (почти) статические библиотеки.
Соображения:
- Все контейнеры хоста будут доступны контейнеру, поэтому он может их останавливать, удалять, запускать любые команды как любой пользователь внутри контейнеров Docker верхнего уровня.
- Все созданные контейнеры создаются в Docker верхнего уровня.
- Конечно, вы должны понимать, что если у контейнера есть доступ к демону Docker хоста, он имеет привилегированный доступ ко всей хост-системе. В зависимости от конфигурации контейнера и системы (AppArmor), она может быть менее или более опасной
- Другие предупреждения здесь 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
больше не нужно запускать менеджер роя.