个人博客:戳我,戳我
这段时间一直在折腾我的博客,由于之前出现过一次电脑硬盘完全挂掉的情况,为了避免重新搭建博客系统,一直打算搞一个方便点的环境,能进行多机迁移之类的。正好,Docker完全满足我的要求。
之前一直只是听说过Docker,听说过容器,听说过镜像,但并没有正真的了解接触过Docker。这次借助于博客的折腾,正好有了这个研究折腾Docker的机会。
正如Docker官网介绍的那样:
Docker is the world’s leading software containerization platform.
关于了解Docker不是本文的重点,这里可以推荐我之前收藏的关于Docker的几个链接:
看完上面的内容基本还是对Docker有了一个比较基础的认识,关于docker的安装,docker命令的使用,docker的设计原理等。
这个地方我当时刚接触的时候没有理清,以为docker是把我windows上的本地环境打包构建成一个镜像,相当于克隆一个我在windows上的博客系统,这个想法还是有点太天真了看来。后来了解了Docker的原理以及使用后,才理清了这些问题。
其实可以很简单的理解,docker是一个软件,运行的是容器,容器里面是各种应用,运行一个容器需要一个镜像,这个镜像可以是一个基础镜像,也可以是一个你自己基于基础镜像构建好的镜像,镜像的内容可以粗略的理解为一个系统,比如各种版本的Linux等。所以关于构建hexo的镜像,就是首先拉取一个基础镜像,比如我选择了Ubuntu系统,然后当容器跑起来后,就相当于一个虚拟机了,这个时候你可以安装你的hexo环境,node环境,git环境等,最后可以把整个构建好的环境整体打包生成一个最终的镜像,这个镜像就是最终需要的镜像。
上面的理解,可能有偏差,因为只是我自己的理解。好了,废话不多说,开始了!(我的linux机器是centos7)
# yum update && yum install docker-engine
启动docker:
# systemctl start docker
运行测试:
# docker run --rm hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
c04b14da8d14: Pull complete
Digest: sha256:0256e8a36e2070f7bf2d0b0763dbabdd67798512411de4cdcf9431a1feb60fd9
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker Hub account:
https://hub.docker.com
For more examples and ideas, visit:
https://docs.docker.com/engine/userguide/
FROM ubuntu:14.04
MAINTAINER nick,@gmail.com>
RUN \
cp /etc/apt/sources.list /etc/apt/sources.list.bak && \
echo "deb http://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiverse" > /etc/apt/sources.list && \
echo "deb http://mirrors.aliyun.com/ubuntu/ trusty-security main restricted universe multiverse" >> /etc/apt/sources.list && \
echo "deb http://mirrors.aliyun.com/ubuntu/ trusty-updates main restricted universe multiverse " >> /etc/apt/sources.list && \
echo "deb http://mirrors.aliyun.com/ubuntu/ trusty-proposed main restricted universe multiverse " >> /etc/apt/sources.list && \
echo "deb http://mirrors.aliyun.com/ubuntu/ trusty-backports main restricted universe multiverse " >> /etc/apt/sources.list && \
echo "deb-src http://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiverse " >> /etc/apt/sources.list && \
echo "deb-src http://mirrors.aliyun.com/ubuntu/ trusty-security main restricted universe multiverse " >> /etc/apt/sources.list && \
echo "deb-src http://mirrors.aliyun.com/ubuntu/ trusty-updates main restricted universe multiverse " >> /etc/apt/sources.list && \
echo "deb-src http://mirrors.aliyun.com/ubuntu/ trusty-proposed main restricted universe multiverse " >> /etc/apt/sources.list && \
echo "deb-src http://mirrors.aliyun.com/ubuntu/ trusty-backports main restricted universe multiverse " >> /etc/apt/sources.list && \
apt-get update && \
apt-get install -y git && \
apt-get install -y nodejs npm && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* && \
ln -s /usr/bin/nodejs /usr/bin/node && \
alias cnpm="npm --registry=https://registry.npm.taobao.org --cache=$HOME/.npm/.cache/cnpm --disturl=https://npm.taobao.org/dist \
--userconfig=$HOME/.cnpmrc" && \
npm install hexo-cli -g
WORKDIR /Hexo
#VOLUME ["/Hexo/source", "/Hexo/themes", "/root/.ssh"]
EXPOSE 4000
CMD ['/bin/bash']
Dockerfile是用来构建一个镜像的命令的集合,docker可以根据里面的命令自动化的构建一个用户所期望的镜像。关于上面Dockerfile的内容,我做一点简单的解释。
前面的echo命令是更换ubuntu的apt-get源为阿里云的源,加快访问下载速度。然后安装git,nodejs,npm,然后更换淘宝的cnmp:
alias cnpm="npm --registry=https://registry.npm.taobao.org --cache=$HOME/.npm/.cache/cnpm --disturl=https://npm.taobao.org/dist \
--userconfig=$HOME/.cnpmrc"
后面就是安装hexo(注意此处的命令可以更换成cnmp install hexo-cli -g,我当时好像是碰到了问题,就采用原来的npm方式了)。
WORKDIR /Hexo
指明工作路径,启动容器后会自动切换到这个目录下。
#VOLUME ["/Hexo/source", "/Hexo/themes", "/root/.ssh"]
指定挂载目录,宿主机的/Heo/source,/Hexo/themes ,/root/.ssh 被挂载到容器里的相应位置,如果没有该目录,则创建该目录,提供一种宿主机和容器的访问策略。此处我前面加了#注释掉了,因为实际情况我不需要,可以在启动容器的命令中手工指定。
最后,
EXPOSE 4000
就是暴露端口4000,映射到宿主机的4000端口,提供另外一种宿主机和容器的访问策略。
关于Dockerfile中这些命令的详细解释,可以参考下面的链接:
Docker镜像创建
解释一下,按照上面的Dockerfile构建出来的镜像,安装了hexo的博客环境所依赖的工具或命令,包括git,node,npm,hexo本身,到此处,其实已经搭建好了一个hexo环境,只不过这个环境在一个容器中,接下来正常的操作就是新建一个目录作为hexo的博客根目录,然后执行‘hexo init . && npm install && …’,但是其实我不会这么做,后面解释。
检查docker是否在运行:
# systemctl status docker
如果是”inactive”,那么启动docker:
# systemctl start docker
依据Dockerfile构建hexo镜像:
#docker build -t hexo:v1 .
注意:此命令是必须在Dockerfile的目录下执行,hexo:v1可以自行命名,就是镜像的名字,v1应该类似于一个tag之类的东西。
如果正常的话,是会看到后面的输出正好对应着Dockerfile中的每条命令。构建成功后大致会看到类似“successful build”之类的提示。查看镜像:
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hexo v1 522f7cfc7a31 8 seconds ago 405MB
关于405MB可能不准确,因为当时的数据我现在不太记得,不过大致在这个量级,还是挺大的。
执行命令:
# docker run -i -t 522f7cfc7a31 -p 4000:4000 /bin/bash
会启动容器,这个时候切换到容器里的系统的终端,如:
root@abfc3a0ec1f0:/Hexo#
紧接着敲入命令:
root@abfc3a0ec1f0:~# hexo -v
hexo-cli: 1.0.2
os: Linux 3.10.0-327.36.3.el7.x86_64 linux x64
http_parser: 2.5.2
node: 4.4.5
v8: 4.5.103.35
uv: 1.8.0
zlib: 1.2.8
ares: 1.10.1-DEV
icu: 56.1
modules: 46
openssl: 1.0.2h
证明hexo容器启动正常,hexo环境安装成功。
这一步就是上面提到的在后面解释的那一步。
上面说到,安装好hexo的环境后,接下来就是执行创建博客源码的步骤,但是由于前一篇博文使用coding私有仓库多终端编写博客中已经把博客源码放到了coding的私有仓库中,所以接下的步骤将会有些许不一样的地方。
配置ssh,目的是为了通过ssh通道克隆我的博客仓库源码,免去http方式的用户名密码验证。配置方式可以参照我之前的博文我的个人博客搭建记录中”配置SSH”一节。这里我把所有命令一起写下来:
root@abfc3a0ec1f0:~# cd ~/.ssl && ls -al ./*
root@abfc3a0ec1f0:~# rm -rf ./*
root@abfc3a0ec1f0:~# git config --global user.name "yourname" && git config --global user.email "youremail" && ssh-keygen -t rsa -C "yourmail@gmail.com" && cat ~/.ssh/id_rsa.pub
实际情况实际替换。然后在coding上添加上面产生的密匙。
执行命令:
root@abfc3a0ec1f0:~# git clone
这一步完成后我们就把整个博客的源码克隆下来了,参照前一篇博文使用coding私有仓库多终端同步编写博客中”在另外的PC上”一节,只需要在博客目录下执行命令:
npm install
接下来就可以编写博客了:
hexo d -g
到这里其实完成了博客的所有依赖,也即此刻就不用再配置博客的系统了,接下来就是如何把这个容器保存下来的问题
简要阐述下上面的过程,首先依赖ubuntu的基础镜像安装好了hexo的环境,导出了一个hexo的第一个版本v1镜像,此时还没有博客源码,然后运行容器,在容器里边操作,配置ssh,克隆博客,完成后,就是再次生成镜像。
执行命令:
root@abfc3a0ec1f0:~# exit
记住容器的id abfc3a0ec1f0,然后执行命令:
# docker commit -m "finally hexo" -a "Author" abfc3a0ec1f0 hexo:v2
完成后执行docker images后会看到现在构建好的镜像hexo:v2版本。这个版本就是我们最终需要的镜像。
# docker save -o hexo_finally.tar hexo:v2
上面把镜像导出到本地。
到此处,已经完成了这篇博客的目的,构建了一个hexo的docker镜像,这个镜像可以运行在任何安装了docker的机器上,达到了之前我预期的多终端同步编写博客的目的。也不再害怕那天我的电脑硬盘又悲剧了,当然这个hexo_finally.tar是要备份的,不然说啥也没用。
但是,为了测试下这个镜像有没有正确,接下来我做点测试。
首先执行命令删除所有镜像:
# docker rmi $(docker images -q)
然后装载镜像:
# docker load < hexo_finally.tar
执行docker images即可查看到装载进来的镜像。然后运行容器:
# docker run -i -t /bin/bash
然后(blog是我自己的博客根目录):
cd blog
尝试执行:
git pull origin master && hexo d -g
这一步多半凶多吉少,我在此处浪费了很多时间。我发现每次运行容器后root用户下的.ssh文件夹会不见了,这个文件下可是我之前生成的密匙所在地啊。反复试了好多次,发现都一样,只要重新运行,.ssh文件夹就会消失。后来我采取了一个折中的办法,把id_rsa和id_rsa.pub两个文件复制到root的$HOME下,然后在重新生成镜像导出,下次再运行容器的时候重新把这两个文件复制到.ssh文件夹下可以解决此问题
好了,到此处,基本完成了hexo的镜像制作,只要备份了这个hexo_finally.tar包,就可以不惧怕任何宕机问题了,欧耶。其实我如果写好博客后,是不需要执行hexo d -g命令的,由于我后来采用了daocloud自动集成,所以只需要把博客源码提交到coding就可以了,然后daocloud会自动集成构建。(关于这种采用daocloud自动集成的方式,我后面的博文会记录到,这里先占个坑,写好了重新更新到这里。点我)
总体过程还是有点复杂的,我由于是回忆的状态写,可能会有疏漏,如果碰到问题,你可以联系我或者自己探索解决。总之,首先要了解docker,然后学会使用docker,然后做起这些来就比较轻松多了。
至于docker嘛,使用感觉并没有想象中那么如丝般柔滑,加载一个镜像,运行一个容器还是挺慢的。恩,对的。
Blog:
rebootcat.com
email: [email protected]
2016-12-20 于杭州
By 史矛革