2014-10-17 30 views
123

Giả sử tôi có một vùng chứa tầm thường dựa trên ubuntu:latest. Bây giờ có một bản cập nhật bảo mật và ubuntu:latest được cập nhật trong repo docker.Cách tự động cập nhật vùng chứa docker của bạn, nếu hình ảnh cơ sở được cập nhật

1) Làm cách nào để biết hình ảnh cục bộ và vùng chứa của nó đang chạy phía sau?

2) Có một số thực hành tốt nhất để tự động cập nhật hình ảnh và container địa phương để theo dõi các bản cập nhật Docker repo, mà trong thực tế sẽ cung cấp cho bạn các niceties cùng của việc giám sát-nâng cấp chạy trên một ubuntu-máy thông thường

+6

Tôi đang tìm câu trả lời cho điều này kể từ khi bắt đầu trình docker. Nó thậm chí còn phức tạp hơn một chút. Nếu tôi cài đặt apache (ví dụ) và được cập nhật, hình ảnh gốc sẽ không thay đổi, vì tôi đã cài đặt nó sau đó. Tôi vẫn muốn có tự động cập nhật cho apache. Tôi thực sự hỏi trong IRC về điều này và đã "theo dõi thượng nguồn và xây dựng lại trên cập nhật" như một câu trả lời ... – Mathias

+7

Vui vì tôi không phải là người duy nhất tự hỏi. Có vẻ như sự phát triển và khả năng tái tạo là quan trọng hơn đối với các nhà phát triển docker hơn là các cơ chế cập nhật hợp lý mà chúng ta đã có trong nhiều năm nay. – hbogert

+0

Vấn đề là, docker chỉ là công nghệ cho các container. Tôi nghĩ rằng nó cần một thời gian để một hệ sinh thái phát triển xung quanh đó. Có những vấn đề khác docker không địa chỉ như đăng nhập. – Mathias

Trả lời

5

Bạn sẽ không biết vùng chứa của mình ở đằng sau mà không chạy docker pull. Sau đó, bạn cần phải rebuild hoặc recompose hình ảnh của mình.

docker pull image:tag 
docker-compose -f docker-compose.yml -f production.yml up -d --build 

Các lệnh có thể được đặt trong tập lệnh cùng với bất kỳ thứ gì cần thiết để hoàn thành nâng cấp, mặc dù vùng chứa thích hợp sẽ không cần thêm bất kỳ thứ gì.

+0

1: ok, nhưng sau đó tôi phải xem tất cả hình ảnh cục bộ của mình, lấy hình ảnh cơ sở của chúng, kéo hình ảnh đó. Sau đó, xây dựng lại các hình ảnh có hình ảnh cơ sở đã thay đổi. Sau đó, dừng các thùng chứa có hình ảnh bị thay đổi và tạo lại các vùng chứa bằng 'docker run' và các tham số cần thiết. Điều này có vẻ quá thủ công. Nhưng nếu đây là hiện trạng, thì tôi sẽ chấp nhận câu trả lời. – hbogert

+0

Vui lòng đợi trước khi bạn chấp nhận. Có lẽ có cái gì đó ngoài kia. Tôi đã sử dụng docker trong 6 tháng, nhưng vẫn chưa theo kịp những phát triển mới nhất. – seanmcl

+0

Bằng cách nào đó, trong nội bộ, Docker có thể so sánh hình ảnh để thực hiện khả năng 'bộ nhớ đệm' của nó. Có lẽ bạn có thể tìm cách để tận dụng điều đó. Nói cách khác, hãy kiểm tra xem liệu các hình ảnh cơ bản (tất cả các cách quay lại cơ sở) đã thay đổi chưa và sau đó kích hoạt một quá trình để xây dựng lại. Thật không may, bộ nhớ đệm sẽ không giúp bạn trong trường hợp đó: toàn bộ hình ảnh sẽ được xây dựng lại vì hình ảnh cơ bản đã thay đổi. –

11

Tôi đã gặp vấn đề tương tự và nghĩ rằng nó có thể được giải quyết đơn giản bằng công việc cron gọi số unattended-upgrade hàng ngày.

Mục đích của tôi là có giải pháp tự động và nhanh chóng để đảm bảo rằng thùng chứa sản phẩm được bảo mật và cập nhật vì có thể mất một thời gian để cập nhật hình ảnh của tôi và triển khai hình ảnh đế mới với bản cập nhật bảo mật mới nhất.

Nó cũng có thể để tự động hóa việc xây dựng hình ảnh và triển khai với Github hooks

tôi đã tạo ra một cơ bản docker image với điều đó tự động kiểm tra và cài đặt cập nhật bảo mật hàng ngày (có thể chạy trực tiếp bởi docker run itech/docker-unattended-upgrade).

Tôi cũng đã xem một số khác nhau approach để kiểm tra xem vùng chứa có cần cập nhật hay không.

thực hiện hoàn chỉnh của tôi:

Dockerfile

FROM ubuntu:14.04 

RUN apt-get update \ 
&& apt-get install -y supervisor unattended-upgrades \ 
&& rm -rf /var/lib/apt/lists/* 

COPY install /install 
RUN chmod 755 install 
RUN /install 

COPY start /start 
RUN chmod 755 /start 

Helper script

cài đặt

#!/bin/bash 
set -e 

cat > /etc/supervisor/conf.d/cron.conf <<EOF 
[program:cron] 
priority=20 
directory=/tmp 
command=/usr/sbin/cron -f 
user=root 
autostart=true 
autorestart=true 
stdout_logfile=/var/log/supervisor/%(program_name)s.log 
stderr_logfile=/var/log/supervisor/%(program_name)s.log 
EOF 

rm -rf /var/lib/apt/lists/* 

ENTRYPOINT ["/start"] 

bắt đầu

Sửa

tôi đã phát triển một công cụ nhỏ docker-run chạy như container Docker và có thể được sử dụng để cập nhật các gói bên trong toàn bộ hoặc một container chạy được lựa chọn, nó cũng có thể được sử dụng để chạy bất kỳ lệnh tùy ý nào.

Có thể dễ dàng kiểm tra bằng lệnh sau:

docker run --rm -v /var/run/docker.sock:/tmp/docker.sock itech/docker-run exec

mà theo mặc định sẽ thực hiện date lệnh trong tất cả các container chạy và hiển thị kết quả. Nếu bạn vượt qua update thay vì exec nó sẽ thực hiện apt-get update Tiếp theo apt-get upgrade -y trong tất cả các container chạy

+0

Tham chiếu của tôi để nâng cấp không cần giám sát chỉ để hiển thị sự tương tự trong môi trường không phải docker. Mục đích của tôi là để giải quyết điều này cách docker (nếu đó tồn tại oc.) Có một quá trình bổ sung trong một container nhịp đập mục đích của docker imo. Nó vá lỗi của sự chậm trễ giữa upstream cập nhật hình ảnh của họ và bạn, người dùng, thực sự depoying nó trên container hiện tại của bạn. Mặc dù điều này có thể mất tới 1 ngày với các nâng cấp không cần giám sát, vì vậy .. Ngoài ra tham chiếu github là không thỏa đáng, vì cơ chế cập nhật hiện phụ thuộc nhiều vào hệ điều hành chủ. – hbogert

+0

Cách "docker" không ngăn cản bạn chạy các quy trình khác trên cùng một vùng chứa nếu chúng có liên quan chặt chẽ và sẽ không tạo ra tắc nghẽn khả năng mở rộng. Và trường hợp sử dụng cụ thể này là một ví dụ hay khi bạn có thể có một thùng chứa với một tiến trình đang chạy khác. (ví dụ: xem hình ảnh cho [gitlab] (https://registry.hub.docker.com/u/sameersbn/gitlab/) vì nó chạy nhiều quy trình * bắt buộc * trên cùng một vùng chứa). – iTech

+0

Tôi sẽ không gọi một cơ chế cập nhật liên quan chặt chẽ đến chức năng chính của hình ảnh.Giải pháp này cũng giống như cho mọi ứng dụng trên một máy thông thường cơ chế cập nhật riêng của nó thay vì đặt gánh nặng lên trình quản lý gói. Mặc dù nó là một giải pháp, nó không trả lời câu hỏi của tôi, tự động cập nhật hình ảnh cục bộ và sau đó, các vùng chứa nên được chạy lại. Với việc cập nhật trong các thùng chứa bản thân chúng tôi đang giới thiệu rất nhiều nhà nước một lần nữa mà chúng tôi không có ý tưởng, đó là chống lại cách docker (một lần nữa imho). – hbogert

79

Chúng tôi sử dụng một kịch bản mà kiểm tra nếu một container chạy được bắt đầu với hình ảnh mới nhất. Chúng tôi cũng sử dụng các tập lệnh init khởi động để bắt đầu hình ảnh docker.

#!/usr/bin/env bash 
set -e 
BASE_IMAGE="registry" 
REGISTRY="registry.hub.docker.com" 
IMAGE="$REGISTRY/$BASE_IMAGE" 
CID=$(docker ps | grep $IMAGE | awk '{print $1}') 
docker pull $IMAGE 

for im in $CID 
do 
    LATEST=`docker inspect --format "{{.Id}}" $IMAGE` 
    RUNNING=`docker inspect --format "{{.Image}}" $im` 
    NAME=`docker inspect --format '{{.Name}}' $im | sed "s/\///g"` 
    echo "Latest:" $LATEST 
    echo "Running:" $RUNNING 
    if [ "$RUNNING" != "$LATEST" ];then 
     echo "upgrading $NAME" 
     stop docker-$NAME 
     docker rm -f $NAME 
     start docker-$NAME 
    else 
     echo "$NAME up to date" 
    fi 
done 

Và init trông giống như

docker run -t -i --name $NAME $im /bin/bash 
+1

Cảm ơn rất nhiều vì sự đóng góp quý giá này. Điều này có vẻ giống như một cách hay để cập nhật hình ảnh cơ sở. Câu hỏi còn lại là, làm thế nào để bạn cập nhật một ứng dụng (như apache) đã được cài đặt bởi sự phân phối trong dockerfile? Hay bạn chỉ sử dụng hình ảnh cơ sở sẵn có mà chỉ cần mã ứng dụng của bạn (như một trang web)? – Mathias

+0

Chúng tôi sử dụng trình đóng gói và con rối để định cấu hình hình ảnh của mình. Hình ảnh của chúng tôi đã sẵn sàng để đi vào sản xuất sau khi tạo ra – bsuttor

+0

@Mathias, xem câu trả lời đã chỉnh sửa của tôi Tôi có một công cụ nhỏ [docker-run] (https://github.com/iTech-Developer/docker-run) mà tôi đang sử dụng để cập nhật các gói linux (hiện đang debian/ubuntu) trong tất cả các thùng chứa đang chạy. – iTech

2

Tiền đề để câu trả lời của tôi:

  1. Container đang chạy với thẻ.
  2. Cùng một thẻ có thể được trỏ đến hình ảnh UUID khác nhau khi chúng tôi vui lòng/cảm thấy thích hợp.
  3. cập nhật được thực hiện với một hình ảnh có thể được cam kết một lớp hình ảnh mới

Cách tiếp cận

  1. Build tất cả các container ở nơi đầu tiên với một kịch bản cập nhật bảo mật vá
  2. xây dựng một quy trình tự động cho các trường hợp sau đây
    • Chạy hình ảnh hiện có tới vùng chứa mới có vá bảo mật cript như lệnh
    • Commit thay đổi đối với hình ảnh như
      • thẻ hiện có -> sau đó khởi động lại container từng người một
      • mới phiên bản tag -> thay thế vài container với thẻ mới -> Validate -> di chuyển tất cả các container để thẻ mới

Thêm vào đó, các hình ảnh cơ bản có thể được nâng cấp/container với một hình ảnh cơ sở mới hoàn toàn có thể được xây dựng tại tôi thường xuyên ntervals, như nhà duy trì cảm thấy cần thiết

Ưu

  1. Chúng tôi đang duy trì các phiên bản cũ của hình ảnh khi tạo hình ảnh an ninh vá mới, vì thế chúng ta có thể rollback đến hình ảnh chạy trước nếu cần thiết
  2. Chúng tôi đang bảo quản bộ nhớ đệm của docker, do đó ít chuyển mạng hơn (chỉ có lớp đã thay đổi mới được nối dây)
  3. Quy trình nâng cấp có thể được xác thực trong dàn dựng trước khi chuyển sang sản xuất
  4. Đây có thể là một quá trình được kiểm soát, do đó các bản vá bảo mật chỉ khi cần thiết/coi là quan trọng có thể được đẩy.
+0

Trên môi trường sản xuất, mặc dù chúng là bản cập nhật bảo mật, tôi nghi ngờ bạn sẽ muốn có cập nhật không cần giám sát! Nếu có bản cập nhật không cần giám sát là cần thiết, quá trình có thể chạy theo khoảng thời gian đều đặn (nếu thích hợp) như một công việc định kỳ. – Phani

+1

Tiền đề của tôi là bản cập nhật bảo mật phải đến từ hình ảnh gốc/cơ sở. – hbogert

+0

@hbogert Tôi thà nói rằng có một dòng phân biệt giữa lý thuyết và thực hành. Khi mọi thứ đi vào thực tế, sẽ có nhiều khía cạnh bên ngoài cần phải được đưa vào tài khoản, như: chi phí (không chỉ giá trị đồng đô la, mà còn thời gian) liên quan đến việc thực hiện. – Phani

3

Một cách tiếp cận khác có thể giả định rằng hình ảnh cơ sở của bạn bị chậm hơn rất nhiều (và điều đó rất có thể xảy ra) và buộc xây dựng hình ảnh khác theo định kỳ (ví dụ: mỗi tuần) và sau đó triển khai lại nếu nó đã thay đổi. Theo như tôi có thể nói, các hình ảnh phổ biến như Debian hoặc Java cập nhật các thẻ của chúng để phục vụ cho các bản sửa lỗi bảo mật, vì vậy các thẻ không thay đổi (nếu bạn muốn đảm bảo rằng bạn cần sử dụng tài liệu tham khảo hơn nữa [sửa] image: @digest], có sẵn trong các phiên bản Docker mới hơn). Do đó, nếu bạn xây dựng hình ảnh của mình với docker build --pull, thì ứng dụng của bạn sẽ nhận được thẻ hình ảnh cơ bản mới nhất và tuyệt vời nhất mà bạn đang tham chiếu.

Vì thẻ có thể thay đổi có thể gây nhầm lẫn, tốt nhất bạn nên tăng số phiên bản của ứng dụng mỗi khi bạn làm điều này sao cho ít nhất mọi thứ bên trong bạn sạch hơn. Vì vậy, tôi không chắc chắn rằng kịch bản được đề xuất trong một trong các câu trả lời trước đó có tác dụng hay không, vì nó không xây dựng lại hình ảnh của ứng dụng - nó chỉ cập nhật thẻ hình ảnh cơ sở và sau đó khởi động lại vùng chứa, nhưng vùng chứa mới vẫn tham chiếu đến băm hình ảnh cơ sở cũ.

Tôi không ủng hộ việc chạy các công việc kiểu cron trong container (hoặc bất kỳ quy trình nào khác, trừ khi thực sự cần thiết) vì điều này đi ngược lại câu thần chú chỉ chạy một tiến trình cho mỗi thùng chứa (có nhiều lý do khác nhau , vì vậy tôi sẽ không đi vào nó ở đây).

3

Tôi sẽ không đi sâu vào toàn bộ câu hỏi liệu bạn có muốn cập nhật không giám sát trong sản xuất (tôi nghĩ là không). Tôi chỉ để lại đây để tham khảo trong trường hợp ai tìm thấy nó hữu ích. Cập nhật tất cả các hình ảnh Docker bạn lên phiên bản mới nhất với các lệnh sau trong terminal của bạn:

# docker images | awk '(NR>1) && ($2!~/none/) {print $1":"$2}' | xargs -L1 docker pull

+0

Lệnh này hữu ích cho việc cập nhật tất cả các hình ảnh, nhưng nó không thay đổi bất kỳ thứ gì đang chạy trong sản xuất. Các thùng chứa vẫn xuất phát từ các hình ảnh cũ, hiện chưa được gắn thẻ. –

12

A 'cách Docker' sẽ được sử dụng docker hubautomated builds. Tính năng Repository Links sẽ xây dựng lại vùng chứa của bạn khi vùng chứa thượng lưu được xây dựng lại và tính năng Webhooks sẽ gửi cho bạn thông báo.

Dường như các webhook bị giới hạn đối với các cuộc gọi HTTP POST. Bạn cần thiết lập một dịch vụ để bắt chúng hoặc có thể sử dụng một trong các POST để gửi các dịch vụ qua email.

Tôi chưa xem xét, nhưng Docker Universal Control Plane mới có thể có một tính năng để phát hiện các vùng chứa được cập nhật và triển khai lại.

+0

Tôi phải xây dựng một webhook cho dịch vụ AMQP: https://github.com/goliatone/rabbithook – goliatone

3

Quản lý phụ thuộc cho hình ảnh Docker là một vấn đề thực sự. Tôi là thành viên của nhóm xây dựng công cụ, MicroBadger, để trợ giúp việc này bằng cách theo dõi hình ảnh vùng chứa và kiểm tra siêu dữ liệu. Một trong những tính năng của nó là cho phép bạn thiết lập webhook thông báo được gọi khi hình ảnh bạn quan tâm (ví dụ: hình ảnh cơ sở) thay đổi.

6

Bạn có thể sử dụng Watchtower để xem các bản cập nhật cho hình ảnh mà vùng chứa được khởi tạo và tự động kéo cập nhật và khởi động lại vùng chứa bằng hình ảnh được cập nhật. Tuy nhiên, điều đó không giải quyết được vấn đề xây dựng lại hình ảnh tùy chỉnh của riêng bạn khi có thay đổi đối với hình ảnh ngược dòng dựa trên đó. Bạn có thể xem vấn đề này như một vấn đề gồm hai phần: (1) biết khi nào một hình ảnh ngược dòng đã được cập nhật và (2) thực hiện việc xây dựng lại hình ảnh thực tế. (1) có thể được giải quyết khá dễ dàng, nhưng (2) phụ thuộc rất nhiều vào môi trường xây dựng địa phương/thực hành của bạn, vì vậy nó có thể khó khăn hơn nhiều để tạo ra một giải pháp tổng quát cho điều đó.

Nếu bạn có thể sử dụng automated builds của Docker Hub, toàn bộ vấn đề có thể được giải quyết một cách tương đối rõ ràng bằng cách sử dụng tính năng repository links, cho phép bạn kích hoạt tự động xây dựng lại khi một kho lưu trữ được liên kết (có thể là cập nhật). Bạn cũng có thể định cấu hình webhook để thông báo cho bạn khi xây dựng tự động xảy ra. Nếu bạn muốn nhận thông báo qua email hoặc SMS, bạn có thể kết nối webhook với số IFTTT Maker. Tôi thấy giao diện người dùng IFTTT là loại khó hiểu, nhưng bạn sẽ định cấu hình weber của Docker để đăng lên https://maker.ifttt.com/trigger/docker_xyz_image_built/với/key/your_key.

Nếu bạn cần xây dựng cục bộ, ít nhất bạn có thể giải quyết vấn đề nhận thông báo khi hình ảnh ngược dòng được cập nhật bằng cách tạo repo giả trong Hub Docker được liên kết với repo (s) bạn quan tâm. Mục đích duy nhất của repo giả sẽ là kích hoạt một webhook khi nó được xây dựng lại (có nghĩa là một trong những Repos liên kết của nó đã được cập nhật). Nếu bạn có thể nhận được webhook này, bạn thậm chí có thể sử dụng nó để kích hoạt xây dựng lại bên cạnh bạn.

+0

Tháp canh sử dụng đế cắm docker. Từ quan điểm bảo mật cho phép truy cập root vào máy chủ. – JoeG

3

Có rất nhiều câu trả lời ở đây, nhưng không có câu trả lời nào phù hợp với nhu cầu của tôi. Tôi muốn có câu trả lời thực sự cho câu hỏi số 1 của người hỏi. Làm cách nào để biết khi nào một hình ảnh được cập nhật trên hub.docker.com?

Tập lệnh dưới đây có thể chạy hàng ngày.Trong lần chạy đầu tiên, nó nhận được đường cơ sở của các thẻ và cập nhật ngày tháng từ sổ đăng ký HUB và lưu chúng cục bộ. Từ đó ra, mỗi lần nó chạy nó sẽ kiểm tra sổ đăng ký cho các thẻ mới và cập nhật ngày tháng. Vì điều này thay đổi mỗi lần một hình ảnh mới tồn tại, nó cho chúng ta biết nếu hình ảnh cơ sở đã thay đổi. Đây là kịch bản:

#!/bin/bash 

DATAPATH='/data/docker/updater/data' 

if [ ! -d "${DATAPATH}" ]; then 
     mkdir "${DATAPATH}"; 
fi 
IMAGES=$(docker ps --format "{{.Image}}") 
for IMAGE in $IMAGES; do 
     ORIGIMAGE=${IMAGE} 
     if [[ "$IMAGE" != *\/* ]]; then 
       IMAGE=library/${IMAGE} 
     fi 
     IMAGE=${IMAGE%%:*} 
     echo "Checking ${IMAGE}" 
     PARSED=${IMAGE//\//.} 
     if [ ! -f "${DATAPATH}/${PARSED}" ]; then 
       # File doesn't exist yet, make baseline 
       echo "Setting baseline for ${IMAGE}" 
       curl -s "https://registry.hub.docker.com/v2/repositories/${IMAGE}/tags/" > "${DATAPATH}/${PARSED}" 
     else 
       # File does exist, do a compare 
       NEW=$(curl -s "https://registry.hub.docker.com/v2/repositories/${IMAGE}/tags/") 
       OLD=$(cat "${DATAPATH}/${PARSED}") 
       if [[ "${VAR1}" == "${VAR2}" ]]; then 
         echo "Image ${IMAGE} is up to date"; 
       else 
         echo ${NEW} > "${DATAPATH}/${PARSED}" 
         echo "Image ${IMAGE} needs to be updated"; 
         H=`hostname` 
         ssh -i /data/keys/<KEYFILE> <USER>@<REMOTEHOST>.com "{ echo \"MAIL FROM: [email protected]${H}\"; echo \"RCPT TO: <USER>@<EMAILHOST>.com\"; echo \"DATA\"; echo \"Subject: ${H} - ${IMAGE} needs update\"; echo \"\"; echo -e \"\n${IMAGE} needs update.\n\ndocker pull ${ORIGIMAGE}\"; echo \"\"; echo \".\"; echo \"quit\"; sleep 1; } | telnet <SMTPHOST> 25" 
       fi 

     fi 
done; 

Bạn sẽ muốn thay đổi biến DATAPATH ở phía trên, và thay đổi các lệnh thông báo email ở cuối để phù hợp với nhu cầu của bạn. Đối với tôi, tôi có nó SSH vào một máy chủ trên mạng khác nơi SMTP của tôi nằm. Nhưng bạn cũng có thể dễ dàng sử dụng lệnh mail.

Bây giờ, bạn cũng muốn kiểm tra các gói được cập nhật bên trong các vùng chứa. Điều này thực sự có thể hiệu quả hơn là thực hiện "kéo" khi các thùng chứa của bạn đang hoạt động. Dưới đây là tập lệnh để kéo tính năng đó ra:

#!/bin/bash 


function needsUpdates() { 
     RESULT=$(docker exec ${1} bash -c ' \ 
       if [[ -f /etc/apt/sources.list ]]; then \ 
       grep security /etc/apt/sources.list > /tmp/security.list; \ 
       apt-get update > /dev/null; \ 
       apt-get upgrade -oDir::Etc::Sourcelist=/tmp/security.list -s; \ 
       fi; \ 
       ') 
     RESULT=$(echo $RESULT) 
     GOODRESULT="Reading package lists... Building dependency tree... Reading state information... Calculating upgrade... 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded." 
     if [[ "${RESULT}" != "" ]] && [[ "${RESULT}" != "${GOODRESULT}" ]]; then 
       return 0 
     else 
       return 1 
     fi 
} 

function sendEmail() { 
     echo "Container ${1} needs security updates"; 
     H=`hostname` 
     ssh -i /data/keys/<KEYFILE> <USRER>@<REMOTEHOST>.com "{ echo \"MAIL FROM: [email protected]${H}\"; echo \"RCPT TO: <USER>@<EMAILHOST>.com\"; echo \"DATA\"; echo \"Subject: ${H} - ${1} container needs security update\"; echo \"\"; echo -e \"\n${1} container needs update.\n\n\"; echo -e \"docker exec ${1} bash -c 'grep security /etc/apt/sources.list > /tmp/security.list; apt-get update > /dev/null; apt-get upgrade -oDir::Etc::Sourcelist=/tmp/security.list -s'\n\n\"; echo \"Remove the -s to run the update\"; echo \"\"; echo \".\"; echo \"quit\"; sleep 1; } | telnet <SMTPHOST> 25" 
} 

CONTAINERS=$(docker ps --format "{{.Names}}") 
for CONTAINER in $CONTAINERS; do 
     echo "Checking ${CONTAINER}" 
     if needsUpdates $CONTAINER; then 
       sendEmail $CONTAINER 
     fi 
done 
+0

mkdir trong tập lệnh đầu tiên có thể là: mkdir -p Ngoài ra, tập lệnh đầu tiên so sánh VAR1 với VAR2, giả sử rằng nên so sánh OLD với NEW. Nếu đúng, mặc dù điều này có nghĩa rằng tập lệnh này sẽ không thực sự làm những gì OP muốn, không bao giờ nó được chạy đầu tiên tại thời điểm cài đặt. Đó là, nó không thực sự xác định bất cứ điều gì về những gì được cài đặt, chỉ khi kết quả khác với lần chạy trước đó ... – JoeG

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