Tại sao container docker thoát ngay lập tức


239

Tôi chạy một container trong nền bằng cách sử dụng

 docker run -d --name hadoop h_Service

nó thoát ra nhanh chóng Nhưng nếu tôi chạy ở nền trước, nó hoạt động tốt. Tôi đã kiểm tra nhật ký bằng

docker logs hadoop

không có lỗi Có ý kiến ​​gì không?

DOCKERFILE

 FROM java_ubuntu_new
 RUN wget http://archive.cloudera.com/cdh4/one-click-install/precise/amd64/cdh4-repository_1.0_all.deb
 RUN dpkg -i cdh4-repository_1.0_all.deb
 RUN curl -s http://archive.cloudera.com/cdh4/ubuntu/precise/amd64/cdh/archive.key | apt-key add -
 RUN  apt-get update
 RUN apt-get install -y hadoop-0.20-conf-pseudo
 RUN dpkg -L hadoop-0.20-conf-pseudo
 USER hdfs
 RUN hdfs namenode -format
 USER root
 RUN apt-get install -y sudo
 ADD . /usr/local/
 RUN chmod 777 /usr/local/start-all.sh
 CMD ["/usr/local/start-all.sh"]

bắt đầu-all.sh

 #!/usr/bin/env bash
 /etc/init.d/hadoop-hdfs-namenode start
 /etc/init.d/hadoop-hdfs-datanode start
 /etc/init.d/hadoop-hdfs-secondarynamenode start
 /etc/init.d/hadoop-0.20-mapreduce-tasktracker start
 sudo -u hdfs hadoop fs -chmod 777 /
 /etc/init.d/hadoop-0.20-mapreduce-jobtracker start
 /bin/bash

1
Nguyên tắc vàng là bạn nên ngăn chặn các máy chủ được neo của mình. Hầu hết các gói máy chủ đều có các tùy chọn để buộc chúng ở phía trước vì daemonizing là trường hợp bình thường.
Arnaud Meuret

Bất cứ điều gì bạn đang hy vọng đạt được, chmod 777không an toànsai. Bạn nên hoàn nguyên các quyền lành mạnh (có thể là 755 trong trường hợp này).
tripleee

Câu trả lời:


125

Một container docker thoát khi quá trình chính của nó kết thúc.

Trong trường hợp này, nó sẽ thoát khi start-all.shtập lệnh của bạn kết thúc. Tôi không biết đủ về hadoop để cho bạn biết cách thực hiện trong trường hợp này, nhưng bạn cần để lại thứ gì đó chạy ở phía trước hoặc sử dụng trình quản lý quy trình như runit hoặc giám sát để chạy các quy trình.

Tôi nghĩ bạn phải nhầm lẫn về nó hoạt động nếu bạn không chỉ định -d; nó sẽ có tác dụng chính xác như nhau Tôi nghi ngờ bạn đã khởi chạy nó với một lệnh hơi khác hoặc sử dụng -itsẽ thay đổi mọi thứ.

Một giải pháp đơn giản có thể là thêm một cái gì đó như:

while true; do sleep 1000; done

đến cuối kịch bản. Tôi không thích điều này tuy nhiên, vì kịch bản nên thực sự giám sát các quá trình mà nó khởi động.

(Tôi nên nói rằng tôi đã đánh cắp mã đó từ https://github.com/fterenceiq/hadoop-docker/blob/master/bootstrap.sh )


217

Điều này đã lừa tôi:

docker run -dit ubuntu

Sau đó, tôi đã kiểm tra các quy trình đang chạy bằng cách sử dụng:

docker ps -a

Để gắn lại container

docker attach CONTAINER_NAME

MIPO: Để thoát mà không dừng loại container: ^P^Q


15
@T Mom, từ docs.docker.com/engine/reference/commandline/run -d, --detach Chế độ tách rời: chạy lệnh trong nền, -i, - tương tác Giữ STDIN mở ngay cả khi không được đính kèm, -t, - -tty Phân bổ một giả TTY -ditchỉ là tốc ký

3
@ am17torres đúng, xin lỗi hãy để tôi làm rõ câu hỏi khó hiểu của mình; d được tách ra và tôi tương tác, vì vậy sự kết hợp giữa d và tôi gây nhầm lẫn cho tôi. Tôi nghĩ d là khởi chạy nó như một quá trình nền (không tương tác).
Tommy

2
@T Mom Khi các tùy chọn này kết hợp, container sẽ vào chế độ tương tác ở chế độ nền .
Yon

2
@ Mẹ ơi, @ am17torres -dilà mức tối thiểu bắt buộc, -ttùy chọn là không cần thiết khi được sử dụng -dnếu tôi hiểu chính xác
Đổi mới

2
Trên thực tế, bạn sẽ không thể thấy lời nhắc của mình nếu bạn gắn lại mà không -tbật ... nhưng vì tôi thường là execmột bash mới mỗi khi tôi không nhận thấy. Tôi đã gặp sự cố khi tách khỏi máy mac nhưng có lẽ tôi đã làm sai điều này ..
Đổi lại

65

Tôi muốn mở rộng hoặc dám nói, cải thiện câu trả lời được đề cập bởi người cắm trại

Khi bạn chạy

docker run -dit ubuntu

về cơ bản bạn đang chạy container ở chế độ nền trong chế độ tương tác.

Khi bạn đính kèm và thoát khỏi container bằng CTRL + D (cách phổ biến nhất để làm điều đó), bạn dừng container vì bạn vừa giết tiến trình chính mà bạn đã khởi động container của mình bằng lệnh trên.

Tận dụng lợi thế của một container đang chạy, tôi sẽ chỉ cần xử lý một quá trình bash khác và nhận TTY giả bằng cách chạy:

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

29

Bất cứ khi nào tôi muốn một container ở lại sau khi hoàn thành việc thực thi tập lệnh, tôi thêm

&& tail -f /dev/null

vào cuối lệnh. Nên nó phải là:

/usr/local/start-all.sh && tail -f /dev/null

19

Tại sao container docker thoát ngay lập tức?

Nếu bạn muốn buộc hình ảnh treo xung quanh (để gỡ lỗi một cái gì đó hoặc kiểm tra trạng thái của hệ thống tệp), bạn có thể ghi đè điểm nhập cảnh để thay đổi nó thành một vỏ:

docker run -it --entrypoint=/bin/bash myimagename

18

Một cách tiếp cận tốt sẽ là khởi động các quy trình và dịch vụ của bạn chạy chúng trong nền và sử dụng wait [n ...]lệnh ở cuối tập lệnh của bạn. Trong bash, lệnh chờ buộc quy trình hiện tại phải:

Đợi cho mỗi quá trình được chỉ định và trả lại trạng thái chấm dứt của nó. Nếu n không được cung cấp, tất cả các quy trình con hiện đang hoạt động được chờ đợi và trạng thái trả về bằng không.

Tôi đã có ý tưởng này từ kịch bản bắt đầu của Sébastien Pujadas cho bản dựng nai sừng tấm của mình .

Lấy từ câu hỏi ban đầu, start-all.sh của bạn sẽ trông giống như thế này ...

 #!/usr/bin/env bash
 /etc/init.d/hadoop-hdfs-namenode start &
 /etc/init.d/hadoop-hdfs-datanode start &
 /etc/init.d/hadoop-hdfs-secondarynamenode start &
 /etc/init.d/hadoop-0.20-mapreduce-tasktracker start &
 sudo -u hdfs hadoop fs -chmod 777 /
 /etc/init.d/hadoop-0.20-mapreduce-jobtracker start &
 wait

5

Thêm phần này vào cuối Dockerfile:

CMD tail -f /dev/null

Tệp Docker mẫu:

FROM ubuntu:16.04

# other commands

CMD tail -f /dev/null

Tài liệu tham khảo


CMD tail -f /dev/nullchạy nó thông qua sh -c "...". Chúng ta có thể sử dụng các exechình thức thay thế? Tức làCMD ["tail", "-f", "/dev/null"]
Meglio

4

Pracitce của tôi là trong Dockerfile bắt đầu một shell sẽ không thoát ngay lập tức CMD [ "sh", "-c", "service ssh start; bash"], sau đó chạy docker run -dit image_name. Bằng cách này, dịch vụ (ssh) và container đang chạy.


1

Tôi đã thêm readtuyên bố shell vào cuối. Điều này giữ cho quá trình chính của container - kịch bản shell khởi động - đang chạy.


1

Thêm

exec "$@"

ở cuối kịch bản shell của tôi là bản sửa lỗi của tôi!


Điều đó chỉ có nghĩa là nó sẽ chạy cmd của bạn, nếu cmd của bạn chỉ là 'bash' thì nó vẫn không hoạt động
Shardj

1

Nếu bạn kiểm tra Dockerfile từ các thùng chứa, ví dụ fballiano / magento2-apache-php

bạn sẽ thấy rằng ở cuối tập tin của mình, anh ta thêm lệnh sau: while true; ngủ 1 giấc; làm xong

Bây giờ, những gì tôi khuyên, là bạn làm điều này

docker container ls --all | grep 127

Sau đó, bạn sẽ thấy nếu hình ảnh docker của bạn có lỗi, nếu nó thoát bằng 0, thì có lẽ nó cần một trong những lệnh này sẽ ngủ mãi mãi.


0

Có nhiều cách có thể khiến docker thoát ngay lập tức. Đối với tôi, đó là vấn đề với tôi Dockerfile. Có một lỗi trong tập tin đó. Tôi đã có ENTRYPOINT ["dotnet", "M4Movie_Api.dll]thay vì ENTRYPOINT ["dotnet", "M4Movie_Api.dll"]. Như bạn có thể thấy tôi đã bỏ lỡ một trích dẫn (") ở cuối.

Để phân tích vấn đề, tôi khởi động thùng chứa của mình và nhanh chóng gắn thùng chứa của mình để có thể biết vấn đề chính xác là gì.

C:\SVenu\M4Movie\Api\Api>docker start 4ea373efa21b


C:\SVenu\M4Movie\Api\Api>docker attach 4ea373efa21b

Trong đó 4ea373efa21b là id container của tôi. Điều này đưa tôi đến vấn đề thực tế.

nhập mô tả hình ảnh ở đây

Sau khi tìm ra vấn đề, tôi phải xây dựng, khôi phục, xuất bản lại container của mình.


0

Đến từ các bản sao, tôi không thấy bất kỳ câu trả lời nào ở đây giải quyết các phản ứng rất phổ biến của việc chạy khối lượng công việc chính của bạn như một công việc nền, và sau đó tự hỏi tại sao Docker thoát.

Nói một cách đơn giản, nếu bạn có

my-main-thing &

sau đó lấy ra &để chạy công việc ở phía trước hoặc thêm

wait

ở cuối đoạn script để làm cho nó chờ tất cả các công việc nền.

Sau đó nó sẽ vẫn thoát nếu khối lượng công việc chính thoát, vì vậy có thể chạy nó trong một while truevòng lặp để buộc nó khởi động lại mãi mãi:

while true; do
    my-main-thing &
    other things which need to happen while the main workload runs in the background
    maybe if you have such things
    wait
done

(Cũng lưu ý cách viết while true. Người ta thường thấy những điều ngớ ngẩn như while [ true ]hoặc while [ 1 ]ngẫu nhiên xảy ra với công việc, nhưng không có nghĩa là những gì tác giả có thể tưởng tượng họ nên có nghĩa là gì.)


0

Bạn cần chạy nó với cờ -d để nó chạy dưới dạng daemon trong nền.

docker chạy -d -it ub Ubuntu bash


-5

Bạn có thể chạy container bằng cờ khởi động lại này.

docker run -d --name=<some-name> -p xxxx:xxxx ... <image-name> --restart=unless-stopped

-8

Vì hình ảnh là một linux, nên một điều cần kiểm tra là đảm bảo bất kỳ tập lệnh shell nào được sử dụng trong vùng chứa đều có kết thúc dòng unix. Nếu chúng có ^ M ở cuối thì chúng là kết thúc dòng windows. Một cách để khắc phục chúng là với dos2unix trên /usr/local/start-all.sh để chuyển đổi chúng từ windows sang unix. Chạy docker trong chế độ tương tác có thể giúp tìm ra các vấn đề khác. Bạn có thể có một lỗi đánh máy tên tập tin hoặc một cái gì đó. xem https://en.wikipedia.org/wiki/Newline

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.