Làm cách nào để chạy lệnh trên bộ chứa Docker đã có?


492

Tôi đã tạo một container với -dnó để nó không tương tác.

docker run -d shykes/pybuilder bin/bash

Tôi thấy rằng container đã thoát:

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

Bây giờ tôi muốn chạy các lệnh thỉnh thoảng trên máy và thoát. Chỉ để nhận được phản hồi.

Tôi đã thử khởi động máy. Tôi đã thử đính kèm. Tôi nghĩ rằng tôi có thể gọi runvới một container, nhưng điều đó dường như không được phép. Sử dụng startdường như chỉ để chạy và sau đó tồn tại nhanh chóng.

Tôi muốn quay lại chế độ tương tác sau khi thoát.

Tôi đã thử:

docker attach d6c45e8cc5f0

Nhưng tôi nhận được:

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

Nhưng nếu tôi bắt đầu nó, nó vẫn thoát. Bắt 22. Tôi không thể thắng.


Làm thế nào bạn biết rằng container docker đã thoát? bạn đã chạy lệnh gì
Thufir

docker container ls -a
Brandon Manchester

Nếu bạn chỉ cần hệ thống tập tin: Làm thế nào để khởi động một container Docker bị dừng bằng một lệnh khác? (Lưu ý rằng các biến môi trường và những thứ khác trong bộ nhớ đã bị mất khi container dừng lại.)
Franklin Yu

Câu trả lời:


548

Vào tháng 10 năm 2014, nhóm Docker đã giới thiệu docker execlệnh : https://docs.docker.com/engine/reference/commandline/exec/

Vì vậy, bây giờ bạn có thể chạy bất kỳ lệnh nào trong một container đang chạy chỉ cần biết ID (hoặc tên) của nó:

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

Lưu ý rằng execlệnh chỉ hoạt động trên container đã chạy. Nếu container hiện đang dừng, trước tiên bạn cần chạy nó bằng lệnh sau:

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

Điều quan trọng nhất ở đây là -dtùy chọn, viết tắt của detached. Điều đó có nghĩa là lệnh ban đầu bạn cung cấp cho container ( /bin/bash) sẽ được chạy trong nền và container sẽ không dừng ngay lập tức .


120
Cái này không hoạt động trên một container bị dừng, chỉ có một cái đang chạy. Vì vậy, nếu bạn có một container ngay lập tức tự dừng lại, như trong câu hỏi, điều này sẽ không thực sự hoạt động để có thứ gì khác chạy bên trong nó.
xen vào

4
@interinf là đúng và CDR LDN có câu trả lời toàn diện hơn.
Tiến sĩ Jan-Philip Gehrcke

6
@ Jan-PhilipGehrcke Btw tên người dùng này đã thay đổi từ CDR LDNthành cdrevcâu trả lời bên dưới ( stackoverflow.com/a/26181666/149428 ).
Taylor Edmiston

3
Tại sao lại qua -it?
Iulian Onofrei

4
omg tại sao điều này quá phức tạp? Có vẻ như điều cơ bản nhất bạn cần làm. Chúng ta không được sử dụng nó theo cách họ dự định.
sudo

287

Container của bạn sẽ thoát khi lệnh bạn đưa ra sẽ kết thúc. Sử dụng các tùy chọn sau để giữ cho nó sống:

  • -i Giữ STDIN mở ngay cả khi không được đính kèm.
  • -t Phân bổ một giả TTY.

Vì vậy, runlệnh mới của bạn là:

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

Nếu bạn muốn đính kèm vào một container đã chạy:

docker exec -it CONTAINER_ID /bin/bash

Trong các ví dụ /bin/bashnày được sử dụng như lệnh.


2
Đã thử docker exec -it CONTAINER_ID /bin/bash -c "export VAR=1 && echo $VAR"và in biến rỗng (dự kiến 1). Tôi đang thiếu gì?
màu vàng01

sau khi chạy 'docker exec -it CONTAINER_ID / bin / bash', nó đi đến bash một cách chính xác nhưng không thể tương tác với nó.
Mây xanh

1
Nhưng nếu tôi đang sử dụng docker-compose -itthì không có sẵn.
adnanmuttaleb

120

Vì vậy, tôi nghĩ rằng câu trả lời đơn giản hơn nhiều câu trả lời sai ở trên.

Để bắt đầu một container hiện có bị dừng

docker start <container-name/ID>

Để dừng một container đang chạy

docker stop <container-name/ID>

Sau đó để đăng nhập vào vỏ tương tác của một container

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

Để bắt đầu một container hiện có và đính kèm vào nó trong một lệnh

docker start -ai <container-name/ID>

Coi chừng, điều này sẽ dừng container khi thoát. Nhưng nói chung, bạn cần khởi động container, đính kèm và dừng nó sau khi bạn hoàn thành.


docker đính kèm <container-name / ID> đang chạy
KunMing Xie

9
@Peter T. Thật ra, tôi thấy câu trả lời của bạn ngắn gọn hơn rất nhiều so với những gì người khác đã cung cấp. Tôi không hiểu tại sao mọi người thích làm phức tạp một câu hỏi rất đơn giản. Cảm ơn Peter câu trả lời này.
Helen Neely

1
điều này đòi hỏi rằng khi bạn đã tạo docker, bạn đã làm nó với -it stackoverflow.com/questions/45216612/ nếu không nó sẽ không bắt đầu .. vì vậy, bạn sẽ bắt đầu docker <container-id> và sau đó docker ps -l và bạn sẽ thấy nó không hoạt động sau khi bắt đầu. và sau đó đính kèm sẽ thất bại. Vì vậy, phải tạo ra với -it quá.
barlop

1
@Peter Câu trả lời phù hợp nhất
Nilanjan Sarkar

1
Đây là câu trả lời chính xác nhất!
nagendra547

91

Để mở rộng câu trả lời của katrmr, nếu container bị dừng và không thể khởi động do lỗi, bạn sẽ cần phải commit nó vào hình ảnh. Sau đó, bạn có thể khởi chạy bash trong hình ảnh mới:

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

1
FYI, tôi làm điều này rất nhiều đến nỗi tôi đã đưa ra một lệnh được gọi là dshelltự động thực hiện trong nhiều tình huống - github.com/avirshup/docker-cli-sugar
Aaron V

41

Một số câu trả lời ở đây là sai lệch vì chúng liên quan đến các container đang chạy, không dừng lại.

Sven Dowideit đã giải thích trên diễn đàn Docker rằng các container bị ràng buộc với quy trình của họ (và Docker không thể thay đổi quy trình của một container bị dừng, dường như ít nhất là do cấu trúc bên trong của nó: https://github.com/docker/docker/issues / 1437 ). Vì vậy, về cơ bản, tùy chọn duy nhất là commitchứa container tới một hình ảnh và runnó với một lệnh khác.

Xem https://forums.docker.com/t/run-command-in-stopped-container 4323
(Tôi tin rằng phương pháp " ENTRYPOINTvới các đối số" cũng sẽ không hoạt động, vì bạn vẫn không thể thay đổi đối số cho một container bị dừng.)


2
Lưu ý: chạy bin/bash-itkhông thay đổi bất cứ điều gì trong container, vì vậy cam kết không thực sự cần thiết và CDR LDN đưa ra câu trả lời đúng cho tình huống cụ thể của OP. Tuy nhiên, commitlà câu trả lời cho vấn đề kỹ thuật về cách thay đổi quy trình container.
katrmr

Nhận xét của candlerb tại run-command-in-stop-container gợi ý sử dụng hình ảnh vứt đi với âm lượng từ thùng chứa không hoạt động đối với tôi: docker run --rm --volume-from CONTAINER -i busybox tar cO / var / TRỰC TIẾP | gzip -c> ~ / mydir_backup.tgz
lươn ghEEz

Đây là câu trả lời thực tế cho câu hỏi. Các container bị ràng buộc với quy trình của chúng, vì vậy lệnh không thể thay đổi.
cjsimon

21

Tôi đã phải sử dụng bash -c để chạy lệnh của mình: docker exec -it CONTAINER_ID bash -c "mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql mysql"


1
-c làm việc cho tôi. tự hỏi tại sao bash một mình sẽ không hoạt động (không nhận được lời nhắc)
André Werlang

18

Tạo một thùng chứa và gửi lệnh cho nó, từng cái một:

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

Đây là câu trả lời tốt cho câu hỏi. Nếu bạn muốn khởi động container sau khi tạo và có thể "docker exec" các lệnh vào nó, bạn phải tạo nó bằng các cờ "-it" trong lệnh tạo docker.
joanlofe

8

Đây là câu trả lời kết hợp tôi tạo ra bằng câu trả lời CDR LDN ở trên và câu trả lời tôi tìm thấy ở đây .

Ví dụ sau đây khởi động một thùng chứa Arch Linux từ một hình ảnh, sau đó cài đặt gitvào thùng chứa đó bằng pacmancông cụ:

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"

Đó là tất cả.


5

Nếu bạn đang cố chạy shell script, bạn cần chạy nó dưới dạng bash.

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

4

Đặt lệnh cho stdin

Phải loại bỏ -tđể nó hoạt động:

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

Điều này có thể thuận tiện hơn khi sử dụng tùy chọn CLI đôi khi.

Đã thử nghiệm với:

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

sau đó trên một vỏ khác:

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

Sau đó, trên vỏ đầu tiên:

ls -l myfile

Đã thử nghiệm trên Docker 1.13.1, máy chủ Ubuntu 16.04.


3

Giả sử hình ảnh đang sử dụng điểm nhập mặc định /bin/sh -c, chạy /bin/bashsẽ thoát ngay lập tức trong chế độ daemon ( -d). Nếu bạn muốn container này chạy shell tương tác, hãy sử dụng -itthay vì -d. Nếu bạn muốn thực thi các lệnh tùy ý trong một thùng chứa thường thực hiện một quy trình khác, bạn có thể muốn thử nsenterhoặc nsinit. Hãy xem https://blog.codecentric.de/en/2014/07/enter-docker-container/ để biết chi tiết.


3

Thật không may, không thể ghi đè ENTRYPOINTbằng các đối số docker run --entrypointđể đạt được mục tiêu này.

Lưu ý: bạn có thể ghi đè cài đặt ENTRYPOINT bằng cách sử dụng --entrypoint, nhưng điều này chỉ có thể đặt nhị phân thành exec (không sử dụng sh -c).


3

Tôi muốn lưu ý rằng câu trả lời hàng đầu là một chút sai lệch.

Vấn đề với việc thực thi docker runlà một container mới được tạo ra mỗi lần. Tuy nhiên, có những trường hợp chúng tôi muốn xem lại các container cũ hoặc không chiếm dung lượng với các container mới.

(Cho clever_bardeenlà tên của container được tạo ...)

Trong trường hợp của OP, đảm bảo hình ảnh docker được chạy đầu tiên bằng cách thực hiện lệnh sau:

docker start clever_bardeen

Sau đó, thực hiện bộ chứa docker bằng lệnh sau:

docker exec -it clever_bardeen /bin/bash

2

Đối với máy Mac:

$ docker exec -it <container-name> sh

nếu bạn muốn kết nối với tư cách người dùng root:

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

1

Câu trả lời đơn giản: bắt đầu và đính kèm cùng một lúc. Trong trường hợp này, bạn đang làm chính xác những gì bạn yêu cầu.

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

đảm bảo thay đổi <CONTAINER_ID/CONTAINER_NAME>


1
# docker exec -d container_id command 

Ví dụ:

# docker exec -d xcdefrdtt service jira stop 

1

Tôi đang chạy windows container và tôi cần nhìn vào bên trong container docker để tìm các tập tin và thư mục được tạo và sao chép.

Để làm điều đó, tôi đã sử dụng lệnh docker entrypoint để nhận dấu nhắc lệnh chạy bên trong container hoặc đính kèm vào container.

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

Điều đó giúp tôi cả với dấu nhắc lệnh gắn vào container và để giữ cho container sống. :)


0

Một cách nhanh chóng để tiếp tục và truy cập vào container đã thoát gần đây nhất:

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

0

Tôi thường sử dụng cái này:

    docker exec -it my-container-name bash

để liên tục tương tác với một container đang chạy.

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.