使用 SSH 和 shell 腳本部署 Docker 鏡像

clipboard.png

譯者按:在本專欄的前面的文章中,咱們已經提到過使用 Docker 的基本方法,所以本次講解一下 使用 SSH 和 shell 腳本進行 Docker 鏡像的自動化部署,原文僅供參考,由於對於 Docker 鏡像,咱們能夠有更好的解決方案:Docker Registry Hub。可是,本文仍然能夠做爲 shell 腳本的參考範例。程序員

背景

當咱們將本站轉移到 Docker 容器內以後,我一直在尋求能進行自動化構建和部署鏡像的方法。毫無疑問,Docker 自己是一個很是完美的應用容器,可是 Docker 並無提供可以自動化更新鏡像的標準方法。固然,我寫了一些 shell 腳本,實現了 Docker 容器鏡像的自動化部署。web

咱們假設基礎架構是一臺 Linux 宿主機和幾個獨立的 Docker 鏡像,沒有網站運行時產生的動態文件,例如用戶上傳的文件。
固然,要解決這些動態文件也很是簡單,本篇文章中的腳本只須要修改一小部分,而後加上 data only container 即可以完美解決動態文件的問題。docker

那麼,咱們開始進行自動化部署吧。shell

腳本

腳本的初衷很是簡單:構建鏡像,上傳鏡像,使用新鏡像重啓容器。咱們會分段講解腳本,固然你只須要把本文的腳本段落組合起來,即可以執行自動化部署了。apache

假設咱們的 apache 文件在 apache/ 子目錄,一個監控程序在 monitoring/ 子目錄。bash

設置環境

假設咱們的腳本名稱爲 deploy.sh,使用以下命令進行初始化:服務器

#!/bin/bash

set -e

REMOTE_USERNAME="..."
REMOTE_HOST="..."
IMAGE_REPOSITORY="my_repository"

前面兩個變量並不須要解釋,後面上傳鏡像的時候用的到。
最後一個變量是 Docker 鏡像的名稱,你須要設置本身的鏡像名稱,在後面咱們也會有這個名稱進行檢測。架構

再後文中咱們會創建同一個名稱可是 tag 不一樣的兩個鏡像分別存儲 apache 和 monitor。ssh

構建

第一件要作的事情即是構建鏡像,構建過程和普通的 Docker 命令同樣。咱們寫了一個函數專門用來構建鏡像:函數

function build_image {
    docker build -t $IMAGE_REPOSITORY:$1 $2
}

build_image apache apache/
build_image monitoring monitoring/

咱們使用上面的已經定義的 IMAGE_REPOSITORY 名稱命名鏡像,而且對咱們的兩個 apache 和 monitoring 鏡像貼標籤。

上傳

固然本專欄的前文中提到,鏡像能夠輸出到文件,也能夠由文件輸入。固然也能夠從標準輸入輸出流進行輸入輸出。咱們使用標準輸入輸出流和管道進行操做。這個輸入和上傳的操做很容易用一行 shell 語句寫出來。

docker save $IMAGE_REPOSITORY:$1 | bzip2 | pv | ssh $REMOTE_USERNAME@$REMOTE_HOST 'bunzip2 | docker load'

固然,成熟的程序員都會寫個函數,順便作作重複性檢測,畢竟幾百 M 的文件呢,上傳都要很久,還能節省帶寬。尤爲是有不少鏡像須要上傳的時候,萬一有幾個重複的呢。咱們所須要的就是按照鏡像名稱和標籤列出本機和遠程服務器上的 Docker 容器的 ID,而後檢測他們的 ID 是否相同。

本節的 shell 腳本以下。

function upload_image_if_needed {
    if [[ $(ssh $REMOTE_USERNAME@$REMOTE_HOST "docker images $IMAGE_REPOSITORY | grep $1 | tr -s ' ' | cut -d ' ' -f 3") != $(docker images $IMAGE_REPOSITORY | grep $1 | tr -s ' ' | cut -d ' ' -f 3) ]]
    then
        echo "$1 image changed, updating..."
        docker save $IMAGE_REPOSITORY:$1 | bzip2 | pv | ssh $REMOTE_USERNAME@$REMOTE_HOST 'bunzip2 | docker load'
    else
        echo "$1 image did not change"
    fi
}

upload_image_if_needed apache
upload_image_if_needed monitoring

更新容器

上面說的是更新鏡像,本節講的是更新容器。
如今是最後一步,咱們須要使用新鏡像重啓容器。固然,和其餘的語言同樣,咱們能夠將遠程主機上的命令寫成本機上的輸入形式:

ssh -tt $REMOTE_USERNAME@$REMOTE_HOST << EOF

...

exit
EOF

而後判斷容器是否存在,若是存在就結束容器。

docker rm -f ${IMAGE_REPOSITORY}_apache || true
docker rm -f ${IMAGE_REPOSITORY}_monitoring || true

注:可能有讀者對 docker rm -f ${IMAGE_REPOSITORY}_apache 這條命令感到不解,在此解釋一下。原文做者使用制定名稱 ${IMAGE_REPOSITORY}_apache 對容器進行命名。

|| 是必需的,由於若是容器不存在的話,docker rm 命令便會返回一個錯誤。咱們只須要刪除容器,並不去判斷他們是否存在。不存在的也就不用刪除,固然,刪除也沒問題。

下面一步即是啓動容器:

docker run -d --name ${IMAGE_REPOSITORY}_apache $IMAGE_REPOSITORY:apache
docker run -d --name ${IMAGE_REPOSITORY}_monitoring $IMAGE_REPOSITORY:monitoring

完整版本

爲了便於閱讀,我特地整理了全部腳本的徹底版,以下:

#!/bin/bash

set -e

REMOTE_USERNAME="..."
REMOTE_HOST="..."
IMAGE_REPOSITORY="my_repository"

function upload_image_if_needed {
    if [[ $(ssh $REMOTE_USERNAME@$REMOTE_HOST "docker images $IMAGE_REPOSITORY | grep $1 | tr -s ' ' | cut -d ' ' -f 3") != $(docker images $IMAGE_REPOSITORY | grep $1 | tr -s ' ' | cut -d ' ' -f 3) ]]
    then
        echo "$1 image changed, updating..."
        docker save $IMAGE_REPOSITORY:$1 | bzip2 | pv | ssh $REMOTE_USERNAME@$REMOTE_HOST 'bunzip2 | docker load'
    else
        echo "$1 image did not change"
    fi
}

function build_image {
    docker build -t $IMAGE_REPOSITORY:$1 $2
}

build_image apache apache/
build_image monitoring monitoring/

upload_image_if_needed apache
upload_image_if_needed monitoring

ssh -tt $REMOTE_USERNAME@$REMOTE_HOST << EOF
docker rm -f ${IMAGE_REPOSITORY}_apache || true
docker rm -f ${IMAGE_REPOSITORY}_monitoring || true

docker run -d --name ${IMAGE_REPOSITORY}_apache $IMAGE_REPOSITORY:apache
docker run -d --name ${IMAGE_REPOSITORY}_monitoring $IMAGE_REPOSITORY:monitoring

exit
EOF

結論

Docker 確實是容器中的佼佼者,並且有很好的命令行支持,可是目前仍是缺乏能便捷部署 Docker 容器的方式。固然,經過幾段簡單的腳本,咱們即可以解決這個問題。我但願這些腳本也能幫助到你。

譯者的話

本文對容器的操做比較簡單粗暴,使用 docker rm 命令進行強行刪除,可能會致使一段時間(通常不到半分鐘,視狀況而定)的網站 403,404 或者 503。
除此以外,本文的 shell 操做能夠當成是 shell 遠程執行命令的範例。

本專欄將繼續推出 Docker 系列文章,歡迎關注。

相關文章
相關標籤/搜索