背景
这段时间一直在折腾我的博客,由于之前出现过一次电脑硬盘完全挂掉的情况,为了避免重新搭建博客系统,一直打算搞一个方便点的环境,能进行多机迁移之类的。正好,Docker完全满足我的要求。
之前一直只是听说过Docker,听说过容器,听说过镜像,但并没有正真的了解接触过Docker。这次借助于博客的折腾,正好有了这个研究折腾Docker的机会。
What is Docker?
正如Docker官网介绍的那样:
Docker is the world’s leading software containerization platform.
关于了解Docker不是本文的重点,这里可以推荐我之前收藏的关于Docker的几个链接:
看完上面的内容基本还是对Docker有了一个比较基础的认识,关于docker的安装,docker命令的使用,docker的设计原理等。
构建hexo镜像
安装Docker
这个地方我当时刚接触的时候没有理清,以为docker是把我windows上的本地环境打包构建成一个镜像,相当于克隆一个我在windows上的博客系统,这个想法还是有点太天真了看来。后来了解了Docker的原理以及使用后,才理清了这些问题。
其实可以很简单的理解,docker是一个软件,运行的是容器,容器里面是各种应用,运行一个容器需要一个镜像,这个镜像可以是一个基础镜像,也可以是一个你自己基于基础镜像构建好的镜像,镜像的内容可以粗略的理解为一个系统,比如各种版本的Linux等。所以关于构建hexo的镜像,就是首先拉取一个基础镜像,比如我选择了Ubuntu系统,然后当容器跑起来后,就相当于一个虚拟机了,这个时候你可以安装你的hexo环境,node环境,git环境等,最后可以把整个构建好的环境整体打包生成一个最终的镜像,这个镜像就是最终需要的镜像。
上面的理解,可能有偏差,因为只是我自己的理解。好了,废话不多说,开始了!(我的linux机器是centos7)
1 | # yum && yum install docker-engine |
启动docker:
1 |
运行测试:
1 | # docker run --rm hello-world |
Dockerfile
1 | FROM ubuntu:14.04 |
Dockerfile是用来构建一个镜像的命令的集合,docker可以根据里面的命令自动化的构建一个用户所期望的镜像。关于上面Dockerfile的内容,我做一点简单的解释。
前面的echo命令是更换ubuntu的apt-get源为阿里云的源,加快访问下载速度。然后安装git,nodejs,npm,然后更换淘宝的cnmp:
1 | alias cnpm="npm --registry=https://registry.npm.taobao.org --cache=$HOME/.npm/.cache/cnpm --disturl=https://npm.taobao.org/dist \ |
后面就是安装hexo(注意此处的命令可以更换成cnmp install hexo-cli -g,我当时好像是碰到了问题,就采用原来的npm方式了)。
1 | WORKDIR /Hexo |
指明工作路径,启动容器后会自动切换到这个目录下。
1 | #VOLUME ["/Hexo/source", "/Hexo/themes", "/root/.ssh"] |
指定挂载目录,宿主机的/Heo/source,/Hexo/themes ,/root/.ssh 被挂载到容器里的相应位置,如果没有该目录,则创建该目录,提供一种宿主机和容器的访问策略。此处我前面加了#注释掉了,因为实际情况我不需要,可以在启动容器的命令中手工指定。
最后,
1 | EXPOSE 4000 |
就是暴露端口4000,映射到宿主机的4000端口,提供另外一种宿主机和容器的访问策略。
关于Dockerfile中这些命令的详细解释,可以参考下面的链接:
Docker镜像创建
解释一下,按照上面的Dockerfile构建出来的镜像,安装了hexo的博客环境所依赖的工具或命令,包括git,node,npm,hexo本身,到此处,其实已经搭建好了一个hexo环境,只不过这个环境在一个容器中,接下来正常的操作就是新建一个目录作为hexo的博客根目录,然后执行‘hexo init . && npm install && …’,但是其实我不会这么做,后面解释。
运行docker,构建镜像
检查docker是否在运行:
1 |
如果是”inactive”,那么启动docker:
1 |
依据Dockerfile构建hexo镜像:
1 | #docker build -t hexo:v1 . |
注意:此命令是必须在Dockerfile的目录下执行,hexo:v1可以自行命名,就是镜像的名字,v1应该类似于一个tag之类的东西。
如果正常的话,是会看到后面的输出正好对应着Dockerfile中的每条命令。构建成功后大致会看到类似“successful build”之类的提示。查看镜像:
1 | # docker images |
关于405MB可能不准确,因为当时的数据我现在不太记得,不过大致在这个量级,还是挺大的。
测试容器hexo
执行命令:
1 | # docker run -i -t 522f7cfc7a31 -p 4000:4000 /bin/bash |
会启动容器,这个时候切换到容器里的系统的终端,如:
1 | root@abfc3a0ec1f0:/Hexo# |
紧接着敲入命令:
1 | root@abfc3a0ec1f0:~# hexo -v |
证明hexo容器启动正常,hexo环境安装成功。
克隆hexo博客仓库源码,尝试提交
这一步就是上面提到的在后面解释的那一步。
上面说到,安装好hexo的环境后,接下来就是执行创建博客源码的步骤,但是由于前一篇博文使用coding私有仓库多终端编写博客中已经把博客源码放到了coding的私有仓库中,所以接下的步骤将会有些许不一样的地方。
配置ssh
配置ssh,目的是为了通过ssh通道克隆我的博客仓库源码,免去http方式的用户名密码验证。配置方式可以参照我之前的博文我的个人博客搭建记录中”配置SSH”一节。这里我把所有命令一起写下来:
1 | root@abfc3a0ec1f0:~# cd ~/.ssl && ls -al ./* |
实际情况实际替换。然后在coding上添加上面产生的密匙。
克隆博客源码
执行命令:
1 | root@abfc3a0ec1f0:~# git clone <server> |
这一步完成后我们就把整个博客的源码克隆下来了,参照前一篇博文使用coding私有仓库多终端同步编写博客中”在另外的PC上”一节,只需要在博客目录下执行命令:
1 | npm install |
接下来就可以编写博客了:
1 | hexo d -g |
到这里其实完成了博客的所有依赖,也即此刻就不用再配置博客的系统了,接下来就是如何把这个容器保存下来的问题
构建最终hexo镜像
简要阐述下上面的过程,首先依赖ubuntu的基础镜像安装好了hexo的环境,导出了一个hexo的第一个版本v1镜像,此时还没有博客源码,然后运行容器,在容器里边操作,配置ssh,克隆博客,完成后,就是再次生成镜像。
执行命令:
1 | root@abfc3a0ec1f0:~# exit |
记住容器的id abfc3a0ec1f0,然后执行命令:
1 |
完成后执行docker images后会看到现在构建好的镜像hexo:v2版本。这个版本就是我们最终需要的镜像。
1 | # docker save -o hexo_finally.tar hexo:v2 |
上面把镜像导出到本地。
到此处,已经完成了这篇博客的目的,构建了一个hexo的docker镜像,这个镜像可以运行在任何安装了docker的机器上,达到了之前我预期的多终端同步编写博客的目的。也不再害怕那天我的电脑硬盘又悲剧了,当然这个hexo_finally.tar是要备份的,不然说啥也没用。
但是,为了测试下这个镜像有没有正确,接下来我做点测试。
验证hexo镜像
首先执行命令删除所有镜像:
1 | # docker rmi $(docker images -q) |
然后装载镜像:
1 |
执行docker images即可查看到装载进来的镜像。然后运行容器:
1 |
然后(blog是我自己的博客根目录):
1 | cd blog |
尝试执行:
1 | git pull origin master && hexo d -g |
这一步多半凶多吉少,我在此处浪费了很多时间。我发现每次运行容器后root用户下的.ssh文件夹会不见了,这个文件下可是我之前生成的密匙所在地啊。反复试了好多次,发现都一样,只要重新运行,.ssh文件夹就会消失。后来我采取了一个折中的办法,把id_rsa和id_rsa.pub两个文件复制到root的$HOME下,然后在重新生成镜像导出,下次再运行容器的时候重新把这两个文件复制到.ssh文件夹下可以解决此问题
END
好了,到此处,基本完成了hexo的镜像制作,只要备份了这个hexo_finally.tar包,就可以不惧怕任何宕机问题了,欧耶。其实我如果写好博客后,是不需要执行hexo d -g命令的,由于我后来采用了daocloud自动集成,所以只需要把博客源码提交到coding就可以了,然后daocloud会自动集成构建。(关于这种采用daocloud自动集成的方式,我后面的博文会记录到,这里先占个坑,写好了重新更新到这里。点我)
总体过程还是有点复杂的,我由于是回忆的状态写,可能会有疏漏,如果碰到问题,你可以联系我或者自己探索解决。总之,首先要了解docker,然后学会使用docker,然后做起这些来就比较轻松多了。
至于docker嘛,使用感觉并没有想象中那么如丝般柔滑,加载一个镜像,运行一个容器还是挺慢的。恩,对的。
Blog:
2016-12-20 于杭州
By 史矛革