การรันสคริปต์ภายในคอนเทนเนอร์นักเทียบท่าโดยใช้เชลล์สคริปต์


89

ฉันกำลังพยายามสร้างเชลล์สคริปต์สำหรับการตั้งค่าคอนเทนเนอร์นักเทียบท่า ไฟล์สคริปต์ของฉันดูเหมือนว่า:

#!bin/bash

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

การเรียกใช้ไฟล์สคริปต์นี้จะเรียกใช้คอนเทนเนอร์ใน bash ที่เรียกใหม่

ตอนนี้ฉันต้องเรียกใช้ไฟล์สคริปต์ (test.sh) ซึ่งอยู่ในคอนเทนเนอร์แล้วจากเชลล์สคริปต์ที่กำหนดด้านบน (เช่น cd /path/to/test.sh && ./test.sh) จะทำอย่างไร?


1
ทำไมไม่ใช้WORKDIRและCMD?
ธรรมิก

1
คุณอาจไม่ต้องการใช้ - มีสิทธิพิเศษที่นี่ ดู: stackoverflow.com/questions/36425230/…
CMP

คำตอบ:


123

คุณสามารถรันคำสั่งในคอนเทนเนอร์ที่กำลังรันโดยใช้docker exec [OPTIONS] CONTAINER COMMAND [ARG...]:

docker exec mycontainer /path/to/test.sh

และเพื่อเรียกใช้จากเซสชันทุบตี:

docker exec -it mycontainer /bin/bash

จากนั้นคุณสามารถเรียกใช้สคริปต์ของคุณ


6
จะเกิดอะไรขึ้นถ้าฉันต้องเข้าสู่ / bin / bash ก่อนแล้วจึงเรียกใช้คำสั่งภายใน bash นั้น?
zappy

49
คุณยังสามารถรันสคริปต์โลคัลจากโฮสต์ได้โดยตรงdocker exec -i mycontainer bash < mylocal.sh ซึ่งจะอ่านสคริปต์โลคัลโฮสต์และรันภายในคอนเทนเนอร์ คุณสามารถทำสิ่งนี้กับสิ่งอื่น ๆ ได้ (เช่นไฟล์. tgz ที่ถูกส่งไปยัง tar) - เพียงแค่ใช้ '-i' เพื่อไพพ์เข้าสู่อินพุต std ของกระบวนการคอนเทนเนอร์
Marvin

@ มาร์วินเทียบเท่ากับ PowerShell ได้อย่างไร ไม่รู้จักอักขระ "<"
Nicekiwi

1
ฉันไม่ได้เป็นกูรู PowerShell (ขอบคุณ) แต่ผมเดินไปรอบ ๆ และพบว่า SO stackoverflow.com/a/11788475/500902 Get-Content mylocal.sh | docker exec -i mycontainer bashดังนั้นอาจจะ ฉันไม่รู้ว่ามันใช้ได้หรือเปล่า
Marvin

99

สมมติว่าคอนเทนเนอร์นักเทียบท่าของคุณเปิดใช้งานแล้วคุณสามารถเรียกใช้คำสั่งเป็น:

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

2
ฉันชอบคำตอบนี้ คุณไม่จำเป็นต้องลงชื่อเข้าใช้ Docker container เพื่อดำเนินการคำสั่งหรือชุดคำสั่ง ขอขอบคุณ!
Hatem Jaber

คุณรู้หรือไม่ว่าจะก้าวไปอีกขั้นและส่งคำสั่งทั้งหมด ( /bin/sh -c "cmd1; cmd2; ...; cmdn") เป็นค่าของตัวแปรเชลล์ได้อย่างไร ฉันถามเพราะ 'นักเทียบท่าทำงาน' ดูเหมือนจะคาดหวังคำสั่งเดียวและอาร์กิวเมนต์ที่ไม่ได้อ้างถึงแต่ละรายการแทนที่จะเป็นสตริงที่ยกมา
davidA

@meowsqueak: คำตอบนี้จะบอกวิธีเรียกใช้คำสั่งหลายคำสั่งภายในคอนเทนเนอร์ที่สร้างไว้แล้วและเรียกใช้งานโดยไม่ต้องเข้าสู่ระบบคอนเทนเนอร์นั้นซึ่งมีประโยชน์ในระบบอัตโนมัติ อย่างไรก็ตามหากคุณต้องการรันคำสั่งหลายคำสั่งในขณะที่สร้างคอนเทนเนอร์ (คำสั่ง PS: docker run จะสร้างและสตาร์ทคอนเทนเนอร์) คุณสามารถทำได้โดยทำตามคำตอบในเธรดเดียวกันนี้stackoverflow.com/a/41363989/777617
Cyclops

แทนที่cmd1ฉันต้องส่งผ่านทั้งวง - แต่คาดว่าจะอยู่;หลังจากคำสั่งลูปและทำคำสั่ง ฉันจะรัน for-loop ทั้งหมดเป็นคำสั่งเดียวเช่นได้cmd1อย่างไร เป็นไปได้ไหม?
Nicholas K

19

ฉันกำลังค้นหาคำตอบสำหรับคำถามเดียวกันนี้และพบENTRYPOINT ในโซลูชันDockerfileสำหรับฉัน

Dockerfile

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

ตอนนี้สคริปต์ถูกดำเนินการเมื่อฉันเริ่มคอนเทนเนอร์และฉันได้รับ bash prompt หลังจากเรียกใช้สคริปต์แล้ว


6

คุณยังสามารถติดตั้งไดเร็กทอรีโลคัลลงในอิมเมจนักเทียบท่าของคุณและซอร์สสคริปต์ในไฟล์ .bashrcไฟล์. อย่าลืมว่าสคริปต์ต้องประกอบด้วยฟังก์ชันเว้นแต่คุณต้องการให้มันทำงานกับเชลล์ใหม่ทุกตัว (สิ่งนี้ล้าสมัยแล้วโปรดดูประกาศการอัปเดต)

ฉันใช้โซลูชันนี้เพื่ออัปเดตสคริปต์นอกอินสแตนซ์นักเทียบท่า ด้วยวิธีนี้ฉันไม่ต้องเรียกใช้รูปภาพอีกครั้งหากมีการเปลี่ยนแปลงเกิดขึ้นฉันเพิ่งเปิดเชลล์ใหม่ (กำจัดการเปิดเชลล์อีกครั้ง - ดูประกาศการอัปเดต)

นี่คือวิธีการผูกไดเร็กทอรีปัจจุบันของคุณ:

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

ตอนนี้ไดเรกทอรีปัจจุบันของคุณถูกผูกไว้กับ /scriptsอินสแตนซ์นักเทียบท่าของคุณ

(ล้าสมัย) ในการบันทึก.bashrcการเปลี่ยนแปลงของคุณให้ยอมรับภาพการทำงานของคุณด้วยคำสั่งนี้:

docker commit $container_id $my_docker_build

อัปเดต

ในการแก้ปัญหาเพื่อเปิดเชลล์ใหม่สำหรับการเปลี่ยนแปลงทุกครั้งตอนนี้ฉันทำสิ่งต่อไปนี้:

ใน dockerfile RUN echo "/scripts/bashrc" > /root/.bashrc"ตัวเองฉันจะเพิ่ม ภายในzshrcฉันส่งออกไดเร็กทอรีสคริปต์ไปยังพา ธ ขณะนี้ไดเร็กทอรีสคริปต์มีไฟล์หลายไฟล์แทนที่จะเป็นไฟล์เดียว ตอนนี้ฉันสามารถเรียกสคริปต์ทั้งหมดได้โดยตรงโดยไม่ต้องเปิดเชลล์ย่อยในทุกการเปลี่ยนแปลง

BTW คุณสามารถกำหนดไฟล์ประวัติภายนอกคอนเทนเนอร์ของคุณได้เช่นกัน ด้วยวิธีนี้คุณไม่จำเป็นต้องทำการเปลี่ยนแปลงทุบตีอีกต่อไป


สายเกินไป..! @javier ชี้แนวทางแก้ตรงแล้ว !! ฉันรู้สึกว่าหนึ่งยังดีกว่า
zappy

2
@zappy วิธีแก้ปัญหาจาก javier ไม่สามารถแก้ปัญหานี้ได้อย่างสะดวกสำหรับฉัน - แต่วิธีแก้ปัญหาของฉันฉันคิดว่ามันน่าสนใจสำหรับผู้ที่มีปัญหาคล้ายกันซึ่งพวกเขาไม่ต้องการรีสตาร์ทอิมเมจนักเทียบท่าเพื่ออัปเดต ดูฟังก์ชันที่ต้องการ ตัวอย่างเช่นหากคุณใช้อิมเมจนักเทียบท่าหลายภาพพร้อมกันเพื่อหมุนคลัสเตอร์นักพัฒนาคุณไม่ต้องการรีสตาร์ทตลอดเวลา
Devpool

3

ในกรณีที่คุณไม่ต้องการ (หรือมี) คอนเทนเนอร์ที่กำลังทำงานอยู่คุณสามารถเรียกใช้สคริปต์ของคุณได้โดยตรงด้วยrunคำสั่ง

ลบ-i -tอาร์กิวเมนต์tty ซ้ำแล้วใช้สิ่งนี้:

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

สิ่งนี้จะ (ไม่ได้ทดสอบ) ยังใช้ได้กับสคริปต์อื่น ๆ :

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


0

หากคุณต้องการเรียกใช้คำสั่งเดียวกันในหลายอินสแตนซ์คุณสามารถทำได้:

for i in c1 dm1 dm2 ds1 ds2 gtm_m gtm_sl; do docker exec -it $i /bin/bash -c "service sshd start"; done
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.