Chạy một tập lệnh bên trong một vùng chứa docker bằng cách sử dụng tập lệnh shell


85

Tôi đang cố gắng tạo tập lệnh shell để thiết lập vùng chứa docker. Tệp tập lệnh của tôi trông giống như sau:

#!bin/bash

docker run -t -i -p 5902:5902 --name "mycontainer" --privileged myImage:new /bin/bash

Chạy tệp script này sẽ chạy vùng chứa trong một bash mới được gọi.

Bây giờ tôi cần chạy một tệp script (test.sh) đã nằm trong vùng chứa từ tập lệnh shell đã cho ở trên. (Ví dụ: cd /path/to/test.sh && ./test.sh) Làm cách nào để thực hiện điều đó?


1
Tại sao không sử dụng WORKDIRCMD?
Dharmit

1
Bạn có thể không muốn sử dụng - đặc quyền ở đây. Xem: stackoverflow.com/questions/36425230/…
CMP

Câu trả lời:


121

Bạn có thể chạy một lệnh trong một vùng chứa đang chạy bằng cách sử dụng docker exec [OPTIONS] CONTAINER COMMAND [ARG...]:

docker exec mycontainer /path/to/test.sh

Và để chạy từ một phiên bash:

docker exec -it mycontainer /bin/bash

Từ đó bạn có thể chạy tập lệnh của mình.


6
Điều gì sẽ xảy ra nếu tôi cần nhập vào / bin / bash trước rồi chạy lệnh bên trong bash đó?
zappy

44
Bạn cũng có thể chạy trực tiếp tập lệnh cục bộ từ máy chủ. docker exec -i mycontainer bash < mylocal.sh Thao tác này đọc tập lệnh máy chủ cục bộ và chạy nó bên trong vùng chứa. Bạn có thể làm điều này với những thứ khác (chẳng hạn như tệp .tgz được đưa vào tar) - nó chỉ bằng cách sử dụng '-i' để đưa vào đầu vào std của quy trình vùng chứa.
Marvin

@Marvin có gì tương đương trong PowerShell? ký tự "<" không được nhận dạng.
Nicekiwi

1
Tôi không phải là chuyên gia về powershell (rất may) nhưng tôi đã lang thang quanh SO và tìm thấy stackoverflow.com/a/11788475/500902 . Vì vậy, có thể Get-Content mylocal.sh | docker exec -i mycontainer bash. Tôi không biết liệu điều đó có hiệu quả không.
Marvin

97

Giả sử rằng vùng chứa docker của bạn đang hoạt động, bạn có thể chạy các lệnh như:

docker exec mycontainer /bin/sh -c "cmd1;cmd2;...;cmdn"

2
Tôi thích câu trả lời này; bạn không cần phải đăng nhập vào vùng chứa docker để thực hiện một lệnh hoặc một bộ lệnh. Cảm ơn bạn!
Hatem Jaber

Bạn có biết cách thực hiện bước này xa hơn và chuyển toàn bộ lệnh ( /bin/sh -c "cmd1; cmd2; ...; cmdn") làm giá trị của một biến shell không? Tôi hỏi vì 'docker run' dường như mong đợi một lệnh duy nhất và các đối số chưa được trích dẫn riêng lẻ hơn là một chuỗi được trích dẫn.
davidA

@meowsqueak: Câu trả lời này cho bạn biết cách chạy nhiều lệnh bên trong một vùng chứa đã được tạo và đang chạy mà không cần đăng nhập vào vùng chứa đó, điều này rất hữu ích trong tự động hóa. Tuy nhiên, nếu bạn muốn chạy nhiều lệnh tại thời điểm tạo vùng chứa (lệnh PS: docker run tạo và khởi động vùng chứa), bạn có thể đạt được điều đó bằng cách làm theo các câu trả lời trong cùng một luồng này stackoverflow.com/a/41363989/777617
Cyclops

Thay vì cmd1, tôi cần phải vượt qua trong một toàn bộ cho-loop - nhưng nó hy vọng ;sau khi vòng lặp tuyên bố và làm tuyên bố. Làm cách nào tôi có thể chạy toàn bộ vòng lặp for dưới dạng một lệnh đơn lẻ cmd1? Có khả thi không?
Nicholas K

18

Tôi đang tìm kiếm câu trả lời cho cùng câu hỏi này và tìm thấy ENTRYPOINT trong giải pháp Dockerfile cho tôi.

Dockerfile

...
ENTRYPOINT /my-script.sh ; /my-script2.sh ; /bin/bash

Bây giờ các tập lệnh được thực thi khi tôi khởi động vùng chứa và tôi nhận được lời nhắc bash sau khi các tập lệnh đã được thực thi.


6

Bạn cũng có thể gắn một thư mục cục bộ vào hình ảnh docker của mình và tạo nguồn script trong của bạn .bashrc. Đừng quên script phải bao gồm các hàm trừ khi bạn muốn nó thực thi trên mọi shell mới. (Điều này đã lỗi thời, hãy xem thông báo cập nhật.)

Tôi đang sử dụng giải pháp này để có thể cập nhật tập lệnh bên ngoài phiên bản docker. Bằng cách này, tôi không phải chạy lại hình ảnh nếu thay đổi xảy ra, tôi chỉ cần mở một trình bao mới. (Đã thoát khỏi việc mở lại trình bao - xem thông báo cập nhật)

Đây là cách bạn liên kết thư mục hiện tại của mình:

docker run -it -v $PWD:/scripts $my_docker_build /bin/bash

Bây giờ thư mục hiện tại của bạn được liên kết với phiên /scriptsbản docker của bạn.

(Đã lỗi thời) Để lưu các .bashrcthay đổi của bạn, hãy cam kết hình ảnh hoạt động của bạn bằng lệnh này:

docker commit $container_id $my_docker_build

Cập nhật

Để giải quyết vấn đề để mở một trình bao mới cho mọi thay đổi, bây giờ tôi làm như sau:

Trong dockerfile chính tôi thêm RUN echo "/scripts/bashrc" > /root/.bashrc". Bên trong, zshrctôi xuất thư mục script vào đường dẫn. Thư mục script hiện chứa nhiều tệp thay vì một tệp. Bây giờ tôi có thể gọi trực tiếp tất cả các tập lệnh mà không cần phải mở trình bao phụ trên mọi thay đổi.

BTW bạn cũng có thể xác định tệp lịch sử bên ngoài vùng chứa của mình. Bằng cách này, bạn không cần phải cam kết thay đổi cơ bản nữa.


Quá muộn..! @javier đã cho thấy một giải pháp thẳng thắn !! Tôi cảm thấy rằng một vẫn tốt hơn.
zappy

2
@zappy, giải pháp từ javier không giải quyết được vấn đề này một cách thuận tiện cho tôi - nhưng giải pháp của tôi đã làm được, tôi nghĩ rằng sẽ rất thú vị cho những người gặp sự cố tương tự khi họ không muốn khởi động lại (các) hình ảnh docker để cập nhật xem các chức năng họ cần. Ví dụ: nếu bạn sử dụng nhiều hình ảnh docker cùng một lúc để tạo một cụm nhà phát triển, bạn không muốn khởi động lại chúng mọi lúc.
Devpool

3

Trong trường hợp bạn không muốn (hoặc có) một vùng chứa đang chạy, bạn có thể gọi trực tiếp tập lệnh của mình bằng runlệnh.

Loại bỏ các -i -tđối số tty lặp đi lặp lại và sử dụng điều này:

    $ docker run ubuntu:bionic /bin/bash /path/to/script.sh

Điều này sẽ (không thử nghiệm) cũng hoạt động cho các tập lệnh khác:

    $ docker run ubuntu:bionic /usr/bin/python /path/to/script.py


0

Nếu bạn muốn chạy cùng một lệnh trên nhiều trường hợp, bạn có thể thực hiện điều này:

for i in c1 dm1 dm2 ds1 ds2 gtm_m gtm_sl; do docker exec -it $i /bin/bash -c "service sshd start"; done
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.