Доступ к гнезду Docker в контейнере
Я пытаюсь создать контейнер, который может получить доступ к удаленному API-интерфейсу док-станции через файл сокета-докере (хост-машина -/var/run/docker.sock).
В ответе здесь предлагается прокси-запрос на сокет. Как я могу это сделать?
Ответы
Ответ 1
Я понял это. Вы можете просто передать файл сокета через аргумент volume
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
Ответ 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
больше не нужно запускать в диспетчере рой.