使用Docker构建nginx-hhvm镜像

如您所知,Docker是“一个提供给开发者和系统管理员的,用来打包,迁移和运行应用程序的开放平台。”自从去年年初发布后,它一直处于快速演进的状态,围绕着该平台的开发者社区也十分活跃。

这篇文章用来记录本人尝试使用Docker构建应用nginx和hhvm的网络服务器基础映像的过程,以资参考。

1、开发环境的准备:

显然需要一套能运行Docker的系统。Docker的容器技术依赖于Linux内核,同时只能在64位系统上运行。在windows可以使用vitrual box虚拟合适的操作系统,这方面的文章比较多,不再赘述。我的话,因为校园网环境按照流量计费,所以选择Digitalocean的VPS作为开发环境,选择最低配置每天的开销约为¥1,至少比流量费便宜。

我将使用CoreOS作为开发环境。CoreOS是专用于Docker的定制化系统,没有包管理系统,比较轻量化,不过常用的Linux工具还是比较齐全的。DigitalOcean上可以方便地建立使用coreos系统的vps。值得注意的是,coreos的root用户的用户名为“core”。而且需要ssh登陆强制要求使用RSA密钥,在digitalocean上创建的时候会要求你选择密钥。

2、基本操作:

docker平台提供了很多构建完成的基础映像,可以简单地下载到本地并且在容器中运行。这些容器与宿主平台共用linux核心,但是拥有独立的“namespace”,与宿主和其他容器隔离。简单操作如下(如果使用非管理员账号可能需要‘sudo’,docker以root权限运行)

core@illya ~ $ docker pull debian:wheezy

core@illya ~ $ docker run -i -t --name foo debian

这将会下载官方打包的debian映像,然后新建容器并以交互方式在容器中运行bash shell。

root@1a022f23501a:/# echo hello

hello

在该容器中可以执行对应系统的特定操作,比如使用atp-get安装软件包。

root@1a022f23501a:/# apt-get update && apt-get install --qq procps

现在可以在容器内使用‘ps’指令列出当前运行的进程了:

root@1a022f23501a:/# ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.6  17856  3076 ?        Ss   07:33   0:00 /bin/bash
root       145  0.0  0.3  15324  1900 ?        R+   07:58   0:00 ps aux

使用'exit'可以从当前容器中退出:
root@1a022f23501a:/#exit

docker可以将经过修改的容器('container')作为新的镜像('image')保存:

core@illya ~ $ docker commit foo bar
81663069ac71b8eec32ba4aa9d90b9f8a7f4ab58945988533f6d4a318d2b682c
core@illya ~ $ docker run -i -t --rm bar ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.1   6908   528 ?        Rs+  08:12   0:00 ps aux

可以看到,被安装到容器中的,新的程序已经可用了。

容易想到,我们可以通过这样的方式,在基础镜像上进行修改,来实现我们所需要的功能。

3、构建nginx-hhvm所需要的知识:

安装nginx或者hhvm的方法漫天遍野,我也是现学的,所以也不多讲。

需要考虑的是,Docker通过监控应用程序进入时运行的第一个进程来判断容器是否退出。nginx默认以守护进程的方式运行,主进程在启动服务后会自动退出。Docker会误认为nginx已经退出而错误地终止容器的运行,显然不对。

我们可以使用 nginx -g 'daemon off' 指令使nginx的守护进程在前台运行。

容易想到,我们的容器中可能不只需要运行一个服务,尽管我们可以用启动脚本的方式来管理服务,但是这样十分不方便扩展。

采纳docker开发者的实践经验,我们可以使用‘supervisor’这个python程序来管理各个服务进程。相关文档可以前往这个链接查看。

4、Dockerfile与自动构建

使用上述的方法来构建docker镜像的话,过程不够透明,比较繁琐,不方便修改和分享。因此,我们可以选择使用Dockerfile来定义容器的构建过程,并且使用Docker.Inc的开放平台来自动构建镜像以及分享。

这里直接给出我用来构建nginx-hhvm服务的Dockerfile:

FROM debian:wheezy
MAINTAINER Robin Liu <spdf@live.com>
ADD build/* /tmp/
RUN \
apt-key add /tmp/hhvm.gpg.key && \
apt-key add /tmp/nginx_signing.key && \
echo "deb http://nginx.org/packages/debian/ wheezy nginx" >> /etc/apt/sources.list && \
echo "deb-src http://nginx.org/packages/debian/ wheezy nginx" >> /etc/apt/sources.list && \
echo deb http://dl.hhvm.com/debian wheezy main | tee /etc/apt/sources.list.d/hhvm.list
RUN \
apt-get update && \
apt-get install -y apt-utils procps supervisor vim.tiny && \
apt-get install -y nginx hhvm
RUN \
cp /tmp/nginx.conf /etc/nginx/nginx.conf && \
cp /tmp/hhvm.server.ini /etc/hhvm/server.ini && \
cp /tmp/supervisord.*.conf /etc/supervisor/conf.d/ && \
cp /tmp/enter.sh /etc/enter.sh && \
chmod 755 /etc/enter.sh
EXPOSE 80 443
VOLUME ["/data"]
CMD ["/etc/enter.sh"]

稍微解释一下各行的意思

FROM debian:wheezy

这一句定义了我们构建的镜像的基础镜像;

MAINTAINER Robin Liu <spdf@live.com>

这一句给出了该镜像的发布者的信息;

ADD build/* /tmp/

这一句将和Dockfile文件同一目录下的'build'文件夹内的全部文件复制到容器的'/tmp'目录下,备用;

RUN \
apt-key add /tmp/hhvm.gpg.key && \
apt-key add /tmp/nginx_signing.key && \
echo "deb http://nginx.org/packages/debian/ wheezy nginx" >> /etc/apt/sources.list && \
echo "deb-src http://nginx.org/packages/debian/ wheezy nginx" >> /etc/apt/sources.list && \
echo deb http://dl.hhvm.com/debian wheezy main | tee /etc/apt/sources.list.d/hhvm.list
RUN \
apt-get update && \
apt-get install -y apt-utils procps supervisor vim.tiny && \
apt-get install -y nginx hhvm

这一段导入了nginx stable,HHVM和Supervisor的软件源,并且安装到系统中;

再接下来的一段将一些预定义的配置文件复制到对应位置,以及将docker容器启动时要运行的脚本变更权限为可执行;

EXPOSE 80 443

这一句定义了容器需要导出的TCP端口;

VOLUME ["/data"]

这一句定义了容器可以由外部挂载的文件目录;

CMD ["/etc/enter.sh"]

这一句定义了容器启动时默认执行的命令。

大概就是这样。

Docker.Inc提供了根据git仓库自动构建镜像的服务,可以根据Dockerfilet版本的变化以及基础镜像的更新自动重新构建镜像。

我的这个nginx-server服务也已提交到,名为‘kagami/nginx-hhvm’。好吧,我就是想强注自己喜欢的id罢了。

  1. 小明猪说道:
    有前途,在学校就这么牛猛了 我还真不信我发不出这条评论
    1. 一树小草说道:
      多谢夸奖。(๑´ڡ`๑)实在是不好意思,踹飞“多说”已经在计划中了,等我治好拖延症,嗯嗯。

回复 小明猪 取消回复

电子邮件地址不会被公开。必填项已用 * 标注