使用 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 系列文章,欢迎关注。

相关文章
相关标签/搜索