Как управлять хостом из контейнера докеров?
Например, как выполнить скопировать на хост bash script?
Как управлять хостом из контейнера докеров?
Например, как выполнить скопировать на хост bash script?
Это действительно зависит от того, что вам нужно сделать bash script!
Например, если bash script просто отгоняет какой-то вывод, вы можете просто сделать
docker run --rm -v $(pwd)/mybashscript.sh:/mybashscript.sh ubuntu bash /mybashscript.sh
Другая возможность заключается в том, что вы хотите, чтобы bash script установил какое-то программное обеспечение - скажем, script для установки docker-compose. вы могли бы сделать что-то вроде
docker run --rm -v /usr/bin:/usr/bin --privileged -v $(pwd)/mybashscript.sh:/mybashscript.sh ubuntu bash /mybashscript.sh
Но на данном этапе вам действительно нужно знать, что делает script, чтобы разрешить конкретные разрешения, необходимые для вашего хоста изнутри контейнера.
Я знаю, что это старый вопрос, но, возможно, идеальное решение - подключиться к хосту через SSH
и выполнить команду следующим образом:
ssh -l ${USERNAME} ${HOSTNAME} "${SCRIPT}"
Поскольку этот ответ продолжает набирать голоса, я хочу добавить примечание, что учетная запись, которая используется для вызова сценария, должна быть учетной записью без каких-либо разрешений, а выполнять только этот сценарий как sudo (что можно сделать из файла sudoers
).
Использовал именованную трубу. На хосте os создайте скрипт для зацикливания и чтения команд, а затем вы вызываете eval для этого.
Попросите контейнер докера прочитать этот именованный канал.
Чтобы получить доступ к трубе, вам необходимо смонтировать ее через том.
Это похоже на механизм SSH (или аналогичный метод на основе сокетов), но правильно ограничивает вас хост-устройством, что, вероятно, лучше. Кроме того, вам не нужно передавать информацию об аутентификации.
Мое единственное предупреждение - быть осторожным относительно того, почему вы это делаете. Это совершенно не то, что нужно делать, если вы хотите создать метод для самостоятельного обновления с помощью пользовательского ввода или чего-то еще, но вы, вероятно, не хотите вызывать команду, чтобы получить некоторые данные конфигурации, поскольку правильным способом было бы передать это как аргументы/объем в докер. Также будьте осторожны с тем, что вы оцениваете, так что просто подумайте модель разрешения.
Некоторые из других ответов, такие как запуск сценария на томе, не будут работать в общем случае, поскольку у них не будет доступа ко всем системным ресурсам, но это может быть более уместно в зависимости от вашего использования.
Как напоминает Маркус, докер - это в основном изоляция процесса. Начиная с docker 1.8, вы можете копировать файлы в обоих направлениях между хостом и контейнером, см. Документ docker cp
https://docs.docker.com/reference/commandline/cp/
Как только файл будет скопирован, вы можете запустить его локально
Напишите простой серверный сервер Python, прослушивающий порт (скажем, 8080), свяжите порт -p 8080: 8080 с контейнером, сделайте HTTP-запрос к localhost: 8080, чтобы запросить сервер Python, выполняющий сценарии оболочки с помощью popen, запустить curl или написание кода для скручивания HTTP-запроса -d '{"foo": "bar"}' localhost: 8080
#!/usr/bin/python
from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer
import subprocess
import json
PORT_NUMBER = 8080
# This class will handles any incoming request from
# the browser
class myHandler(BaseHTTPRequestHandler):
def do_POST(self):
content_len = int(self.headers.getheader('content-length'))
post_body = self.rfile.read(content_len)
self.send_response(200)
self.end_headers()
data = json.loads(post_body)
// Use the post data
cmd = "your shell cmd"
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
p_status = p.wait()
(output, err) = p.communicate()
print "Command output : ", output
print "Command exit status/return code : ", p_status
self.wfile.write(cmd + "\n")
return
try:
# Create a web server and define the handler to manage the
# incoming request
server = HTTPServer(('', PORT_NUMBER), myHandler)
print 'Started httpserver on port ' , PORT_NUMBER
# Wait forever for incoming http requests
server.serve_forever()
except KeyboardInterrupt:
print '^C received, shutting down the web server'
server.socket.close()
docker run --detach-keys="ctrl-p" -it -v /:/mnt/rootdir --name testing busybox
# chroot /mnt/rootdir
#
У меня простой подход.
Шаг 1: Смонтируйте /var/run/docker.sock: /var/run/docker.sock (чтобы вы могли выполнять команды docker внутри вашего контейнера)
Шаг 2: Выполните это ниже в вашем контейнере. Ключевая часть здесь (хост --network, поскольку он будет выполняться из контекста хоста)
запуск докера -i --rm --network хост -v/opt/test.sh: /test.sh alpine: 3.7 sh/test.sh
test.sh должен содержать некоторые команды (ifconfig, netstat и т.д.), которые вам нужны. Теперь вы сможете получить контекстный вывод хоста.
Чтобы расширить user2915097's ответ:
Идея изоляции состоит в том, чтобы иметь возможность ограничить то, что приложение/процесс/контейнер (независимо от вашего угла) может сделать с хост-системой очень четко. Следовательно, возможность копирования и выполнения файла действительно нарушит всю концепцию.
Да. Но это иногда необходимо.
Нет. Это не тот случай, или Докер не подходит. Что вам нужно сделать, так это объявить четкий интерфейс для того, что вы хотите сделать (например, обновить конфигурацию хоста) и написать минимальный клиент/сервер, чтобы сделать именно это и ничего более. Однако, как правило, это не очень желательно. Во многих случаях вам следует просто пересмотреть свой подход и искоренить эту потребность. Докер пришел в существование, когда в основном все было услугой, доступной по протоколу. Я не могу придумать какой-либо надлежащий порядок использования контейнера Docker, получающего права на выполнение произвольных действий на хосте.