Docker container sẽ tự động dừng lại sau khi Docker chạy -d


333

Theo hướng dẫn tôi đọc cho đến nay, sử dụng " docker run -d" sẽ bắt đầu một container từ hình ảnh và container sẽ chạy ở chế độ nền. Đây là giao diện của nó, chúng ta có thể thấy chúng ta đã có id container.

root@docker:/home/root# docker run -d centos
605e3928cdddb844526bab691af51d0c9262e0a1fc3d41de3f59be1a58e1bd1d

Nhưng nếu tôi chạy " docker ps", không có gì được trả lại.

Vì vậy, tôi đã thử " docker ps -a", tôi có thể thấy container đã thoát:

root@docker:/home/root# docker ps -a
CONTAINER ID        IMAGE                 COMMAND             CREATED             STATUS                         PORTS               NAMES
605e3928cddd        centos:latest         "/bin/bash"         31 minutes ago      Exited (0) 31 minutes ago                          kickass_swartz

Bất cứ điều gì tôi đã làm sai? Làm thế nào tôi có thể khắc phục sự cố này?


1
"Docker run hello-world" <== hoạt động hoàn hảo, nhưng nếu tôi chạy "docker run -d hello-world", tôi vẫn không thể có được một container đang chạy.
J John

5
Tôi đã có một vấn đề tương tự nhưng tôi đã giải quyết nó bằng cách sử dụng docker run -it -d <image> /bin/bashcái này để khởi động bash shell một cách tương tác và không đóng container vì quá trình shell đang hoạt động.
Rtsne42

Câu trả lời:


494

Các dockerfile centos có một lệnh mặc định bash.

Điều đó có nghĩa là, khi chạy trong nền ( -d), shell thoát ngay lập tức.

Cập nhật 2017

Các phiên bản gần đây của Docker ủy quyền để chạy một container ở cả chế độ tách ra trong chế độ foreground ( -t, -ihay -it)

Trong trường hợp đó, bạn không cần bất kỳ lệnh bổ sung nào và điều này là đủ:

docker run -t -d centos

Bash sẽ chờ trong nền.
Điều đó ban đầu được báo cáo trong câu trả lời của kalyani-chaudhari và chi tiết trong câu trả lời của jersey jersey .

vonc@voncvb:~$ d ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
4a50fd9e9189        centos              "/bin/bash"         8 seconds ago       Up 2 seconds                            wonderful_wright

Lưu ý rằng đối với alpine , Marinos Một báo cáo trong các bình luận :

docker run -t -d alpine/gitkhông giữ quá trình lên.
Phải làm:docker run --entrypoint "/bin/sh" -it alpine/git


Câu trả lời gốc (2015)

Như đã đề cập trong bài viết này :

Thay vì chạy với docker run -i -t image your-command, sử dụng -dđược khuyến nghị vì bạn có thể chạy container của mình chỉ bằng một lệnh và bạn không cần tách thiết bị đầu cuối của container bằng cách nhấn Ctrl+ P+ Q.

Tuy nhiên, có một vấn đề với -dtùy chọn. Container của bạn ngay lập tức dừng lại trừ khi các lệnh không chạy trên nền trước .
Docker yêu cầu lệnh của bạn tiếp tục chạy ở nền trước. Mặt khác, nó nghĩ rằng các ứng dụng của bạn dừng và tắt container.

Vấn đề là một số ứng dụng không chạy ở nền trước. Làm thế nào chúng ta có thể làm cho nó dễ dàng hơn?

Trong tình huống này, bạn có thể thêm tail -f /dev/nullvào lệnh của bạn.
Bằng cách này, ngay cả khi lệnh chính của bạn chạy trong nền, thùng chứa của bạn không dừng lại vì đuôi vẫn tiếp tục chạy ở phía trước.

Vì vậy, điều này sẽ làm việc:

docker run -d centos tail -f /dev/null

A docker pssẽ hiển thị các container centos vẫn đang chạy.

Từ đó, bạn có thể gắn vào nó hoặc tách ra khỏi nó (hoặc docker execmột số lệnh).


Xin lỗi, một câu hỏi nữa, tôi có một kịch bản cần chạy khi khởi động, có vẻ như /etc/rc.d/rc.local không còn hoạt động nữa (suy nghĩ của tôi vẫn xử lý docker như OS), tôi cho rằng tệp docker là tùy chọn tốt hơn trong việc này trường hợp nào?
J John

5
@GuruprasadGV Điều đó được mong đợi. Thay vì sử dụng docker đính kèm, sử dụng docker exec -it <yourContainer> bash.
VonC

3
Điều này cũng hoạt động nếu bạn thêm lệnh tail ở cuối tệp entrypoint.
yara

2
Tôi đã sử dụng sshd như lệnh cuối cùng (chạy dài) của tôi. Sau đó, bạn có thể ssh trên bộ chứa của mình như trên VM (một khi bạn đặt .ssh / ủy quyền, v.v.) ... Bạn cũng có thể tiếp tục định cấu hình bộ chứa bằng cách sử dụng ansible.
pate

1
Tôi đã kết thúc việc này để thực thi lệnh của mình cộng với sửa lỗi cũ hơn được liệt kê ở trên: docker chạy image_name / bin / bash -c "my / lệnh && tail -f / dev / null"
Geordie

58

Theo câu trả lời này , việc thêm -tcờ sẽ ngăn container thoát ra khi chạy trong nền. Sau đó, bạn có thể sử dụng docker exec -i -t <image> /bin/bashđể vào một dấu nhắc shell.

docker run -t -d <image> <command>

Có vẻ như tùy chọn -t không được ghi chép lại rất tốt , mặc dù trợ giúp nói rằng nó "phân bổ giả TTY."


10
Đẹp. Có vẻ ít hack hơn so với việc tail -f /dev/null
bổ sung

Cảm ơn! Nếu có cơ hội, điều này sẽ giúp được ai đó, điều này không hành xử tốt trong Emacs Eshell.
Peter Becich

2
docker run -t -d --name mysql -p 3306:3306 mysql- không hoạt động đối với tôi (ubfox 14.04.5): STATUS = Đã thoát (1) 4 giây trước
Putnik

Tôi thấy rằng bạn không cần <lệnh> ở đây, trừ khi bạn muốn. Thật kỳ lạ, nó cũng hoạt động để thay thế -t bằng -i (tương tác). Tài liệu có đề cập đến việc sử dụng -t và -i kết hợp sẽ hoạt động giống như một cái vỏ.
áo đậu

43

Lý lịch

Một Docker container chạy một tiến trình ("lệnh" hoặc "entrypoint") để giữ cho nó tồn tại. Container sẽ tiếp tục chạy miễn là lệnh tiếp tục chạy.

Trong trường hợp của bạn, lệnh ( /bin/bashtheo mặc định, bật centos:latest) sẽ thoát ngay lập tức (như bash khi nó không được kết nối với thiết bị đầu cuối và không có gì để chạy).

Thông thường, khi bạn chạy một container trong chế độ daemon (với -d), container đang chạy một số loại quy trình daemon (như httpd). Trong trường hợp này, miễn là trình nền httpd đang chạy, container sẽ vẫn còn sống.

Những gì bạn dường như đang cố gắng làm là giữ cho container tồn tại mà không có quá trình daemon chạy bên trong container. Điều này hơi lạ (vì container không làm gì hữu ích cho đến khi bạn tương tác với nó, có lẽ với docker exec), nhưng có một số trường hợp có thể có ý nghĩa khi làm điều gì đó như thế này.

(Ý của bạn là có được một dấu nhắc bash bên trong container không? Thật dễ dàng! docker run -it centos:latest)

Giải pháp

Một cách đơn giản để giữ cho một container tồn tại trong chế độ daemon vô thời hạn là chạy sleep infinitynhư lệnh của container. Điều này không dựa vào việc làm những việc lạ như phân bổ TTY trong chế độ daemon. Mặc dù nó phụ thuộc vào việc làm những việc lạ như sử dụng sleeplàm lệnh chính của bạn.

$ docker run -d centos:latest sleep infinity
$ docker ps
CONTAINER ID  IMAGE         COMMAND          CREATED       STATUS       PORTS NAMES
d651c7a9e0ad  centos:latest "sleep infinity" 2 seconds ago Up 2 seconds       nervous_visvesvaraya

Giải pháp thay thế

Như được chỉ định bởi cjsimon, -ttùy chọn phân bổ một "giả-tty". Thủ thuật này khiến bạn tiếp tục chạy vô thời hạn vì nghĩ rằng nó được kết nối với TTY tương tác (mặc dù bạn không có cách nào để tương tác với TTY cụ thể đó nếu bạn không vượt qua -i). Dù sao, điều này cũng nên thực hiện các mẹo:

$ docker run -t -d centos:latest

Không chắc chắn 100% liệu -tsẽ tạo ra các tương tác kỳ lạ khác; có thể để lại một bình luận dưới đây nếu nó làm.


Lưu ý rằng điều này không hoạt động trên núi cao vì giấc ngủ của BusyBox không chấp nhận infinity.
John Kugelman

điều này đã giúp tôi khắc phục sự cố hình ảnh amazon-linux, cảm ơn bạn
có ảnh hưởng

18

Xin chào vấn đề này là do docker container thoát nếu không có ứng dụng đang chạy trong container.

-d 

tùy chọn chỉ là để chạy một container trong chế độ deamon.

Vì vậy, mẹo để làm cho container của bạn chạy liên tục là trỏ đến một tệp shell trong docker sẽ giữ cho ứng dụng của bạn chạy. Bạn có thể thử với tệp start.sh

Eg: docker run -d centos sh /yourlocation/start.sh

Start.sh này nên trỏ đến một ứng dụng không bao giờ kết thúc.

Trong trường hợp nếu bạn không muốn bất kỳ ứng dụng nào chạy, bạn có thể cài đặt monitđể giữ cho docker container của bạn chạy. Xin vui lòng cho chúng tôi biết nếu hai trường hợp này làm việc cho bạn để giữ cho container của bạn chạy.

Tất cả tốt nhất


12

Bạn có thể thực hiện những gì bạn muốn với một trong hai:

docker run -t -d <image-name>

hoặc là

docker run -i -d <image-name>

hoặc là

docker run -it -d <image-name>

Tham số lệnh như được đề xuất bởi các câu trả lời khác (ví dụ đuôi -f / dev / null) là hoàn toàn tùy chọn và KHÔNG bắt buộc để bộ chứa của bạn tiếp tục chạy trong nền.

Cũng lưu ý tài liệu Docker cho thấy rằng việc kết hợp các tùy chọn -i và -t sẽ khiến nó hoạt động giống như một cái vỏ.

Xem:

https://docs.docker.com/engine/reference/run/#Forground


9

Tôi có đoạn mã này chạy từ ENTRYPOINTtrong tệp docker của tôi:

while true
do
    echo "Press [CTRL+C] to stop.."
    sleep 1
done

Chạy hình ảnh docker được xây dựng như:

docker run -td <image name>

Đăng nhập vào vỏ container:

docker exec -it <container id> /bin/bash

Đây có phải là giải pháp mà bạn đã tạo vòng lặp vô hạn cho việc này? : D
Muhammad SaLman

8

thực hiện lệnh như sau:

docker run -t -d <image-name>

Nếu bạn muốn chỉ định cổng thì ra lệnh như dưới đây:

docker run -t -d -p <port-no> <image-name>

xác minh container đang chạy bằng lệnh sau:

docker ps

Tôi thực sự thích câu trả lời này là tốt nhất, bởi vì câu trả lời phổ biến nhất cho thấy rằng bạn cần một lệnh (tức là đuôi -f / dev / null). Lệnh này là hoàn toàn tùy chọn. Chìa khóa ở đây là sử dụng -t. Tôi cũng tìm thấy -tôi làm việc thay cho -t hoặc bạn cũng có thể sử dụng cả hai -it kết hợp (vì tài liệu cho thấy nó sẽ chạy như một cái vỏ).
áo đậu

Có bất kỳ lợi thế của việc sử dụng -t -dvs -i -d? Cả hai sẽ giữ cho container chạy.
wvducky

5

Docker yêu cầu lệnh của bạn tiếp tục chạy ở nền trước. Mặt khác, nó nghĩ rằng các ứng dụng của bạn dừng và tắt container.

Vì vậy, nếu tập lệnh nhập docker của bạn là một quá trình nền như sau:

/usr/local/bin/confd -interval=30 -backend etcd -node $CONFIG_CENTER &

'&' Làm cho container dừng và thoát nếu không có quá trình tiền cảnh nào khác được kích hoạt sau này. Vì vậy, giải pháp chỉ là loại bỏ '&' hoặc có một CMD nền trước khác chạy sau nó , chẳng hạn như

tail -f server.log

Có thể muốn touchtệp đó trước, trong trường hợp bạn không thể tìm thấy tệp nhật ký.
Samuel Elh

Thông thường tệp nhật ký tôi đuôi là nhật ký máy chủ hiện tại hoặc đầu ra chuyển hướng, vốn đã có sẵn sau khi quá trình được bắt đầu.
Peiming Hu

4

Docker container thoát nếu nhiệm vụ bên trong được thực hiện, vì vậy nếu bạn muốn giữ cho nó tồn tại ngay cả khi nó không có bất kỳ công việc nào hoặc đã hoàn thành chúng, bạn có thể làm docker run -di image. Sau khi bạn làm docker container lsbạn sẽ thấy nó chạy.


3

Có thể đó chỉ là tôi nhưng trên CentOS 7.3.1611 và Docker 1.12.6 nhưng cuối cùng tôi phải sử dụng kết hợp các câu trả lời được đăng bởi @VonC & @Christopher Simon để làm việc này một cách đáng tin cậy. Không có gì tôi làm trước khi điều này sẽ ngăn container thoát ra sau khi nó chạy CMD thành công. Tôi đang bắt đầu oracle-xe-11Gr2 và sshd.

Dockerfile

...
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N '' && systemctl enable sshd
...
CMD /etc/init.d/oracle-xe start && /sbin/sshd && tail -f /dev/null

Sau đó thêm -d -t và -i để chạy

docker run --shm-size=2g --name oracle-db -d -t -i -p 5022:22 -p 5080:8080 -p 1521:1521 centos-oracle:7.3.1611 

Cuối cùng sau nhiều giờ đập đầu vào tường

ssh -v root@127.0.0.1 -p 5022
...
root@127.0.0.1's password: 
debug1: Authentication succeeded (password).

Vì bất kỳ lý do nào, những điều trên sẽ thoát ra sau khi thực hiện CMD nếu đuôi -f bị xóa hoặc bất kỳ tùy chọn -t -d -i nào bị bỏ qua.



1

Tôi đã có cùng một vấn đề, chỉ cần mở một thiết bị đầu cuối với một cú đánh vào nó đã làm việc cho tôi:

tạo container:

docker run -d mcr.microsoft.com/mssql/server:2019-CTP3.0-ubuntu
containerid=52bbc9b30557

bắt đầu container:

docker start 52bbc9b30557

bắt đầu bash để giữ container chạy:

docker exec -it 52bbc9b30557 bash

bắt đầu quá trình bạn cần:

docker exec -it 52bbc9b30557 /path_to_cool_your_app

1

Nếu bạn đang sử dụng CMD ở cuối Dockerfile, điều bạn có thể làm là thêm mã vào cuối. Điều này sẽ chỉ hoạt động nếu docker của bạn được xây dựng trên Ubuntu hoặc bất kỳ HĐH nào có thể sử dụng bash.

&& /bin/bash

Tóm lại, phần cuối của Dockerfile của bạn sẽ trông giống như thế này.

...

CMD ls && ... && /bin/bash

Vì vậy, nếu bạn có bất cứ thứ gì tự động chạy sau khi bạn chạy hình ảnh docker của bạn và khi tác vụ hoàn thành, bash terminal sẽ hoạt động bên trong docker của bạn. Qua đó, bạn có thể nhập các lệnh shell của bạn.


1

Chạy docker với chế độ tương tác có thể giải quyết vấn đề.

Dưới đây là ví dụ để chạy hình ảnh có và không có chế độ tương tác

chaitra @ RSK-IND-BLR-L06: ~ / docker $ sudo docker chạy -d -t -i test_again1.0 b6b9a942a79b1243bada59db19c7999cfff52d0a8744542fa843c9535

chaitra @ RSK-IND-BLR-L06: ~ / docker $ sudo docker ps

CONTAINER ID HÌNH ẢNH TÌNH TRẠNG TÌNH TRẠNG TẠO TÊN

chaitra @ RSK-IND-BLR-L06: ~ / docker $ sudo docker chạy -d -t -i test_again1.0 bash c3d6a9529fd70c5b2dc2d7e90fe662d19c6dad8549e9c7b7

chaitra @ RSK-IND-BLR-L06: ~ / docker $ sudo docker ps

CONTAINER ID HÌNH ẢNH TÌNH TRẠNG TÌNH TRẠNG TẠO TẠO TÊN Nnam c3d6a9529fd7 test_again1.0 "bash" 2 giây trước Lên 1 giây awesome_haibt


0

nếu bạn muốn hoạt động trên container, bạn cần chạy nó ở phía trước để giữ cho nó tồn tại.


-1

Vấn đề đặt hàng

Jersey Beans trả lời (cả 3 ví dụ) làm việc cho tôi. Sau một chút thử nghiệm và sai sót, tôi nhận ra rằng thứ tự của các đối số có vấn đề.

Giữ cho container chạy trong nền: docker run -t -d <image-name>

Giữ container chạy ở phía trước: docker run <image-name> -t -d

Nó không rõ ràng đối với tôi đến từ nền tảng Powershell.

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.