Tôi có thể chạy nhiều chương trình trong một Docker không?


150

Tôi đang cố gắng xoay quanh Docker từ thời điểm triển khai một ứng dụng dự định chạy trên người dùng trên máy tính để bàn. Ứng dụng của tôi chỉ đơn giản là một ứng dụng web bình và cơ sở dữ liệu mongo. Thông thường tôi sẽ cài đặt cả trong VM và, chuyển tiếp một cổng máy chủ đến ứng dụng web khách. Tôi muốn dùng thử Docker nhưng tôi không chắc làm thế nào tôi có ý định sử dụng nhiều hơn một chương trình. Các tài liệu nói rằng chỉ có thể có ENTRYPOINT vì vậy làm thế nào tôi có thể có ứng dụng Mongo và bình của tôi. Hoặc họ cần phải ở trong các thùng chứa riêng biệt, trong trường hợp nào họ nói chuyện với nhau và làm thế nào để phân phối ứng dụng dễ dàng?


2
Spot on: khiến tôi tự hỏi tại sao docker lại phổ biến đến vậy .. (quy trình đơn ..?) - nhưng hãy xem câu trả lời cho chúng tôi biết ..
javadba

Câu trả lời:


120

Có thể chỉ có một ENTRYPOINT, nhưng mục tiêu đó thường là một tập lệnh khởi chạy bao nhiêu chương trình cần thiết. Bạn cũng có thể sử dụng ví dụ như Giám sát viên hoặc tương tự để đảm bảo khởi chạy nhiều dịch vụ bên trong một container. Đây là một ví dụ về một container docker chạy mysql, apache và wordpress trong một container .

Giả sử, Bạn có một cơ sở dữ liệu được sử dụng bởi một ứng dụng web. Sau đó, có thể dễ dàng hơn để chạy cả hai trong một container.

Nếu Bạn có một cơ sở dữ liệu dùng chung được sử dụng bởi nhiều hơn một ứng dụng, thì tốt hơn là chạy cơ sở dữ liệu trong vùng chứa riêng của nó và mỗi ứng dụng trong các thùng chứa riêng của chúng.

Có ít nhất hai khả năng làm thế nào các ứng dụng có thể giao tiếp với nhau khi chúng chạy trong các thùng chứa khác nhau:

  1. Sử dụng các cổng IP tiếp xúc và kết nối thông qua chúng.
  2. Các phiên bản docker gần đây hỗ trợ liên kết .

1
Có vẻ như phiên bản mới của Docker hiện hỗ trợ các mạng container Docker .
jpierson

Docker hiện hỗ trợ để chạy Trình giám sát, cho phép bạn phân tách hành vi cho từng quy trình như autorestart = true, stdout_logfile, stderr_logfile, v.v. Hãy xem docs.docker.com/engine/admin/USE_supervisord
Andreas Lundgren

4
Tôi chắc chắn sẽ không khuyên bạn nên thử chạy ứng dụng web và mongodb trong cùng một thùng chứa trong ví dụ này. Có các trường hợp sử dụng tốt của giám sát hoặc các quy trình giống như init trong Docker nhưng đây không phải là một phần của chúng. Thật đơn giản hơn khi sử dụng docker-compose để chỉ chạy hai dịch vụ trong các thùng chứa riêng biệt.
nicolas-van

@ nicolas-van tại sao nó đơn giản hơn? Có phải vì nếu db chết tôi có thể khởi động lại bộ chứa của db thay vì phải khởi động lại toàn bộ không?
sáng chói

Các ứng dụng trên cùng một máy cũng có thể giao tiếp qua các ổ cắm tên miền Unix . Hiệu suất cao nhất được đảm bảo.
Jule hoài nghi

21

Tôi có yêu cầu tương tự là chạy LAMP stack, Mongo DB và các dịch vụ của riêng tôi

Docker là ảo hóa dựa trên hệ điều hành, đó là lý do tại sao nó cô lập vùng chứa của nó xung quanh một tiến trình đang chạy, do đó nó yêu cầu ít nhất một tiến trình đang chạy trong FOREGROUND.

Vì vậy, bạn cung cấp tập lệnh khởi động của riêng bạn làm điểm vào, do đó tập lệnh khởi động của bạn trở thành tập lệnh hình ảnh Docker mở rộng, trong đó bạn có thể xếp chồng bất kỳ số lượng dịch vụ nào cho đến khi dịch vụ BẮT ĐẦU MỘT LẦN BẮT ĐẦU, SAU KHI TOWARDS THE END

Vì vậy, tập tin hình ảnh Docker của tôi có hai dòng dưới đây:

COPY myStartupScript.sh /usr/local/myscripts/myStartupScript.sh
CMD ["/bin/bash", "/usr/local/myscripts/myStartupScript.sh"]

Trong kịch bản của tôi, tôi chạy tất cả MySQL, MongoDB, Tomcat, v.v ... Cuối cùng, tôi chạy Apache của tôi như một luồng tiền cảnh.

source /etc/apache2/envvars
/usr/sbin/apache2 -DFOREGROUND

Điều này cho phép tôi bắt đầu tất cả các dịch vụ của mình và giữ cho container tồn tại với dịch vụ cuối cùng bắt đầu ở phía trước

Hy vọng nó giúp

CẬP NHẬT : Kể từ lần cuối tôi trả lời câu hỏi này, những điều mới đã xuất hiện như Docker compose , có thể giúp bạn chạy từng dịch vụ trên container của chính nó, nhưng liên kết tất cả chúng lại với nhau như là sự phụ thuộc giữa các dịch vụ đó, hãy thử biết thêm về docker-compose và sử dụng nó, nó là cách thanh lịch hơn trừ khi nhu cầu của bạn không phù hợp với nó.


6

Tôi hoàn toàn không đồng ý với một số giải pháp trước đây khuyến nghị chạy cả hai dịch vụ trong cùng một container. Nó được nêu rõ trong tài liệu rằng nó không được khuyến nghị :

Chúng tôi thường khuyên bạn nên tách riêng các khu vực quan tâm bằng cách sử dụng một dịch vụ cho mỗi container. Dịch vụ đó có thể phân nhánh thành nhiều quy trình (ví dụ: máy chủ web Apache bắt đầu nhiều quy trình worker). Bạn có thể có nhiều quy trình, nhưng để có được lợi ích cao nhất từ ​​Docker, hãy tránh một container chịu trách nhiệm cho nhiều khía cạnh của ứng dụng tổng thể của bạn. Bạn có thể kết nối nhiều container bằng các mạng do người dùng xác định và khối lượng được chia sẻ.

Có những trường hợp sử dụng tốt cho giám sát hoặc các chương trình tương tự nhưng chạy ứng dụng web + cơ sở dữ liệu không phải là một phần của chúng.

Bạn chắc chắn nên sử dụng docker-compose để làm điều đó và sắp xếp nhiều container với các trách nhiệm khác nhau.


2
Đây là một nhận xét, không phải là một câu trả lời. Vui lòng xem xét thêm một lời giải thích và / hoặc liên kết để hỗ trợ vị trí này. Nếu không thì không có ích.
Ivan Ivanov

1
Đây là một câu trả lời theo nghĩa là khuyến nghị tốt nhất tôi có thể đưa ra trong trường hợp sử dụng như vậy là sử dụng docker-compose. Dù sao, bạn đúng khi tôi có thể cung cấp thêm liên kết đến các đề xuất chính thức. Tôi sẽ cập nhật điều đó.
nicolas-van

Câu hỏi là về việc chạy 2 quy trình trong một container, do đó không quan tâm đến các thực tiễn tốt nhất. Tôi sẽ cung cấp cho bạn một ví dụ: Tôi đã phải chạy RabbitMQ bên trong hình ảnh PhotonOS dựa và một quá trình java quá ... Vì vậy, tôi đã sử dụng một kịch bản nhập cảnh và được sử dụng trong khi EntryPoint :)
Vallerious

Câu hỏi ban đầu không phải là một câu hỏi chung về tính khả thi kỹ thuật của việc chạy hai quy trình trong bộ chứa Docker. Nó nêu một trường hợp sử dụng cụ thể là triển khai ứng dụng Python cùng với cơ sở dữ liệu MongoDB. Và, đối với trường hợp sử dụng đó, khuyến nghị tốt nhất là không khuyến khích việc sử dụng một container duy nhất và khuyến nghị sử dụng docker-compose.
nicolas-van

5

Chúng có thể nằm trong các thùng chứa riêng biệt và thực sự, nếu ứng dụng cũng được dự định chạy trong một môi trường lớn hơn, có lẽ chúng sẽ như vậy.

Một hệ thống nhiều container sẽ cần thêm một số phối hợp để có thể đưa ra tất cả các phụ thuộc cần thiết, mặc dù trong Docker v0.6.5 +, có một cơ sở mới để hỗ trợ với chính Docker - Liên kết . Tuy nhiên, với một giải pháp đa máy, vẫn có thứ gì đó phải được sắp xếp từ bên ngoài môi trường Docker.

Với hai thùng chứa khác nhau, hai phần vẫn giao tiếp qua TCP / IP, nhưng trừ khi các cổng bị khóa cụ thể (không được khuyến nghị, vì bạn không thể chạy nhiều hơn một bản sao), bạn sẽ phải vượt qua cổng mới rằng cơ sở dữ liệu đã được hiển thị cho ứng dụng, để nó có thể giao tiếp với Mongo. Đây là một lần nữa, một cái gì đó mà Liên kết có thể giúp đỡ.

Để cài đặt đơn giản, nhỏ hơn, trong đó tất cả các phụ thuộc đều nằm trong cùng một thùng chứa, có cả cơ sở dữ liệu và thời gian chạy Python được khởi động bởi chương trình ban đầu được gọi là ENTRYPOINT. Điều này có thể đơn giản như một tập lệnh shell hoặc một số bộ điều khiển quy trình khác - Giám sát khá phổ biến và một số ví dụ tồn tại trong Dockerfiles công khai.


3

Tôi đồng ý với các câu trả lời khác rằng sử dụng hai container là tốt hơn, nhưng nếu bạn đặt trái tim vào việc đóng gói nhiều dịch vụ trong một container, bạn có thể sử dụng một cái gì đó như giám sát.

trong Hipache chẳng hạn, Dockerfile đi kèm chạy giám sát và tệp giám sát tệp chỉ định cho cả hipache và redis-server sẽ được chạy.


2

Docker cung cấp một vài ví dụ về cách làm điều đó. Tùy chọn gọn nhẹ là:

Đặt tất cả các lệnh của bạn trong một tập lệnh bao bọc, hoàn thành với thông tin kiểm tra và gỡ lỗi. Chạy tập lệnh bao bọc như của bạn CMD. Đây là một ví dụ rất ngây thơ. Đầu tiên, tập lệnh bao bọc:

#!/bin/bash

# Start the first process
./my_first_process -D
status=$?
if [ $status -ne 0 ]; then
  echo "Failed to start my_first_process: $status"
  exit $status
fi

# Start the second process
./my_second_process -D
status=$?
if [ $status -ne 0 ]; then
  echo "Failed to start my_second_process: $status"
  exit $status
fi

# Naive check runs checks once a minute to see if either of the processes exited.
# This illustrates part of the heavy lifting you need to do if you want to run
# more than one service in a container. The container will exit with an error
# if it detects that either of the processes has exited.
# Otherwise it will loop forever, waking up every 60 seconds

while /bin/true; do
  ps aux |grep my_first_process |grep -q -v grep
  PROCESS_1_STATUS=$?
  ps aux |grep my_second_process |grep -q -v grep
  PROCESS_2_STATUS=$?
  # If the greps above find anything, they will exit with 0 status
  # If they are not both 0, then something is wrong
  if [ $PROCESS_1_STATUS -ne 0 -o $PROCESS_2_STATUS -ne 0 ]; then
    echo "One of the processes has already exited."
    exit -1
  fi
  sleep 60
done

Tiếp theo, Dockerfile:

FROM ubuntu:latest
COPY my_first_process my_first_process
COPY my_second_process my_second_process
COPY my_wrapper_script.sh my_wrapper_script.sh
CMD ./my_wrapper_script.sh

2

Bạn có thể chạy 2 tiến trình trong nền trước bằng cách sử dụng wait. Chỉ cần tạo một tập lệnh bash với nội dung sau đây. ví dụ như start.sh:

# runs 2 commands simultaneously:

mongod & # your first application
P1=$!
python script.py & # your second application
P2=$!
wait $P1 $P2

Trong Dockerfile của bạn, hãy bắt đầu với

CMD bash start.sh

0

Nếu một tập lệnh chuyên dụng có vẻ như quá nhiều chi phí, bạn có thể sinh ra các quy trình riêng biệt một cách rõ ràng với sh -c. Ví dụ:

CMD sh -c 'mini_httpd -C /my/config -D &' \
 && ./content_computing_loop
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.