ฉันจะรันคำสั่งบนคอนเทนเนอร์ Docker ที่มีอยู่แล้วได้อย่างไร


492

ฉันสร้างคอนเทนเนอร์ด้วย-dดังนั้นจึงไม่สามารถโต้ตอบได้

docker run -d shykes/pybuilder bin/bash

ฉันเห็นว่าคอนเทนเนอร์ได้ออก:

CONTAINER ID        IMAGE                     COMMAND             CREATED             STATUS                      PORTS               NAMES
d6c45e8cc5f0        shykes/pybuilder:latest   "bin/bash"          41 minutes ago      Exited (0) 2 seconds ago                        clever_bardeen

ตอนนี้ฉันต้องการเรียกใช้คำสั่งเป็นครั้งคราวบนเครื่องและออก เพียงเพื่อให้ได้คำตอบ

ฉันพยายามสตาร์ทเครื่อง ฉันพยายามแนบ ฉันคิดว่าฉันสามารถโทรหาrunตู้คอนเทนเนอร์ได้ แต่ดูเหมือนจะไม่ได้รับอนุญาต ใช้startดูเหมือนว่าจะทำงานแล้วมีอยู่อย่างรวดเร็ว

ฉันต้องการกลับสู่โหมดโต้ตอบหลังจากออก

ฉันเหนื่อย:

docker attach d6c45e8cc5f0

แต่ฉันได้รับ:

2014/10/01 22:33:34 You cannot attach to a stopped container, start it first

แต่ถ้าฉันเริ่มมันก็ออกไปแล้ว จับ 22. ฉันไม่สามารถชนะ


คุณรู้ได้อย่างไรว่าคอนเทนเนอร์นักเทียบท่าออกจากแล้ว? คุณสั่งงานอะไร
Thufir

docker container ls -a
Brandon Manchester

หากคุณเพียงต้องการระบบไฟล์: จะเริ่มต้น Docker container ที่หยุดทำงานด้วยคำสั่งอื่นได้อย่างไร (โปรดทราบว่าตัวแปรสภาพแวดล้อมและสิ่งอื่น ๆ ในหน่วยความจำจะหายไปแล้วเมื่อคอนเทนเนอร์หยุดทำงาน)
Franklin Yu

คำตอบ:


548

ในเดือนตุลาคม 2014 ทีมนักเทียบท่าได้แนะนำdocker execคำสั่ง : https://docs.docker.com/engine/reference/commandline/exec/

ดังนั้นตอนนี้คุณสามารถเรียกใช้คำสั่งใด ๆ ในภาชนะที่ทำงานอยู่เพียงแค่รู้ ID (หรือชื่อ):

docker exec -it <container_id_or_name> echo "Hello from container!"

โปรดทราบว่าexecคำสั่งใช้งานได้กับคอนเทนเนอร์ที่รันอยู่แล้วเท่านั้น หากคอนเทนเนอร์หยุดอยู่ในปัจจุบันคุณต้องรันด้วยคำสั่งต่อไปนี้ก่อน:

docker run -it -d shykes/pybuilder /bin/bash

สิ่งที่สำคัญที่สุดที่นี่เป็นตัวเลือกซึ่งย่อมาจาก-d detachedก็หมายความว่าคำสั่งที่คุณให้ไว้ในขั้นต้นจะคอนเทนเนอร์ ( /bin/bash) จะทำงานในพื้นหลังและภาชนะจะไม่หยุดทันที


120
สิ่งนี้ใช้ไม่ได้กับคอนเทนเนอร์ที่หยุดแล้วเพียงอันเดียวที่ทำงานอยู่ ดังนั้นถ้าคุณมีตู้สินค้าที่หยุดตัวเองทันทีเช่นเดียวกับคำถามสิ่งนี้จะไม่ทำงานเพื่อให้ได้สิ่งอื่นที่อยู่ภายใน
interfect

4
@interfect ถูกต้องและ CDR LDN มีคำตอบที่ครอบคลุมมากขึ้น
ดร. Jan-Philip Gehrcke

6
@ ม.ค. PhilipGehrcke Btw ชื่อผู้ใช้คนนี้ได้เปลี่ยนจากCDR LDNการcdrevสำหรับคำตอบด้านล่าง ( stackoverflow.com/a/26181666/149428 )
เทย์เลอร์ Edmiston

3
ทำไมผ่าน-it?
Iulian Onofrei

4
ทำไมมันซับซ้อนกันจัง ดูเหมือนว่าสิ่งพื้นฐานที่สุดที่คุณต้องทำ เราจะต้องไม่ใช้อย่างที่ตั้งใจ
sudo

287

คอนเทนเนอร์ของคุณจะออกจากคำสั่งที่คุณให้ไว้จะสิ้นสุด ใช้ตัวเลือกต่อไปนี้เพื่อให้มันสด:

  • -i เปิด STDIN แม้ว่าจะไม่ได้เชื่อมต่อก็ตาม
  • -t จัดสรรหลอก -YTY

ดังนั้นrunคำสั่งใหม่ของคุณคือ:

docker run -it -d shykes/pybuilder bin/bash

หากคุณต้องการแนบกับคอนเทนเนอร์ที่ใช้งานอยู่:

docker exec -it CONTAINER_ID /bin/bash

ในตัวอย่างเหล่านี้/bin/bashใช้เป็นคำสั่ง


2
พยายามdocker exec -it CONTAINER_ID /bin/bash -c "export VAR=1 && echo $VAR"และพิมพ์ตัวแปรเปล่า (คาดว่า1) ฉันพลาดอะไรไป
yellow01

หลังจากใช้งาน 'นักเทียบท่า exec -it CONTAINER_ID / bin / bash' จะไปที่การทุบตีอย่างถูกต้อง แต่ไม่สามารถโต้ตอบกับมันได้
Blue Clouds

1
แต่ถ้าฉันใช้นักเทียบท่าแต่ง-itไม่สามารถใช้ได้
adnanmuttaleb

120

ดังนั้นฉันคิดว่าคำตอบนั้นง่ายกว่าคำตอบที่ทำให้เข้าใจผิดหลายข้อด้านบน

เพื่อเริ่มภาชนะที่มีอยู่ซึ่งหยุด

docker start <container-name/ID>

เพื่อหยุดภาชนะที่ใช้งาน

docker stop <container-name/ID>

จากนั้นให้ล็อกอินเข้าสู่เชลล์เชิงโต้ตอบของคอนเทนเนอร์

docker exec -it <container-name/ID> bash

เพื่อเริ่มต้นภาชนะที่มีอยู่และแนบไปกับมันในคำสั่งเดียว

docker start -ai <container-name/ID>

ระวังนี่จะหยุดคอนเทนเนอร์เมื่อออก แต่โดยทั่วไปคุณต้องเริ่มต้นคอนเทนเนอร์แนบและหยุดมันหลังจากที่คุณทำเสร็จแล้ว


นักเทียบท่าแนบ <container-name / ID> ซึ่งทำงานอยู่
KunMing Xie

9
@Peter T. จริงๆแล้วฉันพบคำตอบของคุณสั้นกระชับกว่าที่คนอื่น ๆ ให้ไว้ ฉันไม่เข้าใจว่าทำไมผู้คนถึงชอบคำถามที่ซับซ้อนมาก ๆ ขอบคุณ Peter คำตอบนี้
เฮเลนนีลี

1
สิ่งนี้ต้องการว่าเมื่อคุณสร้างนักเทียบท่าคุณทำมันด้วย -it stackoverflow.com/questions/45216612/ …ไม่ อย่างนั้นมันจะไม่เริ่มเลย .. ดังนั้นคุณจะเริ่มนักเทียบท่า <container-id> แล้วเทียบท่า ps -l และคุณจะเห็นว่ามันไม่ได้เกิดขึ้นหลังจากการเริ่มต้น แล้วไฟล์แนบจะล้มเหลว ดังนั้นต้องสร้างด้วย -it ด้วย
barlop

1
@Peter คำตอบที่เกี่ยวข้องมากที่สุด
Nilanjan Sarkar

1
นี่คือคำตอบที่ถูกต้องที่สุด!
nagendra547

91

หากต้องการขยายคำตอบของ katrmr หากคอนเทนเนอร์หยุดและไม่สามารถเริ่มได้เนื่องจากข้อผิดพลาดคุณจะต้องcommitใช้รูปภาพ จากนั้นคุณสามารถเปิดใช้ bash ในภาพใหม่:

docker commit [CONTAINER_ID] temporary_image
docker run --entrypoint=bash -it temporary_image

1
FYI ฉันทำสิ่งนี้มากจนฉันได้รวบรวมคำสั่งที่เรียกว่าdshellทำโดยอัตโนมัติในสถานการณ์ที่หลากหลาย - github.com/avirshup/docker-cli-sugar
Aaron V

41

บางคำตอบที่นี่ทำให้เข้าใจผิดเพราะพวกเขาเกี่ยวข้องกับภาชนะบรรจุที่ทำงานอยู่ไม่หยุด

Sven Dowideit อธิบายไว้ในฟอรัม Docker ว่าคอนเทนเนอร์ถูกผูกไว้กับกระบวนการของพวกเขา (และนักเทียบท่าไม่สามารถเปลี่ยนกระบวนการของคอนเทนเนอร์ที่หยุดทำงานได้ดูเหมือนอย่างน้อยก็เนื่องจากโครงสร้างภายในของมัน: https://github.com/docker/docker/issues / 1437 ) ดังนั้นโดยทั่วไปตัวเลือกเดียวคือcommitคอนเทนเนอร์ไปยังรูปภาพและrunด้วยคำสั่งที่แตกต่างกัน

ดูhttps://forums.docker.com/t/run-command-in-stopped-container/343
(ฉันเชื่อว่าวิธี " ENTRYPOINTด้วยการขัดแย้ง" จะไม่ทำงานเช่นกันเนื่องจากคุณยังคงไม่สามารถเปลี่ยน ขัดแย้งกับคอนเทนเนอร์ที่หยุดทำงาน)


2
ข้อสังเกต: การทำงานbin/bashโดย-itไม่เปลี่ยนอะไรในคอนเทนเนอร์ดังนั้นการยืนยันว่าไม่จำเป็นจริงๆและ CDR LDN ให้คำตอบที่ถูกต้องสำหรับสถานการณ์เฉพาะของ OP ยังคงcommitเป็นคำตอบสำหรับปัญหาทางเทคนิคของวิธีการเปลี่ยนกระบวนการภาชนะ
katrmr

ความคิดเห็นโดย candlerb ที่ run-command-in-stop-container แนะนำให้ใช้อิมเมจแบบ throwaway กับไดรฟ์ข้อมูลจากคอนเทนเนอร์ที่ไม่ทำงานใช้งานได้สำหรับฉัน: docker run --rm --volumes- จาก CONTAINER -i busybox tar cO / var / DIR | gzip -c> ~ / mydir_backup.tgz
eel ghEEz

นี่คือคำตอบที่แท้จริงของคำถามที่ถาม คอนเทนเนอร์ถูกผูกไว้กับกระบวนการดังนั้นจึงไม่สามารถเปลี่ยนคำสั่งได้
cjsimon

21

ฉันต้องใช้ bash -c เพื่อเรียกใช้คำสั่งของฉัน: docker exec -it CONTAINER_ID bash -c "mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql mysql"


1
-c ทำงานให้ฉัน สงสัยว่าทำไมการทุบตีเพียงอย่างเดียวจึงไม่ทำงาน (ไม่ได้รับพรอมต์)
André Werlang

18

สร้างคอนเทนเนอร์และส่งคำสั่งไปทีละตัว:

docker create --name=my_new_container -it ubuntu
docker start my_new_container
// ps -a says 'Up X seconds'
docker exec my_new_container /path/to/my/command
// ps -a still says 'Up X+Y seconds'
docker exec my_new_container /path/to/another/command

นี่คือคำตอบที่ดีสำหรับคำถาม หากคุณต้องการเริ่มต้นคอนเทนเนอร์หลังจากการสร้างและสามารถสั่งคำสั่ง "docker exec" ได้คุณต้องสร้างมันด้วยแฟล็ก "-it" ในคำสั่ง docker create
joanlofe

8

นี่คือคำตอบร่วมกันฉันทำขึ้นโดยใช้คำตอบที่ CDR LDN ข้างต้นและคำตอบที่ฉันพบที่นี่

ตัวอย่างต่อไปนี้เริ่มต้นคอนเทนเนอร์ Arch Linux จากอิมเมจแล้วติดตั้งgitบนคอนเทนเนอร์นั้นโดยใช้pacmanเครื่องมือ:

sudo docker run -it -d archlinux /bin/bash
sudo docker ps -l
sudo docker exec -it [container_ID] script /dev/null -c "pacman -S git --noconfirm"

นั้นคือทั้งหมด.


5

หากคุณพยายามเรียกใช้เชลล์สคริปต์คุณต้องใช้มันเป็นทุบตี

docker exec -it containerid bash -c /path/to/your/script.sh

4

ไพพ์คำสั่งไปยัง stdin

จะต้องลบ-tมันเพื่อให้มันทำงาน:

echo 'touch myfile' | sudo docker exec -i CONTAINER_NAME bash

ซึ่งจะสะดวกกว่าที่ใช้ตัวเลือก CLI ในบางครั้ง

ทดสอบกับ:

sudo docker run --name ub16 -it ubuntu:16.04 bash

จากนั้นบนเปลือกอื่น:

echo 'touch myfile' | sudo docker exec -i ub16 bash

จากนั้นบนเปลือกแรก:

ls -l myfile

ทดสอบบน Docker 1.13.1 โฮสต์ Ubuntu 16.04


3

สมมติว่าภาพกำลังใช้จุดเข้าใช้งานเริ่มต้นการ/bin/sh -cทำงาน/bin/bashจะออกทันทีในโหมด daemon ( -d) หากคุณต้องการภาชนะนี้เพื่อเรียกใช้เปลือกโต้ตอบใช้แทน-it -dหากคุณต้องการที่จะรันคำสั่งโดยพลการในภาชนะที่มักจะดำเนินการขั้นตอนอื่นคุณอาจต้องการที่จะลองหรือnsenter nsinitดูhttps://blog.codecentric.de/en/2014/07/enter-docker-container/สำหรับรายละเอียด


3

น่าเสียดายที่มันเป็นไปไม่ได้ที่จะแทนที่ENTRYPOINTด้วยการโต้แย้งdocker run --entrypointเพื่อให้บรรลุเป้าหมายนี้

หมายเหตุ: คุณสามารถแทนที่การตั้งค่า ENTRYPOINT โดยใช้ - ผู้ชี้จุด แต่สามารถตั้งค่าไบนารีเป็น exec เท่านั้น (จะไม่มีการใช้ sh -c)


3

ฉันต้องการที่จะทราบว่าคำตอบที่ดีที่สุดคือการทำให้เข้าใจผิดเล็กน้อย

ปัญหาเกี่ยวกับการดำเนินการdocker runคือสร้างคอนเทนเนอร์ใหม่ทุกครั้ง อย่างไรก็ตามมีหลายกรณีที่เราต้องการกลับไปใช้ภาชนะบรรจุเก่าหรือไม่ใช้พื้นที่สำหรับบรรจุภัณฑ์ใหม่

(รับclever_bardeenเป็นชื่อของภาชนะที่สร้างขึ้น ... )

ในกรณีของ OP ให้ตรวจสอบให้แน่ใจว่าอิมเมจของ Docker นั้นรันครั้งแรกโดยการรันคำสั่งต่อไปนี้:

docker start clever_bardeen

จากนั้นเรียกใช้คอนเทนเนอร์นักเทียบท่าโดยใช้คำสั่งต่อไปนี้:

docker exec -it clever_bardeen /bin/bash

2

สำหรับ Mac:

$ docker exec -it <container-name> sh

หากคุณต้องการเชื่อมต่อในฐานะผู้ใช้รูท:

$ docker exec -u 0 -it <container-name> sh

1

คำตอบง่ายๆ: เริ่มและแนบในเวลาเดียวกัน ในกรณีนี้คุณกำลังทำสิ่งที่คุณต้องการ

docker start <CONTAINER_ID/CONTAINER_NAME> && docker attach <CONTAINER_ID/CONTAINER_NAME> 

ให้แน่ใจว่าจะเปลี่ยน <CONTAINER_ID/CONTAINER_NAME>



1

ฉันกำลังเรียกใช้ windows container และฉันต้องการดูใน docker container เพื่อหาไฟล์และโฟลเดอร์ที่สร้างและคัดลอก

เพื่อที่จะทำฉันใช้ต่อไปนี้คำสั่งนักเทียบท่าเพื่อรับพรอมต์คำสั่งที่ทำงานอยู่ภายในภาชนะหรือแนบกับภาชนะ

ENTRYPOINT ["C:\\Windows\\System32\\cmd.exe", "-D", "FOREGROUND"]

ที่ช่วยให้ฉันทั้งสองพร้อมรับคำสั่งแนบกับภาชนะและเพื่อให้ภาชนะที่มีชีวิต :)


0

วิธีที่รวดเร็วในการดำเนินการต่อและเข้าถึงคอนเทนเนอร์ที่ออกล่าสุด:

docker start -a -i `docker ps -q -l`

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.