Làm cách nào để chạy tập lệnh shell trên máy chủ từ vùng chứa docker?


94

Làm cách nào để kiểm soát máy chủ từ vùng chứa docker?

Ví dụ, làm thế nào để thực thi được sao chép vào tập lệnh bash của máy chủ lưu trữ?


8
Điều đó sẽ không hoàn toàn ngược lại với việc cách ly máy chủ khỏi docker?
Marcus Müller

31
Đúng. Nhưng nó đôi khi cần thiết.
Alex Ushakov


Không chắc chắn về "máy chủ điều khiển" nhưng gần đây tôi đã tham gia một cuộc nói chuyện của các nhà khoa học dữ liệu, những người đang sử dụng docker để chạy các tập lệnh nhằm xử lý khối lượng công việc khổng lồ (sử dụng GPU gắn AWS) và xuất kết quả cho máy chủ. Một trường hợp sử dụng rất thú vị. Về cơ bản các kịch bản được đóng gói với một môi trường thực thi đáng tin cậy nhờ vào Docker
KCD

@KCD Và tại sao họ lại thích ứng dụng chứa thông qua docker thay vì sử dụng vùng chứa cấp hệ thống (LXC)?
Alex Ushakov

Câu trả lời:


28

Điều đó THỰC SỰ phụ thuộc vào những gì bạn cần tập lệnh bash đó để làm!

Ví dụ: nếu tập lệnh bash chỉ lặp lại một số đầu ra, bạn có thể làm

docker run --rm -v $(pwd)/mybashscript.sh:/mybashscript.sh ubuntu bash /mybashscript.sh

Một khả năng khác là bạn muốn tập lệnh bash để cài đặt một số phần mềm - giả sử tập lệnh để cài đặt docker-comp. bạn có thể làm một cái gì đó như

docker run --rm -v /usr/bin:/usr/bin --privileged -v $(pwd)/mybashscript.sh:/mybashscript.sh ubuntu bash /mybashscript.sh

Nhưng tại thời điểm này, bạn thực sự phải biết rõ tập lệnh đang làm gì để cho phép các quyền cụ thể mà nó cần trên máy chủ của bạn từ bên trong vùng chứa.


1
Tôi đã có ý tưởng tạo vùng chứa kết nối với máy chủ và tạo các vùng chứa mới.
Alex Ushakov

1
Docker có vẻ không thích thú cưỡi tương đối của bạn. Điều này sẽ hoạt độngdocker run --rm -v $(pwd)/mybashscript.sh:/work/mybashscript.sh ubuntu /work/mybashscript.sh
KCD

5
Dòng đầu tiên bắt đầu một vùng chứa ubuntu mới và gắn tập lệnh vào nơi nó có thể đọc được. Chẳng hạn, nó không cho phép vùng chứa truy cập vào hệ thống tệp máy chủ. Dòng thứ hai hiển thị máy chủ lưu trữ /usr/binvới vùng chứa. Trong cả hai trường hợp, vùng chứa đều không có quyền truy cập đầy đủ vào hệ thống máy chủ. Có lẽ tôi sai, nhưng nó có vẻ là một câu trả lời tồi cho một câu hỏi tồi.
Paul

3
Công bằng - câu hỏi khá mơ hồ. Câu hỏi không yêu cầu "toàn quyền truy cập vào hệ thống máy chủ lưu trữ". Như đã mô tả, nếu tập lệnh bash chỉ nhằm mục đích lặp lại một số đầu ra, nó sẽ không CẦN bất kỳ quyền truy cập nào vào hệ thống tệp máy chủ. Đối với ví dụ thứ hai của tôi, đó là cài đặt docker-comp, quyền duy nhất bạn cần là quyền truy cập vào thư mục bin nơi tệp nhị phân được lưu trữ. Như tôi đã nói ở phần đầu - để làm điều này, bạn sẽ phải có những ý tưởng rất cụ thể về những gì script đang làm để cho phép các quyền phù hợp.
Paul Becotte

1
Đã thử điều này, tập lệnh được thực thi trong vùng chứa, không phải trên máy chủ
All2Pie

60

Giải pháp tôi sử dụng là kết nối với máy chủ lưu trữ SSHvà thực hiện lệnh như sau:

ssh -l ${USERNAME} ${HOSTNAME} "${SCRIPT}"

CẬP NHẬT

Vì câu trả lời này tiếp tục nhận được phiếu bầu, tôi muốn nhắc nhở (và đặc biệt khuyên bạn) rằng tài khoản đang được sử dụng để gọi tập lệnh phải là tài khoản không có quyền nào cả, mà chỉ thực thi tập lệnh đó với tư cách là sudo(có thể thực hiện từ sudoerstệp).


Như một workaround, container có thể ra một tập hợp các lệnh và dẫn chương trình có thể chạy chúng sau khi thoát khỏi container: eval $ (Docker chạy --rm -nó container_name_to_output script)
parity3

Tôi cần chạy một dòng lệnh trên Máy chủ từ bên trong vùng chứa Docker, nhưng khi tôi vào vùng chứa, sshkhông tìm thấy. Bạn có bất cứ lời đề nghị khác?
Ron Rosenfeld

@RonRosenfeld, bạn đang sử dụng hình ảnh Docker nào? trong trường hợp debian / ubuntu, chạy này: apt update && apt install openssh-client.
Mohammed Noureldin

Nó sẽ là bất cứ thứ gì đã được cài đặt trên NAS Synology của tôi. Làm thế nào tôi có thể nói?
Ron Rosenfeld

@RonRosenfeld, xin lỗi tôi không hiểu những gì bạn có nghĩa là
Mohammed Noureldin

52

Đã sử dụng một đường ống được đặt tên. Trên hệ điều hành máy chủ, tạo một tập lệnh để lặp và đọc các lệnh, sau đó bạn gọi eval trên đó.

Yêu cầu bộ chứa docker đọc đến đường ống được đặt tên đó.

Để có thể truy cập đường ống, bạn cần phải gắn nó qua một ổ đĩa.

Điều này tương tự như cơ chế SSH (hoặc một phương pháp dựa trên ổ cắm tương tự), nhưng hạn chế bạn thích hợp với thiết bị chủ, có lẽ tốt hơn. Thêm vào đó, bạn không cần phải chuyển thông tin xác thực.

Cảnh báo duy nhất của tôi là hãy thận trọng về lý do tại sao bạn đang làm điều này. Đó là điều hoàn toàn cần làm nếu bạn muốn tạo một phương thức để tự nâng cấp với đầu vào của người dùng hoặc bất cứ điều gì, nhưng có thể bạn không muốn gọi một lệnh để lấy một số dữ liệu cấu hình, vì cách thích hợp sẽ là chuyển nó vào dưới dạng args / volume vào docker. Cũng nên thận trọng về thực tế là bạn đang đánh giá, vì vậy chỉ cần suy nghĩ về mô hình cấp phép.

Một số câu trả lời khác như chạy script. Dưới một ổ đĩa sẽ không hoạt động chung vì chúng sẽ không có quyền truy cập vào toàn bộ tài nguyên hệ thống, nhưng nó có thể phù hợp hơn tùy thuộc vào cách sử dụng của bạn.


14
CHÚ Ý: Đây là câu trả lời đúng / hay nhất và cần thêm một chút khen ngợi. Mọi câu trả lời khác đều loay hoay với việc hỏi "bạn đang cố gắng làm gì" và đưa ra ngoại lệ cho những thứ. Tôi có một trường hợp sử dụng rất cụ thể yêu cầu tôi có thể làm điều này và đây là câu trả lời tốt duy nhất imho. SSH ở trên sẽ yêu cầu hạ thấp tiêu chuẩn bảo mật / tường lửa và công cụ chạy docker chỉ là sai. Cám ơn vì cái này. Tôi cho rằng điều này không nhận được nhiều lượt ủng hộ vì nó không phải là một câu trả lời sao chép / dán đơn giản, nhưng đây là câu trả lời. +100 điểm từ tôi nếu tôi có thể
Farley

3
Đối với những người đang tìm kiếm thêm thông tin, bạn có thể sử dụng tập lệnh sau chạy trên máy chủ: unix.stackexchange.com/a/369465 Tất nhiên, bạn sẽ phải chạy nó với 'nohup' và tạo một số loại trình bao bọc trình giám sát để duy trì nó còn sống (có thể sử dụng một công việc định kỳ: P)
sucotronic

7
Đây có thể là một câu trả lời tốt. Tuy nhiên, sẽ tốt hơn nhiều nếu bạn cung cấp thêm chi tiết và giải thích thêm về dòng lệnh. Có thể công phu không?
Mohammed Noureldin

5
Được ủng hộ, Điều này hoạt động! Tạo một đường ống được đặt tên bằng cách sử dụng 'mkfifo host_executor_queue' nơi ổ đĩa được gắn kết. Sau đó, để thêm người tiêu dùng thực thi các lệnh được đưa vào hàng đợi dưới dạng trình bao của máy chủ, hãy sử dụng 'tail -f host_executor_queue | sh & '. Dấu & ở cuối làm cho nó chạy trong nền. Cuối cùng để đẩy các lệnh vào hàng đợi, hãy sử dụng 'echo touch foo> host_executor_queue' - kiểm tra này tạo một tệp tạm thời foo tại thư mục chính. Nếu bạn muốn người dùng bắt đầu khi khởi động hệ thống, hãy đặt '@reboot tail -f host_executor_queue | sh & 'trong crontab. Chỉ cần thêm đường dẫn tương đối vào host_executor_queue.
skybunk

1
ai đó có thể chỉnh sửa câu trả lời bằng mã ví dụ?
Lucas Pottersky

6

Nếu bạn không lo lắng về bảo mật và chỉ đơn giản là bạn đang tìm cách khởi động một bộ chứa docker trên máy chủ từ bên trong một bộ chứa docker khác như OP, bạn có thể chia sẻ máy chủ docker đang chạy trên máy chủ với bộ chứa docker bằng cách chia sẻ ổ cắm lắng nghe của nó.

Vui lòng xem https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface và xem khả năng chấp nhận rủi ro cá nhân của bạn có cho phép điều này đối với ứng dụng cụ thể này hay không.

Bạn có thể thực hiện việc này bằng cách thêm các vòng khối lượng sau vào lệnh bắt đầu của mình

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

hoặc bằng cách chia sẻ /var/run/docker.sock trong tệp soạn thảo docker của bạn như sau:

version: '3'

services:
   ci:
      command: ...
      image: ...
      volumes
         - /var/run/docker.sock:/var/run/docker.sock

Khi bạn chạy lệnh bắt đầu docker trong vùng chứa docker của mình, máy chủ docker đang chạy trên máy chủ của bạn sẽ thấy yêu cầu và cung cấp vùng chứa anh chị em.

tín dụng: http://jpetazzo.github.io/2015/09/03/do-not-use-docker-in-docker-for-ci/


1
Hãy xem xét rằng docker phải được cài đặt trong vùng chứa, nếu không, bạn cũng sẽ cần phải gắn một ổ đĩa cho mã nhị phân docker (ví dụ /usr/bin/docker:/usr/bin/docker:).
Gerry

1
Hãy cẩn thận khi lắp ổ cắm docker vào bộ chứa của bạn, đây có thể là một vấn đề bảo mật nghiêm trọng: docs.docker.com/engine/security/security/…
DatGuyKaj

@DatGuyKaj cảm ơn, tôi đã chỉnh sửa câu trả lời của mình để phản ánh các vấn đề mà tài nguyên của bạn nêu ra.
Matt Bucci

Điều này không trả lời câu hỏi, đó là về việc chạy tập lệnh trên máy chủ lưu trữ, không phải trong vùng chứa
Brandon

5

Câu trả lời này chỉ là một phiên bản chi tiết hơn của giải pháp của Bradford Medeiros , đối với tôi nó cũng hóa ra là câu trả lời tốt nhất, vì vậy công lao sẽ thuộc về anh ta.

Trong câu trả lời của mình, anh ấy giải thích LÀM GÌ ( đường ống được đặt tên ) nhưng không chính xác LÀM THẾ NÀO để làm điều đó.

Tôi phải thừa nhận rằng tôi không biết những gì được đặt tên là ống dẫn tại thời điểm tôi đọc giải pháp của mình. Vì vậy, tôi đã cố gắng thực hiện nó (trong khi nó thực sự đơn giản), nhưng tôi đã thành công, vì vậy tôi rất vui được giúp đỡ bằng cách giải thích cách tôi đã làm. Vì vậy, quan điểm của câu trả lời của tôi là chỉ nêu chi tiết các lệnh bạn cần chạy để nó hoạt động, nhưng một lần nữa, tín dụng sẽ thuộc về anh ta.

PHẦN 1 - Thử nghiệm khái niệm đường ống được đặt tên mà không có docker

Trên máy chủ chính, chọn thư mục mà bạn muốn đặt tệp ống dẫn có tên của mình, ví dụ: /path/to/pipe/và tên ống dẫn mypipe, sau đó chạy:

mkfifo /path/to/pipe/mypipe

Đường ống được tạo ra. Kiểu

ls -l /path/to/pipe/mypipe 

Và kiểm tra các quyền truy cập bắt đầu bằng "p", chẳng hạn như

prw-r--r-- 1 root root 0 mypipe

Bây giờ chạy:

tail -f /path/to/pipe/mypipe

Thiết bị đầu cuối hiện đang đợi dữ liệu được gửi vào đường ống này

Bây giờ hãy mở một cửa sổ đầu cuối khác.

Và sau đó chạy:

echo "hello world" > /path/to/pipe/mypipe

Kiểm tra thiết bị đầu cuối đầu tiên (thiết bị đầu cuối có tail -f), nó sẽ hiển thị "hello world"

PHẦN 2 - Chạy lệnh qua đường ống

Trên vùng chứa máy chủ, thay vì chạy tail -fchỉ xuất bất cứ thứ gì được gửi dưới dạng đầu vào, hãy chạy lệnh này sẽ thực thi nó dưới dạng các lệnh:

eval "$(cat /path/to/pipe/mypipe)"

Sau đó, từ thiết bị đầu cuối khác, hãy thử chạy:

echo "ls -l" > /path/to/pipe/mypipe

Quay lại terminal đầu tiên và bạn sẽ thấy kết quả của ls -llệnh.

PHẦN 3 - Làm cho nó nghe mãi mãi

Bạn có thể nhận thấy rằng trong phần trước, ngay sau khi ls -lđầu ra được hiển thị, nó sẽ dừng nghe lệnh.

Thay vì eval "$(cat /path/to/pipe/mypipe)"chạy:

while true; do eval "$(cat /path/to/pipe/mypipe)"; done

(bạn có thể nohup điều đó)

Giờ đây, bạn có thể gửi lần lượt số lượng lệnh không giới hạn, tất cả chúng sẽ được thực thi, không chỉ lệnh đầu tiên.

PHẦN 4 - Làm cho nó hoạt động ngay cả khi khởi động lại xảy ra

Cảnh báo duy nhất là nếu máy chủ phải khởi động lại, vòng lặp "while" sẽ ngừng hoạt động.

Để xử lý khởi động lại, đây là những gì tôi đã làm:

Đưa while true; do eval "$(cat /path/to/pipe/mypipe)"; donevào một tệp execpipe.sh#!/bin/bashtiêu đề

Đừng quên chmod +x

Thêm nó vào crontab bằng cách chạy

crontab -e

Và sau đó thêm

@reboot /path/to/execpipe.sh

Tại thời điểm này, hãy kiểm tra nó: khởi động lại máy chủ của bạn và khi nó được sao lưu, hãy lặp lại một số lệnh vào đường dẫn và kiểm tra xem chúng có được thực thi hay không. Tất nhiên, bạn không thể thấy đầu ra của các lệnh, vì vậy ls -lsẽ không giúp ích được gì, nhưng touch somefilesẽ hữu ích.

Một tùy chọn khác là sửa đổi tập lệnh để đưa đầu ra vào một tệp, chẳng hạn như:

while true; do eval "$(cat /path/to/pipe/mypipe)" &> /somepath/output.txt; done

Bây giờ bạn có thể chạy ls -lvà đầu ra (cả stdout và stderr sử dụng &>trong bash) phải ở trong output.txt.

PHẦN 5 - Làm cho nó hoạt động với docker

Nếu bạn đang sử dụng cả docker compile và dockerfile như tôi, đây là những gì tôi đã làm:

Giả sử bạn muốn gắn kết thư mục mẹ của mypipe như /hostpipetrong vùng chứa của bạn

Thêm điều này:

VOLUME /hostpipe

trong tập tin docker của bạn để tạo điểm gắn kết

Sau đó thêm cái này:

volumes:
   - /path/to/pipe:/hostpipe

trong tệp soạn thảo docker của bạn để mount / path / to / pipe as / hostpipe

Khởi động lại bộ chứa docker của bạn.

PHẦN 6 - Thử nghiệm

Thực thi vào vùng chứa docker của bạn:

docker exec -it <container> bash

Vào thư mục mount và kiểm tra, bạn có thể thấy đường dẫn:

cd /hostpipe && ls -l

Bây giờ hãy thử chạy một lệnh từ bên trong vùng chứa:

echo "touch this_file_was_created_on_main_host_from_a_container.txt" > /hostpipe/mypipe

Và nó sẽ hoạt động!

CẢNH BÁO: Nếu bạn có máy chủ OSX (Mac OS) và vùng chứa Linux, nó sẽ không hoạt động (giải thích tại đây https://stackoverflow.com/a/43474708/10018801 và sự cố tại đây https://github.com/docker / for-mac / issue / 483 ) vì cách triển khai đường dẫn không giống nhau, vì vậy những gì bạn viết vào đường dẫn từ Linux chỉ có thể được đọc bởi Linux và những gì bạn viết vào đường dẫn từ Mac OS chỉ có thể được đọc bởi một Mac OS (câu này có thể không chính xác lắm, nhưng chỉ cần lưu ý rằng có một vấn đề đa nền tảng).

Ví dụ: khi tôi chạy thiết lập docker trong DEV từ máy tính Mac OS của mình, đường ống có tên như đã giải thích ở trên không hoạt động. Nhưng trong phần dàn dựng và sản xuất, tôi có máy chủ Linux và bộ chứa Linux, và nó hoạt động hoàn hảo.

PHẦN 7 - Ví dụ từ vùng chứa Node.JS

Đây là cách tôi gửi một lệnh từ vùng chứa nút js của tôi đến máy chủ chính và truy xuất đầu ra:

const pipePath = "/hostpipe/mypipe"
const outputPath = "/hostpipe/output.txt"
const commandToRun = "pwd && ls-l"

console.log("delete previous output")
if (fs.existsSync(outputPath)) fs.unlinkSync(outputPath)

console.log("writing to pipe...")
const wstream = fs.createWriteStream(pipePath)
wstream.write(commandToRun)
wstream.close()

console.log("waiting for output.txt...") //there are better ways to do that than setInterval
let timeout = 10000 //stop waiting after 10 seconds (something might be wrong)
const timeoutStart = Date.now()
const myLoop = setInterval(function () {
    if (Date.now() - timeoutStart > timeout) {
        clearInterval(myLoop);
        console.log("timed out")
    } else {
        //if output.txt exists, read it
        if (fs.existsSync(outputPath)) {
            clearInterval(myLoop);
            const data = fs.readFileSync(outputPath).toString()
            if (fs.existsSync(outputPath)) fs.unlinkSync(outputPath) //delete the output file
            console.log(data) //log the output of the command
        }
    }
}, 300);

Điều này hoạt động tốt. Còn về vấn đề bảo mật? Tôi muốn sử dụng điều này để bắt đầu / dừng các bộ chứa docker từ bên trong một bộ chứa đang chạy? Có phải tôi chỉ tạo một người dùng dockeruser mà không có bất kỳ đặc quyền nào ngoại trừ việc chạy các lệnh docker không?
Kristof van Woensel

4

Viết một máy chủ python máy chủ đơn giản đang lắng nghe trên một cổng (giả sử 8080), liên kết cổng -p 8080: 8080 với vùng chứa, thực hiện một yêu cầu HTTP tới localhost: 8080 để yêu cầu máy chủ python chạy các tập lệnh shell với popen, chạy một cuộn hoặc viết mã để tạo một yêu cầu HTTP curl -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()

IMO đây là câu trả lời tốt nhất. Chạy các lệnh tùy ý trên máy chủ PHẢI được thực hiện thông qua một số loại API (ví dụ: REST). Đây là cách duy nhất để bảo mật có thể được thực thi và các quy trình đang chạy có thể được kiểm soát đúng cách (ví dụ: giết, xử lý stdin, stdout, exit-code, v.v.). Nếu tất nhiên sẽ rất tuyệt nếu API này có thể chạy bên trong Docker, nhưng cá nhân tôi không ngại chạy nó trực tiếp trên máy chủ.
barney765

2

Sự lười biếng của tôi đã khiến tôi tìm ra giải pháp dễ dàng nhất mà chưa được công bố như một câu trả lời ở đây.

Nó dựa trên bài báo tuyệt vời của luc juggery .

Tất cả những gì bạn cần làm để có được một trình bao đầy đủ cho máy chủ linux của bạn từ bên trong vùng chứa docker của bạn là:

docker run --privileged --pid=host -it alpine:3.8 \
nsenter -t 1 -m -u -n -i sh

Giải trình:

--privileged: cấp quyền bổ sung cho vùng chứa, nó cho phép vùng chứa có quyền truy cập vào các thiết bị của máy chủ (/ dev)

--pid = host: cho phép các vùng chứa sử dụng cây quy trình của máy chủ Docker (máy ảo mà daemon Docker đang chạy) Tiện ích nsenter: cho phép chạy một tiến trình trong các không gian tên hiện có (các khối xây dựng cung cấp cách ly cho các vùng chứa)

nsenter (-t 1 -m -u -n -i sh) cho phép chạy quá trình sh trong cùng bối cảnh cách ly với quá trình với PID 1. Toàn bộ lệnh sau đó sẽ cung cấp một trình bao tương tác trong VM

Thiết lập này có ý nghĩa bảo mật chính và nên được sử dụng cẩn thận (nếu có).


1
docker run --detach-keys="ctrl-p" -it -v /:/mnt/rootdir --name testing busybox
# chroot /mnt/rootdir
# 

3
Mặc dù câu trả lời này có thể giải quyết câu hỏi của OP, nhưng bạn nên giải thích cách nó hoạt động và tại sao nó giải quyết được vấn đề. Điều này giúp các nhà phát triển mới hiểu điều gì đang xảy ra và cách tự khắc phục sự cố này và các vấn đề tương tự. Cảm ơn vì đã đóng góp!
Caleb Kleveter 14/1218

1

Tôi có một cách tiếp cận đơn giản.

Bước 1: Mount /var/run/docker.sock:/var/run/docker.sock (Vì vậy, bạn sẽ có thể thực hiện các lệnh docker bên trong vùng chứa của mình)

Bước 2: Thực hiện điều này bên dưới bên trong vùng chứa của bạn. Phần quan trọng ở đây là ( - máy chủ mạng vì nó sẽ thực thi từ ngữ cảnh máy chủ)

docker run -i --rm --network host -v /opt/test.sh:/test.sh alpine: 3.7 sh /test.sh

test.sh nên chứa một số lệnh (ifconfig, netstat, v.v.) bất cứ thứ gì bạn cần. Bây giờ bạn sẽ có thể nhận được đầu ra ngữ cảnh máy chủ.


2
Theo tài liệu chính thức của docker về kết nối mạng sử dụng mạng máy chủ, "Tuy nhiên, theo tất cả các cách khác, chẳng hạn như lưu trữ, không gian tên quy trình và không gian tên người dùng, quy trình được cách ly với máy chủ." Kiểm tra - docs.docker.com/network/network-tutorial-host
Peter Mutisya

0

Như Marcus đã nhắc, về cơ bản docker là quá trình cô lập. Bắt đầu với docker 1.8, bạn có thể sao chép tệp theo cả hai cách giữa máy chủ và vùng chứa, hãy xem tài liệu củadocker cp

https://docs.docker.com/reference/commandline/cp/

Sau khi một tệp được sao chép, bạn có thể chạy nó cục bộ


1
Tôi biết điều đó. Nói cách khác, làm cách nào để chạy tập lệnh này từ bên trong vùng chứa docker?
Alex Ushakov


2
@AlexUshakov: không được. Làm điều đó sẽ phá vỡ rất nhiều lợi thế của docker. Đừng làm vậy. Đừng thử nó. Xem xét lại những gì bạn cần làm.
Marcus Müller

Xem thêm Vlad của lừa forums.docker.com/t/...
user2915097

1
bạn luôn có thể, trên máy chủ lưu trữ, nhận giá trị của một số biến trong vùng chứa của bạn, chẳng hạn như myvalue=$(docker run -it ubuntu echo $PATH)và kiểm tra nó thường xuyên trong một trình bao tập lệnh (tất nhiên, bạn sẽ sử dụng một cái gì đó khác ngoài $ PATH, chỉ là một ví dụ), khi nó được một số giá trị cụ thể, bạn khởi động kịch bản của bạn
user2915097

0

Bạn có thể sử dụng khái niệm ống dẫn, nhưng sử dụng tệp trên máy chủ và fswatch để thực hiện mục tiêu thực thi một tập lệnh trên máy chủ từ bộ chứa docker. Như vậy (Sử dụng có rủi ro của riêng bạn):

#! /bin/bash

touch .command_pipe
chmod +x .command_pipe

# Use fswatch to execute a command on the host machine and log result
fswatch -o --event Updated .command_pipe | \
            xargs -n1 -I "{}"  .command_pipe >> .command_pipe_log  &

 docker run -it --rm  \
   --name alpine  \
   -w /home/test \
   -v $PWD/.command_pipe:/dev/command_pipe \
   alpine:3.7 sh

rm -rf .command_pipe
kill %1

Trong ví dụ này, bên trong vùng chứa gửi lệnh tới / dev / command_pipe, như sau:

/home/test # echo 'docker network create test2.network.com' > /dev/command_pipe

Trên máy chủ, bạn có thể kiểm tra xem mạng đã được tạo chưa:

$ docker network ls | grep test2
8e029ec83afe        test2.network.com                            bridge              local

-7

Để mở rộng phản hồi của người dùng2915097 :

Ý tưởng của sự cô lập là có thể hạn chế những gì một ứng dụng / quy trình / vùng chứa (bất kể góc độ của bạn ở đây là gì) có thể làm với hệ thống máy chủ rất rõ ràng. Do đó, có thể sao chép và thực thi một tệp sẽ thực sự phá vỡ toàn bộ khái niệm.

Đúng. Nhưng nó đôi khi cần thiết.

Không. Không phải vậy, hoặc Docker không phải là thứ thích hợp để sử dụng. Những gì bạn nên làm là khai báo một giao diện rõ ràng cho những gì bạn muốn làm (ví dụ: cập nhật cấu hình máy chủ), và viết một máy khách / máy chủ tối thiểu để thực hiện chính xác điều đó và không cần thêm gì nữa. Nói chung, tuy nhiên, điều này có vẻ không được mong muốn cho lắm. Trong nhiều trường hợp, bạn chỉ nên nghĩ lại cách tiếp cận của mình và loại bỏ nhu cầu đó. Docker ra đời khi về cơ bản mọi thứ đều là một dịch vụ có thể truy cập được bằng một số giao thức. Tôi không thể nghĩ ra bất kỳ cách sử dụng thích hợp nào của vùng chứa Docker có được quyền thực thi các nội dung tùy ý trên máy chủ.


Tôi có trường hợp sử dụng: Tôi có dịch vụ dày đặc A(src trên github). Trong Arepo, tôi tạo các hook thích hợp mà sau lệnh 'git pull', tạo hình ảnh docker mới và chạy chúng (tất nhiên là xóa vùng chứa cũ). Tiếp theo: github có các web-hook cho phép tạo yêu cầu POST đến liên kết điểm cuối tùy ý sau khi push on master. Vì vậy, tôi sẽ không tạo dịch vụ dày đặc B sẽ là điểm cuối đó và sẽ chỉ chạy 'git pull' trong repo A trong máy HOST (quan trọng: lệnh 'git pull' phải được thực hiện trong môi trường HOST - không phải trong môi trường B vì B không thể chạy container mới A bên trong B ...)
Kamil Kiełczewski

1
Vấn đề: Tôi muốn không có gì trong HOST ngoại trừ linux, git và docker. Và tôi muốn có dịch vụ dockerizet A và dịch vụ B (thực chất là trình xử lý git-push thực thi git pull trên repo A sau khi ai đó thực hiện git push trên master). Vì vậy, tự động triển khai git là một trường hợp sử dụng có vấn đề
Kamil Kiełczewski

@ KamilKiełczewski Tôi đang cố gắng làm chính xác như vậy, bạn đã tìm ra giải pháp chưa?
dùng871784

1
Nói, "Không, không phải vậy" là suy nghĩ hẹp hòi và cho rằng bạn biết mọi trường hợp sử dụng trên thế giới. Trường hợp sử dụng của chúng tôi đang chạy thử nghiệm. Chúng cần chạy trong các vùng chứa để kiểm tra môi trường một cách chính xác, nhưng với bản chất của các bài kiểm tra, chúng cũng cần thực thi các tập lệnh trên máy chủ.
Senica Gonzalez

1
Chỉ dành cho những người thắc mắc tại sao tôi để lại câu trả lời -7: a) Không sao cả. Tôi đã sai. OK rằng điều này được ghi lại ở đây. b) Các ý kiến ​​đóng góp thực sự có giá trị; xóa câu trả lời cũng sẽ xóa chúng. c) Nó vẫn đóng góp một quan điểm có thể là khôn ngoan để xem xét (đừng phá vỡ sự cô lập của bạn nếu bạn không cần thiết. Tuy nhiên, đôi khi bạn phải làm vậy).
Marcus Müller
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.