Original URL:https://advancedweb.hu/2015/04/14/deploying-docker-images-via-ssh/

Background

When we began Dockerizing this blog for good, I began to look for ways to automate the build and deployment process. It turned out that although Docker is an excellent container for running applications, there is no standard way to update a server. Luckily with a moderately complex shell script it is indeed doable, and can be fully automated.

Our current architecture is made of several dependent Docker images and a Linux box as a production server. Luckily we have no dynamic data, but the deploy script can easily be modified to handle those too. In that case we would use thedata only containerapproach.

So, let’s build our deployment script!

The script

The basic idea of the build script is simple: Build the images, upload them to the server, then restart the containers with the new versions. These are the building blocks, just need some tricks to mix in order to be able to fully automate the process.

For the sake of example, let’s say we have an apache app in the apache/ subdirectory and a monitoring app residing in monitoring/.
Setting up

Let’s name our script deploy.sh and add some bootstrapping:

#!/bin/bash

set -e

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

The last variable will be the repository name for the Docker images. It is important to add one, as we will use it for the up-to-date check later.
Building

The first thing to do is to build the images. It has nothing interesting, just a standard Docker build:

function build_image {
docker build -t $IMAGE_REPOSITORY:$ $
} build_image apache apache/
build_image monitoring monitoring/

It builds the image to the predefined repository and adds a tag for easy retrieval.
Uploading to the remote server

Fortunately Docker can save and load an image to/from the standard input stream, so it makes piping possible. It effectively makes the whole uploading a one-liner.

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

What we should implement is to first check whether the image was actually modified or not. As Docker images tends to weight several hundred megabytes, it can save a lot of bandwidth, especially when there are several images and only a few of them are changing. The idea is that we can list the images for a given repository, then extract the image ID, then do the same on the remote machine, and if the IDs are the same, then the images are the same.

The finished part looks like this:

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 $ | tr -s ' ' | cut -d ' ' -f ) ]]
then
echo "$1 image changed, updating..."
docker save $IMAGE_REPOSITORY:$ | 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

Updating the containers

The last step is to restart the containers using the new images. The good thing is that we can embed remote bash commands in our deploy script and treat them just like the local ones:

ssh -tt $REMOTE_USERNAME@$REMOTE_HOST << EOF

...

exit
EOF

The first thing is to kill the current containers if they exist:

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

The || true is needed, because if the conta

iner does not exists, then docker rm gives back an error. Since we just want to have the containers killed, in case they did not exist in the first place, doing nothing is perfectly fine.

The second step is to start the containers, the standard way:

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

The final script

For a better overview, here is the complete script:

#!/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 $ | tr -s ' ' | cut -d ' ' -f ) ]]
then
echo "$1 image changed, updating..."
docker save $IMAGE_REPOSITORY:$ | 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:$ $
} 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

Conclusion

Docker is a fascinating container technology that allows building works-everywhere apps, and it comes with good CLI support. It currently lacks the features to make deploying easy, but with some scripting magic, we can work around these issues. I hope the above script gives some insight and possibly a solution to people facing the same problem.

Deploying Docker images via SSH的更多相关文章

  1. Docker创建支持ssh服务的容器和镜像

    原文链接:Docker创建支持ssh服务的容器和镜像 1. 这里使用的centos作为容器,所以首先下载centos的images # sudo docker pull centos 2. 下载后执行 ...

  2. 配置docker容器上ssh无密登录

    配置docker容器上ssh无密登录 1.修改所有容器中root账户密码 ssh到远程主机时,首次需要密码访问,因此需要修改root账号密码. 密码必须要8位以上字母数字混合. $>passwd ...

  3. Docker 添加容器SSH服务

    很多时候我们需要登陆到容器内部操作,此时我们就需要开启容器的SSH支持了,下面的小例子将具体介绍三种分配IP地址的方法,分别是pipworl分配,commit分配,Docker分配等. 基于commi ...

  4. docker中安装ssh服务

    系统:Debian Docker 目标:在docker(debian系统)中安装ssh服务,实现远程登陆和控制docker 步骤: 初始状态:通过docker pull debian得到的一个debi ...

  5. Centos7下,简单DOCKER 使用.映射SSH端口到宿主主机.

    其实使用docker完全没有必要ssh,初学的时候,可以这样熟悉以下操作. 参考这哥们的文章:http://www.jianshu.com/p/d2dd936863ec 获取镜像 docker pul ...

  6. Deploying docker registry v2

    生成证书 openssl genrsa -out mydomain.key 2048 生成秘钥 openssl req -newkey rsa:4096 -nodes -sha256 -keyout ...

  7. 配置docker中免密码SSH

    更换docker国内镜像,使用DaoCloud,特别快 编写Dockerfile文件 FROM ubuntu MAINTAINER ggzone xxx@live.com ENV REFRESHED_ ...

  8. 为Docker镜像添加SSH服务

    一.基于commit命令创建 1. 首先下载镜像 $ docker run -it ubuntu:16.04 /bin/bash 2. 安装SSH服务 #更新apt缓存 root@5ef1d31632 ...

  9. stackstorm docker中配置ssh免密码登录方式

    在docker中配置st2的ssh登录方式折腾了好久,今天终于彻底搞懂了如何重启容器后也不丢失之前的配置,只要容器起来后就可以正常ssh 执行st2中的remote-shell-script 和rem ...

随机推荐

  1. BZOJ 3771 Triple ——FFT

    直接暴力卷积+统计就可以了. 去重比较复杂. 其实也不复杂,抄吧! 反正AC了. #include <map> #include <cmath> #include <qu ...

  2. Window下安装使用RabbitMQ

    RabbitMQ官网 http://www.rabbitmq.com 下载地址 http://www.rabbitmq.com/download.html 一 Windows下安装RabbitMq 1 ...

  3. 美食节(bzoj 2879)

    Description CZ市为了欢迎全国各地的同学,特地举办了一场盛大的美食节.作为一个喜欢尝鲜的美食客,小M自然不愿意错过这场盛宴.他很快就尝遍了美食节所有的美食.然而,尝鲜的欲望是难以满足的.尽 ...

  4. DataBinder.Eval值的判断

    原文发布时间为:2009-04-10 -- 来源于本人的百度文章 [由搬家工具导入] 问:如何对<%# DataBinder.Eval(Container.DataItem,"Ly_R ...

  5. 转:C#制作ORM映射学习笔记一 自定义Attribute类

    之前在做unity项目时发现只能用odbc连接数据库,感觉非常的麻烦,因为之前做web开发的时候用惯了ORM映射,所以我想在unity中也用一下ORM(虽然我知道出于性能的考虑这样做事不好的,不过自己 ...

  6. python-rtslib 模块

    Python library for configuring the Linux kernel-based multiprotocol SCSI target (LIO) A Python objec ...

  7. springBoot Json

    pom 加json配置 <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson ...

  8. Axisfault faultcode:Server.userException异常

    ---恢复内容开始--- Axisfault faultcode:Server.userException异常 AxisFault faultCode: {http://schemas.xmlsoap ...

  9. 2017广东工业大学程序设计竞赛决赛 F(LCA + 斐波那契数列性质)

    不能组成三角形的极端数列:1,1,2,3,5,8,13,21,……到第50项时候肯定到1e9了…… 如果两个点之间距离大于50,则直接Yes…… 否则的话直接暴力取出所有边,然后升序排序,判断一下就可 ...

  10. poj1185 [NOI2001]炮兵阵地

    http://poj.org/problem?id=1185 三维装压dp,压缩上一行状态与本行状态,枚举上两行状态转移 第一维可以滚掉,实际复杂度只枚举符合情况的情况,每行状态不会超过60并非$2^ ...