1. 云栖社区>
  2. 博客列表>
  3. 正文

Hexo 升级与 Docker 初体验

潘家邦 2016-01-21 10:45:55 浏览1338 评论1

容器服务

摘要: 背景 之前我一直使用 Hexo 2.8 来编译我的博客。几个星期前的一天,我突发奇想要给 Hexo 来个升级,于是接下来的折腾就开始了。 执行了 npm install hexo-cli -g 之后,一切都还好,当我试着执行hexo server 启动服务器的时候,悲剧发生了,没法启动。

背景

之前我一直使用 Hexo 2.8 来编译我的博客。几个星期前的一天,我突发奇想要给 Hexo 来个升级,于是接下来的折腾就开始了。

执行了 npm install hexo-cli -g 之后,一切都还好,当我试着执行hexo server 启动服务器的时候,悲剧发生了,没法启动。一番 Google 之后发现从 2.8 升级到 3.0 似乎没那么平滑,于是我决定降回 2.8,然后另选时间升级。

降级之路也不平坦,即使我显式给出了降级之后各个组件的版本,整个依赖树也回不到从前了。可能这个也是 npm 包管理体系的特 (quē) 性 (xiàn) 吧,大家都不太会在依赖中显式的写出某个指定的版本,反而比较喜欢使用版本范围,据说这样子能够自动获取依赖包升级之后的 bug fix 和性能提升[1]

不管怎么说,这样折腾一番之后,我的 Hexo 博客环境没有之前好用了。看来 2.8 已经没法待下去了,只有升级到 3.0 这条路。

Docker

虽然博客环境没有之前好用,但是它至少还是能够磕磕绊绊把我的博客编译部署的。我希望至少在我升级的时候,我还能使用现在的博客环境。

之前用 Python 的时候,有一个叫 Virtualenv 的神器,可以在系统中部署多套隔离的 Python 环境,我的电脑里就用它弄了两套完全隔离的环境,一套是 Py27,一套是 Pypy。似乎 Node.js 生态圈中还没有类似的工具。问题在于 hexo 必须安装到全局目录才能作为命令使用,一旦全局安装 Hexo 3.0,势必覆盖 2.8 版本。

如果在过去,我可能会弄一个 Linux 的虚拟机来安装 Hexo 3.0。在容器技术如火如荼的今天,开个虚拟机就为了用 Linux 显得不合时宜而又可笑,仿佛从几年之前穿越过来的。半年前我就在电脑上安装了 Docker,用的是 boot2docker,文档也看了好几篇,但是一直没有认真用过,只是凑个热闹,假装自己紧跟技术潮流。

这次,我要正正经经的用一次 Docker,至少构建一个包含完整 Hexo 3.0 环境的镜像。

其实 OS X 上有一个看起来还算不错的 Docker GUI 前端,叫 Kitematic,对命令行无爱的话可以试试(对命令行无爱的人得有多大的勇气才能使用 Docker)。

一番折腾之后,我对 Docker 也算有了一些感觉,总体来说体验不错。Docker 的概念中,容器、镜像等等还挺有意思的。

简单用程序来打个比方,也许不是那么贴切。我们用 Dockerfile 来描述镜像的构建过程,就好像我们用高级语言来描述程序的执行过程;当我们根据 Dockerfile 来构建镜像,就仿佛用编译器把代码编译成可执行文件;当我们把镜像跑起来,容器就产生了,就仿佛可执行文件一旦执行,进程就出现了。

个把小时之后,我成功使用 Docker 基于 ubuntu:14.04 构建出了一个 Hexo 镜像,第二天晚上我成功在镜像中完成了 Hexo 的升级尝试,并把我的博客环境也升级到了 Hexo 3.0。

镜像

折腾的过程当然不会像我写的这么顺利,这里把一些重要的过程做个记录。

Docker 和 boot2docker 的安装过程这里就不说了,直接参考 Docker Documentation

写 Dockerfile 的要点可以参考 Best practices for writing Dockerfiles,但是写好的 Dockerfile 该怎怎么用,我翻来覆去看了好多遍文档才找到比较科学的方法。

一般来说使用 docker build 的时候,需要传一个保存有名为 “Dockerfile” 的文件的路径作为参数。这种方式的优点是有一个构建的环境,即 Dockerfile 所在的目录,docker 可以在构建的时候使用这个环境中的文件[2]

对于我构建 Hexo 镜像来说,我不需要这样的构建环境,直接使用重定向把 Dockerfile 传递给 docker 是一个相对更好的选择。

于是我可以随意给 Dockerfile 命名,然后用下面的命令来构建镜像。

docker build -t jamespan/hexo - < path-to-hexo-docker-file
镜像构建完成之后,我可以用下面的命令把镜像跑起来,使用 --rm 参数能够在我退出容器之后自动删除容器,使用 -v 参数能够挂载数据卷,把本地的目录或文件 mount 到容器中,使用 -p 参数能够绑定端口,-t 和 -i 参数经常一起使用,可以给 docker 分配一个虚拟终端,然后一直等待标准输入,像一个 shell 一样工作[3]
docker run -it --rm -p 4000:4000 \
   -v path-to-source:/root/blog/source \
   -v path-to-theme:/root/blog/themes \
   -v path-to-config.yml:/root/blog/_config.yml \
   jamespan/hexo /bin/bash

Hexo 的用户应该知道,我们实际上需要关心的,就是两个目录一个文件:source 目录存放我们的博文、页面等,是博客内容;themes 目录存放主题,是博客的样式;_config.yml 是整个博客的配置,记录一些重要的变量,定义各种插件的行为。

理论上我们能够做到使用容器运行一个安装了必要插件的 Hexo 环境,然后挂载这些目录和文件到正确的目录,就能使用容器为我们提供标准的 Hexo 服务。

Hexo

我以 ubuntu:14.04 为基础构建我的镜像,Dockerfile 保存在了 Gist,点此访问

FROM ubuntu:14.04
 
MAINTAINER Pan Jiabang, panjiabang@gmail.com
 
RUN \
  # use aliyun's mirror for faster download speed
  sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list && \
  apt-get update && \
  apt-get install -y nodejs curl git-core && \
  # use nodejs as node 
  update-alternatives --install /usr/bin/node node /usr/bin/nodejs 10 && \
  # install npm
  curl -L https://npmjs.org/install.sh | sh && \
  # clean up install cache
  apt-get clean && \
  rm -rf /var/lib/apt/lists/*

WORKDIR /root
 
RUN \
  mkdir blog && cd blog && \
  # install hexo
  npm install hexo-cli -g && \
  hexo init && npm install && \
  # install plugins for hexo
  npm install hexo-generator-sitemap --save && \
  npm install hexo-generator-feed --save && \
  npm install hexo-deployer-git --save && \
  npm un hexo-renderer-marked --save && \
  npm i hexo-renderer-markdown-it --save
 
WORKDIR /root/blog/
 
VOLUME ["/root/blog/source"]
VOLUME ["/root/blog/themes"]
 
EXPOSE 4000
 
CMD ["/bin/bash"]

从 ubuntu 开始,先是更换软件源,使用阿里云的镜像,这样子安装软件的速度会快很多。然后就是安装 nodejs、curl 和 git。curl 后面安装 npm 的时候会用到。我之所以没有选择从软件源安装 npm,是因为那样子会顺带安装上很多 *-dev 的包,而我仅仅是搭建 Hexo 环境而已,不需要那些东西的。

接下来一大段脚本是安装 Hexo 及其插件,还有初始化博客目录。最后是声明目录挂载点。

基本上整个镜像的构建脚本都在这里了。

升级

在 Docker 中尝试安装 Hexo 3.0 是一边调试、部署一边记录,最后把执行过的命令整理成 Dockerfile 的。

调试过程中发现一个有趣的问题,之前使用 Hexo 2.8 的时候,我在编辑器中修改了文件,hexo server 会感知文件变化,然后自动更新静态博客。我在 Docker 中挂载 source 目录然后启动 hexo server,从浏览器访问页面一切都正常,唯独我在编辑器中修改了内容,服务器没有自动更新博客内容,必须让我手动停止然后再重新启动 hexo server。

如果我真正安装 Hexo 3.0 之后也是这种情况,那是没法接受的,我开始查找原因。中间绕了不少弯路,最后查看 npm 安装日志发现是一个叫 fsevents 的可选依赖没有安装。

我想,如果我能够把 fsevents 成功安装,应该就没问题了。谁知道我各种姿势尝试安装之后,还是失败了。查看 fsevents 之后发现这是一个专门用来监听 OS X 系统文件变化的类库。在 Linux 上没法安装一个 OS X 专用类库也是合理的。

好像除了监听文件变化在 Docker 中没法测试之外,其他一切都还好。于是我花了几分钟,把本机博客目录的 node_modules 目录和 package.json 备份之后,升级了 Hexo。

要说这次升级一点后遗症都没有,那是不可能的。不过总体来说,升级到 3.0 之后整体上感觉还是不错的,至少修复了之前困扰我多时的文章发布日期偏移的 bug,代价是我把评论系统从漏洞百出的多说换成了 DISQUS,感觉整个博客瞬间和国际接轨了,萌萌哒~

要不我试着用英文写博客?


  1. 如何使用NPM来管理你的Node.js依赖 

  2. Docker command line - build 

  3. Docker run reference - Foreground 

本文为云栖社区原创内容,未经允许不得转载,如需转载请发送邮件至yqeditor@list.alibaba-inc.com;如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:yqgroup@service.aliyun.com 进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。

用云栖社区APP,舒服~

【云栖快讯】哪个编程语言最热门?各个专业领域的技术趋势是什么?如何才能更快速的踏上技术进阶之路……云栖社区2017中国开发者大调查火热进行!答卷可抽奖,红轴机械键盘、天猫精灵,丰富好礼大概率抽取  详情请点击

网友评论

1F
z605

大佬的博客地址是多少呀

关注
潘家邦
蒟蒻研发工程师,客居杭州。喜欢学习研究新技术,...
30篇文章|32关注
提供了高性能可伸缩的容器应用管理服务,支持在一组云服务器上通过Docker容器来进行应用生命周期管理。 更多>

兼容Jenkins标准,可提供快速可靠的持续集成与持续交付服务。基于容器技术和阿里云基础服务架构,提供稳定和安全... 更多>

深度挖掘企业与企业、企业与人物的关系,通过多位交叉分析及智能算法,构建基于企业全息画像和企业关系网络的风险洞察、... 更多>

为您提供简单高效、处理能力可弹性伸缩的计算服务,帮助您快速构建更稳定、安全的应用,提升运维效率,降低 IT 成本... 更多>
安全技术百问

安全技术百问