2016-06-15 25 views
7

Tôi có Hình ảnh Docker sử dụng Tập lệnh (/bin/bash /init.sh) làm Điểm nhập. Tôi chỉ muốn thực thi tập lệnh này vào lần bắt đầu đầu tiên của vùng chứa. Nó sẽ được bỏ qua khi các thùng chứa được khởi động lại hoặc khởi động lại sau một sự cố của trình cắm thêm daemon.Chỉ chạy lệnh trong Vùng chứa Docker vào lần bắt đầu đầu tiên

Có cách nào để thực hiện việc này với docker hay không, hoặc có phải thực hiện một số loại kiểm tra trong tập lệnh không?

Trả lời

9

Điểm vào cho vùng chứa đế cho biết trình điều khiển docker sẽ chạy gì khi bạn muốn "chạy" vùng chứa cụ thể đó. Hãy đặt câu hỏi "những gì các container nên chạy khi nó bắt đầu lần thứ hai?" hoặc "vùng chứa sẽ chạy sau khi được khởi động lại?"

Có thể, những gì bạn đang làm là tuân theo cùng một phương pháp bạn thực hiện với cơ chế cấp phép "trường học cũ". Kịch bản của bạn là "cài đặt" các kịch bản cần thiết và bạn sẽ chạy ứng dụng của bạn như một dịch vụ systemd/upstart, phải không? Nếu bạn đang làm điều đó, bạn nên thay đổi điều đó thành định nghĩa "dockerized" hơn.

Điểm vào cho vùng chứa đó phải là tập lệnh thực sự khởi chạy ứng dụng của bạn thay vì thiết lập mọi thứ. Giả sử bạn cần cài đặt java để có thể chạy ứng dụng của bạn. Vì vậy, trong dockerfile bạn thiết lập các thùng chứa cơ sở để cài đặt tất cả những điều bạn cần như:

FROM alpine:edge 

RUN apk --update upgrade && apk add openjdk8-jre-base 
RUN mkdir -p /opt/your_app/ && adduser -HD userapp 

ADD target/your_app.jar /opt/your_app/your-app.jar 
ADD scripts/init.sh /opt/your_app/init.sh 

USER userapp 
EXPOSE 8081 

CMD ["/bin/bash", "/opt/your_app/init.sh"] 

container của chúng tôi, tại công ty tôi làm việc cho, trước khi chạy ứng dụng thực tế trong kịch bản init.sh họ lấy cấu hình từ lãnh sự (thay vì cung cấp một điểm gắn kết và đặt các cấu hình bên trong máy chủ hoặc nhúng chúng vào trong vùng chứa). Vì vậy, kịch bản sẽ giống như thế:

#!/bin/bash 

echo "Downloading config from consul..." 
confd -onetime -backend consul -node $CONSUL_URL -prefix /cfgs/$CONSUL_APP/$CONSUL_ENV_NAME 
echo "Launching your-app..." 
java -jar /opt/your_app/your-app.jar 

Một lời khuyên tôi có thể cung cấp cho bạn là (trong kinh nghiệm thực sự ngắn của tôi làm việc với các container) đối xử với container của bạn như thể họ không quốc tịch khi họ đang được cung cấp (tất cả các lệnh bạn chạy trước điểm vào).

+1

Hoàn toàn đồng ý về việc xem xét các vùng chứa không quốc tịch. Nếu có dữ liệu để khởi tạo, hãy đặt nó trong một ổ đĩa. – BMitch

+2

Tôi thực sự muốn làm theo lời khuyên của bạn, nhưng nó không phải là dễ dàng. Tôi có rất ít ảnh hưởng đến những thay đổi của ứng dụng và đã có thay đổi rất nhiều để sử dụng nó theo cách bạn mô tả. Ví dụ: mỗi khi vùng chứa bắt đầu, tập lệnh init sẽ thiết lập cơ sở dữ liệu cho ứng dụng. Điều này không nên xảy ra khi container được khởi động lại, vì nó ghi đè dữ liệu đã có ở đó ... Thật không may là nó được chứng minh là rất khó để dạy cho các nhà phát triển ứng dụng cách sử dụng docker. Vì vậy, tôi đang cố gắng để giữ cho nó cực kỳ đơn giản cho họ. – christian

+0

làm thế nào để bạn chạy điều này? – StarWind0

1

Tôi muốn làm tương tự trên vùng chứa cửa sổ. Nó có thể đạt được bằng cách sử dụng task scheduler trên windows. Tương đương với Linux cho Task Scheduler là cron. Bạn có thể sử dụng nó trong trường hợp của bạn. Để thực hiện điều chỉnh sửa này dockerfile và thêm dòng sau vào cuối

WORKDIR /app 
COPY myTask.ps1 . 
RUN schtasks /Create /TN myTask /SC ONSTART /TR "c:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe C:\app\myTask.ps1" /ru SYSTEM 

này Tạo một nhiệm vụ với tên myTask chạy nó onStart và nhiệm vụ tự của nó là để thực hiện một kịch bản PowerShell đặt ở "c: \ ứng dụng \ myTask.ps1 ".

Tập lệnh myTask.ps1 này sẽ thực hiện bất kỳ việc khởi tạo nào bạn cần thực hiện khi khởi động vùng chứa. Hãy chắc chắn rằng bạn xóa nhiệm vụ này một khi nó được thực hiện thành công hoặc người nào khác nó sẽ chạy ở mọi lần khởi động. Để xóa nó, bạn có thể sử dụng lệnh sau ở cuối tập lệnh myTask.ps1.

schtasks /Delete /TN myTask /F 
0

tôi phải làm điều này và tôi đã kết thúc làm một docker run -d mà vừa tạo ra một container tách ra và bắt đầu bash (ở chế độ nền) tiếp theo là một docker exec, mà đã làm các khởi tạo cần thiết. đây là một ví dụ

docker run -itd --name=myContainer myImage /bin/bash 
docker exec -it myContainer /bin/bash -c /init.sh 

Bây giờ khi tôi khởi động lại container của tôi tôi có thể chỉ làm

docker start myContainer 
docker attach myContainer 

này có thể không lý tưởng nhưng làm việc tốt cho tôi.

Các vấn đề liên quan