Cách tự động cập nhật các thùng chứa docker của bạn, nếu hình ảnh cơ sở được cập nhật


205

Nói rằng tôi có một container 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.

  1. Làm thế nào tôi biết hình ảnh địa phương của tôi và container của nó đang chạy phía sau?

  2. Có một số cách tốt nhất để tự động cập nhật hình ảnh và bộ chứa cục bộ để theo dõi các bản cập nhật repo của docker, trong thực tế sẽ cung cấp cho bạn các đặc điểm tương tự của việc nâng cấp không giám sát chạy trên máy ub Ubuntu thông thường


11
Tôi đang tìm kiếm một câu trả lời cho điều này kể từ khi bắt đầu 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 cơ sở sẽ không thay đổi, vì tôi đã cài đặt nó sau đó. Tôi vẫn muốn có bản cập nhật tự động cho apache. Tôi thực sự đã hỏi trong IRC về điều này và nhận được "theo dõi ngược dòng và xây dựng lại các bản cập nhật" như một câu trả lời ...
Mathias

8
Vui mừng tôi không phải là người duy nhất tự hỏi. Dường như sự phát triển và khả năng tái tạo là quan trọng đố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

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ó vấn đề khác docker không giải quyết như đăng nhập.
Mathias

3
Cảm ơn mọi người đã trả lời. Tôi xin lỗi tôi không thể chia tiền thưởng. Mặc dù không có giải pháp cuối cùng cho vấn đề của tôi, nhưng vẫn có đầu vào tốt từ tất cả các bạn.
Mathias

1
Đối với @Mathias, giải pháp tôi vừa thêm có một tập lệnh sẽ kiểm tra các bản cập nhật bảo mật cho các gói được cài đặt trong thùng kéo sau. Nó cũng có một kịch bản riêng để kiểm tra hình ảnh cơ sở.
Fmstrat

Câu trả lời:


8

Một trong những cách để làm điều đó là lái nó qua hệ thống CI / CD của bạn. Khi hình ảnh cha mẹ của bạn được xây dựng, có một cái gì đó quét repos git của bạn cho hình ảnh bằng cách sử dụng cha mẹ đó. Nếu được tìm thấy, sau đó bạn sẽ gửi yêu cầu kéo để chuyển sang các phiên bản mới của hình ảnh. Yêu cầu kéo, nếu tất cả các bài kiểm tra vượt qua, sẽ được hợp nhất và bạn sẽ có một hình ảnh con mới dựa trên cha mẹ được cập nhật. Một ví dụ về một công cụ thực hiện phương pháp này có thể được tìm thấy ở đây: https://engineering.salesforce.com/open-source-dockerfile-image-update-6400121c1a75 .

Nếu bạn không kiểm soát hình ảnh cha mẹ của mình, như trường hợp của bạn phụ thuộc vào ubuntuhình ảnh chính thức , bạn có thể viết một số công cụ phát hiện các thay đổi trong thẻ hình ảnh cha mẹ hoặc tổng kiểm tra (không phải điều tương tự, các thẻ có thể thay đổi) và gọi hình ảnh trẻ em xây dựng cho phù hợp.


Wow đây là một cái búa lớn, cho biết: kể từ khi tôi hỏi câu hỏi này, tôi cũng đã nhận ra rằng máy chủ xây dựng là nơi để giải quyết vấn đề này. Tôi rất vui khi thấy một số dụng cụ. Nếu bạn giải thích cách tiếp cận của bạn trong các khái niệm chung (và không phải là công cụ / triển khai chính xác của bạn) và đưa nó vào câu trả lời thì có lẽ tôi sẽ chấp nhận nó.
hbogert

Cảm ơn @hbogert Tôi đã chỉnh sửa phần trên và cũng bao gồm một ý tưởng về những việc cần làm nếu bạn đang xử lý các hình ảnh công khai
Ma3oxuct

123

Chúng tôi sử dụng một tập lệnh để kiểm tra xem một container đang chạy có được bắt đầu với hình ảnh mới nhất không. Chúng tôi cũng sử dụng các tập lệnh init mới bắt đầu để 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 có giá trị này. Đây có vẻ là một cách tốt để 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 bản phân phối trong dockerfile? Hoặc bạn chỉ sử dụng hình ảnh cơ bản làm sẵn chỉ cần mã ứng dụng của bạn (như một trang web)?
Mathias

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

@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 mà tôi đang sử dụng để cập nhật linux (hiện debian / ubuntu) gói trong tất cả các container chạy.
iTech

3
Nếu một hình ảnh có cùng tên với một container (ví dụ redis), LATEST=`docker inspect --format "{{.Id}}" $IMAGE`sẽ nhận được thông tin về container. Thêm --type imageđể sửa lỗi này.
Patrick Fisher

1
Cảm ơn bài viết của bạn. Tôi đã sửa đổi nó để bọc toàn bộ bên trong một vòng lặp để có được hình ảnh từ docker: for IMAGE in $(docker ps --format {{.Image}} -q | sort -u)
Armand

25

Một "cách docker" sẽ là sử dụng các bản dựng tự động của docker hub . Các Repository Liên kết tính năng sẽ xây dựng lại container của bạn khi một container thượng nguồn được xây dựng lại, và Webhooks Tính năng này sẽ gửi cho bạn một thông báo.

Có vẻ như các webhooks bị giới hạn trong 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 email các dịch vụ ngoài đó.

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


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

Đáng buồn thay, kích hoạt ngược dòng không còn có sẵn: github.com/docker/hub-feedback/issues/1717 .
Julien Chastang

22

Bạn có thể sử dụng Tháp Canh để xem các bản cập nhật cho hình ảnh mà một bộ chứa được khởi tạo từ đó và tự động kéo bản cập nhật và khởi động lại bộ 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ó sự thay đổi đối với hình ảnh ngược dòng mà nó dựa trên. Bạn có thể xem đây là 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 / thực tiễn xây dựng tại địa phương của bạn, vì vậy có lẽ khó 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 các bản dựng tự động của Docker Hub , toàn bộ vấn đề có thể được giải quyết tương đối sạch sẽ bằng tính năng liên kết kho lưu trữ , cho phép bạn kích hoạt xây dựng lại tự động khi kho lưu trữ được liên kết (có thể là một kho lưu trữ ngược dòng) được cập nhật. Bạn cũng có thể định cấu hình một webhook để thông báo cho bạn khi quá trình xây dựng tự động xảy ra. Nếu bạn muốn có email hoặc thông báo SMS, bạn có thể kết nối webhook với IFTTT Maker . Tôi thấy giao diện người dùng IFTTT khá khó hiểu, nhưng bạn sẽ định cấu hình webhook Docker để đăng lên https://maker.ifttt.com/trigger/docker_xyz_image_built / with / 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 một repo giả trong Docker Hub được liên kết với (các) sở thích của bạn. 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 (ngụ ý một trong những repos được liên kết của nó đã được cập nhật). Nếu bạn có thể nhận webhook này, bạn thậm chí có thể sử dụng nó để kích hoạt xây dựng lại về phía bạn.


1
Tháp canh sử dụng ổ cắm docker mặc dù. Từ góc độ bảo mật đang cho phép truy cập root vào máy chủ.
JoeG

1
Ngoài ra, Watchtower dường như không thể cập nhật hình ảnh từ các kho riêng tư ngoài Docker Hub. Một người lập dị cho chúng tôi, những người sử dụng Azure.
Thomas Eyde

1
Bạn có thể sử dụng đăng ký riêng bằng cách sử dụng REPO_USERREPO_PASScác biến môi trường. Hãy xem readme.md từ Watchtower để biết thêm thông tin: github.com/v2tec/watchtower#usage
Alejandro Nortes

2
Lời cảnh báo, tháp canh bị người bảo trì bỏ rơi và hình ảnh trong DockerHub thậm chí không cập nhật với hình ảnh trong github.
XanderStrike

Repo của Tháp Canh dường như đã được di chuyển sang chứarrr / tháp canh . Và có một số vấn đề với các bản dựng tự động được liên kết trên Dockerhub, như được chỉ ra bởi câu trả lời này cho một câu hỏi tương tự .
chrki

10

Tôi đã có cùng một vấn đề và nghĩ rằng nó có thể được giải quyết đơn giản bằng một công việc định kỳ gọi unattended-upgradehàng ngày.

Ý định của tôi là có một giải pháp tự động và nhanh chóng để đảm bảo rằng thùng chứa sản xuất được bảo mật và cập nhật vì đôi khi tôi có thể cập nhật hình ảnh của mình và triển khai hình ảnh docker mới với các cập nhật bảo mật mới nhất.

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

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

Tôi cũng đã gặp một cách tiếp cận khác để kiểm tra xem container có cần cập nhật hay không.

Thực hiện đầy đủ 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

Kịch bản trợ giúp

Tải về

#!/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"]

khởi đầu

#!/bin/bash

set -e

echo "Adding crontab for unattended-upgrade ..."
echo "0 0 * * * root /usr/bin/unattended-upgrade" >> /etc/crontab

# can also use @daily syntax or use /etc/cron.daily

echo "Starting supervisord ..."
exec /usr/bin/supervisord -n -c /etc/supervisor/supervisord.conf

Biên tập

Tôi đã phát triển một công cụ docker-run nhỏ chạy như container docker và có thể được sử dụng để cập nhật các gói bên trong tất cả hoặc các container đang chạy, 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 thi datelệnh trong tất cả các container đang chạy và hiển thị kết quả. Nếu bạn vượt qua updatethay vì execnó sẽ thực thi apt-get updatetheo sau apt-get upgrade -ytrong tất cả các container đang chạy


tài liệu tham khảo của tôi về nâng cấp không giám sát chỉ để hiển thị sự tương tự trong môi trường không có docker. Mục đích của tôi là giải quyết điều này theo cách docker (nếu điều đó tồn tại oc.) Có một quá trình bổ sung trong một container chứa mục đích của docker imo. Nó khắc phục vấn đề về độ trễ giữa việc cập nhật ngược dòng hình ảnh của họ và bạn, người dùng, thực sự làm mất 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 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 rất nhiều vào hệ điều hành máy chủ.
hbogert

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

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

1
Bạn có thể cần một cái gì đó ở cấp độ cao hơn docker, chẳng hạn như Kuberneteshữu ích cho việc triển khai cơ sở hạ tầng lớn, nhưng nó vẫn đang được Google phát triển mạnh. Hiện tại, bạn có thể tự động hóa việc này bằng một công cụ cung cấp như Ansible theo cách khá đơn giản.
iTech

Trích dẫn "cách tiếp cận khác nhau" của bạn có thể là những gì tôi đang tìm kiếm. Đóng góp của riêng bạn trông giống như một sự thay thế khả thi cho "thùng chứa chất béo". Tôi chắc chắn sẽ xem xét cả hai một chút nữa, cảm ơn câu trả lời của bạn.
Mathias

7

Bạn sẽ không biết container của bạn ở phía sau mà không chạy docker pull . Sau đó, bạn cần phải xây dựng lại hoặc sắp xếp lại hình ảnh của bạn.

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 một tập lệnh cùng với bất kỳ thứ gì khác cần thiết để hoàn thành nâng cấp, mặc dù một thùng chứa thích hợp sẽ không cần thêm gì.


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

Xin vui lòng chờ trước khi bạn chấp nhận. Có lẽ có một cái gì đó ra khỏi đó. Tôi đã sử dụng docker được 6 tháng, nhưng không theo kịp những phát triển mới nhất.
seanmcl

Bằng cách nào đó, bên trong, Docker có thể so sánh các hình ảnh để thực hiện khả năng 'lưu trữ' của nó. Có lẽ bạn có thể tìm ra một cách để tận dụng RATNG. Nói cách khác, kiểm tra xem các hình ảnh bên dưới (tất cả các cách quay lại cơ sở) đã thay đổi và sau đó kích hoạt một quy 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ơ sở đã thay đổi.
Thom Parkin

5

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 một nhóm đã xây dựng một công cụ, MicroBadger , để giúp giải quyết vấn đề này bằng cách giám sát hình ảnh container 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 một webhook thông báo được gọi khi một hình ảnh bạn quan tâm (ví dụ: hình ảnh cơ sở) thay đổi.


5

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ó một 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 hình ảnh được cập nhật trên hub.docker.com?

Kịch bản dưới đây có thể được chạy hàng ngày. Trong lần chạy đầu tiên, nó nhận được một đường cơ sở của các thẻ và ngày cập nhật từ sổ đăng ký HUB và lưu chúng cục bộ. Từ đó trở đi, mỗi khi chạy, nó sẽ kiểm tra sổ đăng ký để tìm thẻ mới và ngày cập nhật. Vì điều này thay đổi mỗi khi 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: root@${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 DATAPATHbiến ở trên cùng và thay đổi 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ó SSH vào một máy chủ trên một mạng khác nơi đặt SMTP của tôi. Nhưng bạn có thể dễ dàng sử dụngmail lệnh.

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

#!/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: root@${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

1
mkdir trong tập lệnh đầu tiên có lẽ phải 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 MỚI. Nếu đúng, điều này có nghĩa là tập lệnh này sẽ không thực sự làm những gì OP muốn, KHÔNG GIỚI HẠN nó được chạy lần đầ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 các lần chạy trước ...
JoeG

5

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 lại khá nhanh (và điều đó rất có thể xảy ra) và buộc xây dựng hình ảnh khác cho ứng dụng của bạn 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 cơ bản phổ biến như Debian hoặc Java chính thức cập nhật các thẻ của chúng để phục vụ cho việc sửa lỗi bảo mật, vì vậy các thẻ không phải là bất biến (nếu bạn muốn đảm bảo chắc chắn hơn rằng bạn cần sử dụng tham chiếu [image: @digest ], có sẵn trong các phiên bản Docker gần đây hơn). Do đó, nếu bạn định xây dựng hình ảnh của mình docker build --pull, thì ứng dụng của bạn sẽ nhận được thẻ hình ảnh cơ sở mới nhất và lớn nhất mà bạn đang tham khảo.

Vì các thẻ có thể thay đổi có thể gây nhầm lẫn, tốt nhất nên tăng số phiên bản của ứng dụng của bạn mỗi khi bạn làm điều này để ít nhất là về phía bạn mọi thứ sạch sẽ hơn.

Vì vậy, tôi không chắc rằng tập lệnh được đề xuất trong một trong các câu trả lời trước đó thực hiện công việc, vì nó không xây dựng lại hình ảnh của ứng dụng của bạn - nó chỉ cập nhật thẻ hình ảnh cơ bản và sau đó nó khởi động lại bộ chứa, nhưng bộ chứa mới vẫn tham chiếu băm hình ảnh cơ sở cũ.

Tôi sẽ không ủng hộ việc chạy các công việc kiểu cron trong các thùng chứa (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 với câu thần chú chỉ chạy một quy trình trên mỗi container (có nhiều lý lẽ về lý do tại sao điều này tốt hơn, vì vậy tôi m sẽ không đi vào đây).


4

Tôi sẽ không đi 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 hay không (tôi nghĩ là không). Tôi chỉ để lại ở đây để tham khảo trong trường hợp bất cứ ai thấy nó hữu ích. Cập nhật tất cả hình ảnh docker của bạn lên phiên bản mới nhất bằng lệnh sau trong thiết bị đầu cuối của bạn:

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


1
Lệnh này hữu ích để cập nhật tất cả các hình ảnh, nhưng nó không thay đổi bất cứ điều gì đang chạy trong sản xuất. Các container vẫn xuất phát từ những hình ảnh cũ, hiện chưa được xử lý.
Không có

Thật. Và đây là một trong những cuốn sách nữa ... Sử dụng # docker system prune -a --volumes -fđể dọn dẹp những hình ảnh, khối lượng cũ (lủng lẳng), v.v.
Meferdati

4

CẬP NHẬT: Sử dụng Dependabot - https://dependabot.com/docker/

BLUF: tìm kiếm điểm chèn phù hợp để theo dõi các thay đổi đối với một container là thách thức. Sẽ thật tuyệt nếu DockerHub sẽ giải quyết điều này. (Liên kết kho lưu trữ đã được đề cập nhưng lưu ý khi thiết lập chúng trên DockerHub - "Kích hoạt bản dựng trong kho lưu trữ này bất cứ khi nào hình ảnh cơ sở được cập nhật trên Docker Hub. Chỉ hoạt động đối với hình ảnh không chính thức." )

Trong khi cố gắng tự giải quyết vấn đề này, tôi đã thấy một số đề xuất cho webhooks vì vậy tôi muốn giải thích một vài giải pháp tôi đã sử dụng.

  1. Sử dụng microbadger.com để theo dõi các thay đổi trong vùng chứa và sử dụng tính năng webhook thông báo của nó để kích hoạt một hành động. Tôi đã thiết lập điều này với zapier.com (nhưng bạn có thể sử dụng bất kỳ dịch vụ webhook tùy chỉnh nào) để tạo một vấn đề mới trong kho github của tôi sử dụng Alpine làm hình ảnh cơ bản.

    • Ưu điểm: Bạn có thể xem lại các thay đổi được báo cáo bởi microbadger trong github trước khi thực hiện hành động.
    • Nhược điểm: Microbadger không cho phép bạn theo dõi một thẻ cụ thể. Có vẻ như nó chỉ theo dõi 'mới nhất'.
  2. Theo dõi nguồn cấp RSS cho git cam kết với một container ngược dòng. Ví dụ. https://github.com/gliderlabs/docker-alpine/commits/rootfs/l Library-3,8 / x86_64 . Tôi đã sử dụng zapier.com để theo dõi nguồn cấp dữ liệu này và để kích hoạt bản dựng tự động của bộ chứa trong Travis-CI bất cứ khi nào có gì đó được cam kết. Đây là một chút cực đoan nhưng bạn có thể thay đổi kích hoạt để làm những việc khác như mở một vấn đề trong kho git của bạn để can thiệp thủ công.

    • Ưu điểm: Gần hơn với một đường ống tự động. Bản dựng Travis-CI chỉ kiểm tra xem liệu thùng chứa của bạn có vấn đề với bất cứ điều gì đã được cam kết với kho lưu trữ hình ảnh cơ sở hay không. Tùy thuộc vào bạn nếu dịch vụ CI của bạn thực hiện thêm bất kỳ hành động nào.
    • Nhược điểm: Theo dõi nguồn cấp dữ liệu cam kết không hoàn hảo. Rất nhiều thứ được cam kết với kho lưu trữ không ảnh hưởng đến việc xây dựng hình ảnh cơ sở. Không tính đến bất kỳ vấn đề nào với tần suất / số lần xác nhận và bất kỳ điều chỉnh API nào.

3

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

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

Tiếp cận

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

Ngoài ra, hình ảnh cơ sở có thể được nâng cấp / thùng chứa với hình ảnh cơ sở hoàn toàn mới có thể được xây dựng theo định kỳ, vì người bảo trì cảm thấy cần thiết

Ưu điểm

  1. Chúng tôi đang bảo tồn phiên bản cũ của hình ảnh trong khi tạo hình ảnh vá bảo mật mới, do đó chúng tôi có thể quay lại hình ảnh đang chạy trước đó nếu cần thiết
  2. Chúng tôi đang bảo quản bộ đệm docker, do đó truyền mạng ít hơn (chỉ có lớp thay đổi được lên dây)
  3. Quá trình nâng cấp có thể được xác nhận trong dàn dựng trước khi chuyển sang prod
  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 / được coi là quan trọng.

Trên môi trường sản xuất, mặc dù chúng là các cập nhật bảo mật, tôi nghi ngờ bạn sẽ muốn có các cập nhật không giám sát! Nếu có các cập nhật không giám sát là cần thiết, quy trình có thể được chạy theo các 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à các cập nhật bảo mật nên đến từ hình ảnh ngược dòng / cơ sở.
hbogert

@hbogert Tôi muốn nói có một sự khác biệt tố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 được tính đến, như: chi phí (không chỉ giá trị đồng đô la, mà còn cả thời gian) liên quan đến việc thực hiện.
Phani

3

Câu trả lời trên cũng đúng

Có hai cách tiếp cận

  1. Sử dụng webhooks
  2. Chạy tập lệnh cho mỗi phút cụ thể để có được hình ảnh docker mới

Tôi chỉ chia sẻ kịch bản có thể nó sẽ hữu ích cho bạn! Bạn có thể sử dụng nó với cronjob, tôi đã thử thành công trên OSX

#!/bin/bash
##You can use below commented line for setting cron tab for running cron job and to store its O/P in one .txt file  
#* * * * * /usr/bin/sudo -u admin -i bash -c /Users/Swapnil/Documents/checkimg.sh > /Users/Swapnil/Documents/cron_output.log 2>&1
# Example for the Docker Hub V2 API
# Returns all images and tags associated with a Docker Hub organization account.
# Requires 'jq': https://stedolan.github.io/jq/

# set username, password, and organization
# Filepath where your docker-compose file is present
FILEPATH="/Users/Swapnil/Documents/lamp-alpine"
# Your Docker hub user name
UNAME="ur username"
# Your Docker hub user password
UPASS="ur pwd"
# e.g organisation_name/image_name:image_tag
ORG="ur org name"
IMGNAME="ur img name"
IMGTAG="ur img tag"
# Container name
CONTNAME="ur container name"
# Expected built mins
BUILDMINS="5"
#Generally cronjob frequency
CHECKTIME="5"
NETWORKNAME="${IMGNAME}_private-network"
#After Image pulling, need to bring up all docker services?
DO_DOCKER_COMPOSE_UP=true
# -------
echo "Eecuting Script @ date and time in YmdHMS: $(date +%Y%m%d%H%M%S)"
set -e
PIDFILE=/Users/Swapnil/Documents/$IMGNAME/forever.pid
if [ -f $PIDFILE ]
then
  PID=$(cat $PIDFILE)
  ps -p $PID > /dev/null 2>&1
  if [ $? -eq 0 ]
  then
    echo "Process already running"
    exit 1
  else
    ## Process not found assume not running
    echo $$
    echo $$ > $PIDFILE
    if [ $? -ne 0 ]
    then
      echo "Could not create PID file"
      exit 1
    fi
  fi
else
  echo $$ > $PIDFILE
  if [ $? -ne 0 ]
  then
    echo "Could not create PID file"
    exit 1
  fi
fi

# Check Docker is running or not; If not runing then exit
if docker info|grep Containers ; then
    echo "Docker is running"
else
    echo "Docker is not running"
    rm $PIDFILE
    exit 1
fi

# Check Container is running or not; and set variable
CONT_INFO=$(docker ps -f "name=$CONTNAME" --format "{{.Names}}")
if [ "$CONT_INFO" = "$CONTNAME" ]; then
    echo "Container is running"
    IS_CONTAINER_RUNNING=true
else
    echo "Container is not running"
    IS_CONTAINER_RUNNING=false
fi


# get token
echo "Retrieving token ..."
TOKEN=$(curl -s -H "Content-Type: application/json" -X POST -d '{"username": "'${UNAME}'", "password": "'${UPASS}'"}' https://hub.docker.com/v2/users/login/ | jq -r .token)

# get list of repositories
echo "Retrieving repository list ..."
REPO_LIST=$(curl -s -H "Authorization: JWT ${TOKEN}" https://hub.docker.com/v2/repositories/${ORG}/?page_size=100 | jq -r '.results|.[]|.name')

# output images & tags
echo "Images and tags for organization: ${ORG}"
echo
for i in ${REPO_LIST}
do
  echo "${i}:"
  # tags
  IMAGE_TAGS=$(curl -s -H "Authorization: JWT ${TOKEN}" https://hub.docker.com/v2/repositories/${ORG}/${i}/tags/?page_size=100 | jq -r '.results|.[]|.name')
  for j in ${IMAGE_TAGS}
  do
    echo "  - ${j}"
  done
  #echo
done

# Check Perticular image is the latest or not
#imm=$(curl -s -H "Authorization: JWT ${TOKEN}" https://hub.docker.com/v2/repositories/${ORG}/${IMGNAME}/tags/?page_size=100)
echo "-----------------"
echo "Last built date details about Image ${IMGNAME} : ${IMGTAG} for organization: ${ORG}"
IMAGE_UPDATED_DATE=$(curl -s -H "Authorization: JWT ${TOKEN}" https://hub.docker.com/v2/repositories/${ORG}/${IMGNAME}/tags/?page_size=100 | jq -r '.results|.[]|select(.name | contains("'${IMGTAG}'")).last_updated')
echo "On Docker Hub IMAGE_UPDATED_DATE---$IMAGE_UPDATED_DATE"
echo "-----------------"

IMAGE_CREATED_DATE=$(docker image inspect ${ORG}/${IMGNAME}:${IMGTAG} | jq -r '.[]|.Created')
echo "Locally IMAGE_CREATED_DATE---$IMAGE_CREATED_DATE"

updatedDate=$(date -jf '%Y-%m-%dT%H:%M' "${IMAGE_UPDATED_DATE:0:16}" +%Y%m%d%H%M%S) 
createdDate=$(date -jf '%Y-%m-%dT%H:%M' "${IMAGE_CREATED_DATE:0:16}" +%Y%m%d%H%M%S)
currentDate=$(date +%Y%m%d%H%M%S)

start_date=$(date -jf "%Y%m%d%H%M%S" "$currentDate" "+%s")
end_date=$(date -jf "%Y%m%d%H%M%S" "$updatedDate" "+%s")
updiffMins=$(( ($start_date - $end_date) / (60) ))
if [[ "$updiffMins" -lt $(($CHECKTIME+1)) ]]; then
        if [ ! -d "${FILEPATH}" ]; then
            mkdir "${FILEPATH}";
        fi
        cd "${FILEPATH}"
        pwd
        echo "updatedDate---$updatedDate" > "ScriptOutput_${currentDate}.txt"
        echo "createdDate---$createdDate" >> "ScriptOutput_${currentDate}.txt"
        echo "currentDate---$currentDate" >> "ScriptOutput_${currentDate}.txt"
        echo "Found after regular checking time -> Docker hub's latest updated image is new; Diff ${updiffMins} mins" >> "ScriptOutput_${currentDate}.txt"
        echo "Script is checking for latest updates after every ${CHECKTIME} mins" >> "ScriptOutput_${currentDate}.txt"
        echo "Fetching all new"
        echo "---------------------------"
        if $IS_CONTAINER_RUNNING ; then
            echo "Container is running"         
        else
            docker-compose down
            echo "Container stopped and removed; Network removed" >> "ScriptOutput_${currentDate}.txt"
        fi
        echo "Image_Created_Date=$currentDate" > ".env"
        echo "ORG=$ORG" >> ".env"
        echo "IMGNAME=$IMGNAME" >> ".env"
        echo "IMGTAG=$IMGTAG" >> ".env"
        echo "CONTNAME=$CONTNAME" >> ".env"
        echo "NETWORKNAME=$NETWORKNAME" >> ".env"
        docker-compose build --no-cache
        echo "Docker Compose built" >> "ScriptOutput_${currentDate}.txt"
        if $DO_DOCKER_COMPOSE_UP ; then
            docker-compose up -d
            echo "Docker services are up now, checked in" >> "ScriptOutput_${currentDate}.txt"  
        else
            echo "Docker services are down, checked in" >> "ScriptOutput_${currentDate}.txt"
        fi
elif [[ "$updatedDate" -gt "$createdDate" ]]; then 
    echo "Updated is latest"
    start_date=$(date -jf "%Y%m%d%H%M%S" "$updatedDate" "+%s")
    end_date=$(date -jf "%Y%m%d%H%M%S" "$createdDate" "+%s")
    diffMins=$(( ($start_date - $end_date) / (60) ))
    if [[ "$BUILDMINS" -lt "$diffMins" ]]; then
        if [ ! -d "${FILEPATH}" ]; then
            mkdir "${FILEPATH}";
        fi
        cd "${FILEPATH}"
        pwd
        echo "updatedDate---$updatedDate" > "ScriptOutput_${currentDate}.txt"
        echo "createdDate---$createdDate" >> "ScriptOutput_${currentDate}.txt"
        echo "currentDate---$currentDate" >> "ScriptOutput_${currentDate}.txt"
        echo "Found after comparing times -> Docker hub's latest updated image is new; Diff ${diffMins} mins" >> "ScriptOutput_${currentDate}.txt"
        echo "Actual image built time is less i.e. ${diffMins} mins than MAX expexted BUILD TIME i.e. ${BUILDMINS} mins" >> "ScriptOutput_${currentDate}.txt"
        echo "Fetching all new" >> "ScriptOutput_${currentDate}.txt"
        echo "-----------------------------"
        if $IS_CONTAINER_RUNNING ; then
            echo "Container is running"         
        else
            docker-compose down
            echo "Container stopped and removed; Network removed" >> "ScriptOutput_${currentDate}.txt"
        fi
        echo "Image_Created_Date=$currentDate" > ".env"
        echo "ORG=$ORG" >> ".env"
        echo "IMGNAME=$IMGNAME" >> ".env"
        echo "IMGTAG=$IMGTAG" >> ".env"
        echo "CONTNAME=$CONTNAME" >> ".env"
        echo "NETWORKNAME=$NETWORKNAME" >> ".env"
        docker-compose build --no-cache
        echo "Docker Compose built" >> "ScriptOutput_${currentDate}.txt"
        if $DO_DOCKER_COMPOSE_UP ; then
            docker-compose up -d
            echo "Docker services are up now" >> "ScriptOutput_${currentDate}.txt"  
        else
            echo "Docker services are down" >> "ScriptOutput_${currentDate}.txt"
        fi
    elif [[ "$BUILDMINS" -gt "$diffMins" ]]; then
        echo "Docker hub's latest updated image is NOT new; Diff ${diffMins} mins"
        echo "Docker images not fetched"
    else
        echo "Docker hub's latest updated image is NOT new; Diff ${diffMins} mins"
        echo "Docker images not fetched"
    fi
elif [[ "$createdDate" -gt "$updatedDate" ]]; then 
    echo "Created is latest"
    start_date=$(date -jf "%Y%m%d%H%M%S" "$createdDate" "+%s")
    end_date=$(date -jf "%Y%m%d%H%M%S" "$updatedDate" "+%s")
    echo "Docker hub has older docker image than local; Older than $(( ($start_date - $end_date) / (60) ))mins"
fi
echo 
echo "------------end---------------"
rm $PIDFILE

Đây là tập tin docker-compose của tôi

version:  "3.2"
services:
  lamp-alpine:
    build:
      context: .
    container_name: "${CONTNAME}"
    image: "${ORG}/${IMGNAME}:${IMGTAG}"
    ports:
      - "127.0.0.1:80:80"
    networks:
      - private-network 

networks:
  private-network:
    driver: bridge

3

Đây là cách đơn giản nhất để tự động cập nhật container docker

Đặt công việc qua $ crontab -e:

0 * * * * sh ~/.docker/cron.sh

Tạo thư mục ~/.dockervới tập tin cron.sh:

#!/bin/sh
if grep -Fqe "Image is up to date" << EOF
`docker pull ubuntu:latest`
EOF
then
    echo "no update, just do cleaning"
    docker system prune --force
else
    echo "newest exist, recompose!"
    cd /path/to/your/compose/file
    docker-compose down --volumes
    docker-compose up -d
fi

0

bạn đã thử cái này chưa: https://github.com/v2tec/watchtower . đó là một công cụ đơn giản chạy trong container docker xem các container khác, nếu hình ảnh cơ sở của chúng thay đổi, nó sẽ kéo và triển khai lại.


-1

Một giải pháp đơn giản và tuyệt vời là người chăn cừu


iiuc, điều này không giúp ích theo nghĩa chung, bởi vì điều này được kết hợp với Swarm và chỉ khởi động lại ngược dòng, trong khi chúng tôi muốn phản ứng, xây dựng lại, v.v. về những thay đổi ngược dòng và không chỉ đơn giản là khởi động lại.
hbogert

Nghe có vẻ giống như một việc bạn nên làm trong một đường ống CI
user672009
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.