以前的公司项目管理用Redmine,公司里的IT团队为了部署方便,将 Bitnami打包好的版本装在虚拟机里并且预先配置好各种预设值和数据库 什么的,需要新实例的时候直接在服务器上新建一个虚拟机就可以了。最近因 为工作需要,我要自己在本地搭一个Redmine实例,手上的破机器又跑不起虚 拟机,难道只能直接上了?那倒不至于,我们还有Docker.
Docker和虚拟机
Docker是用Go语言实现的“应用容器”(Application Container),用于
将具体应用和它的执行环境(包括依赖的库等等)打包到一起,以方便部
署,并且与其他应用隔离开来。Docker的大名我在年初就听说过了,但是因为
不想趟Go语言这滩浑水,所以一直没有动手……这次回头研究它的时候发现
Fedora的yum源里已经有docker-io
包了,所以不试白不试……
它与虚拟机最大的不同在于,虚拟机一般工作在机器码级别,会模拟出整 个硬件环境,包括独立的CPU和IO设备等,所以虚拟机映像一般比较大而且运行 速度没有原生程序快;而Docker提供的容器只是在操作系统层面模拟出一 个独立的应用环境——像是提供特定的二进制程序和库文件——而其他基础设施, 像硬件和驱动程序之类的依然用的是宿主系统那一套,而且应用和宿主操作系 统之间没有任何抽象层,应用代码是直接在宿主CPU上跑的。Docker的实现有点 像chroot,但是更精细一些,还涉及到进程命名空间和许多其他细节——对 这些细节感兴趣的同学请移步到dotCloud的PaaS Under the Hood系列文 章。
由此可见,Docker要比虚拟机更轻量级,只需要一次性通过宿主操作系统 设定容器的环境就够了。但是宿主系统必须支持容器操作,而且通过Docker打 包的应用要满足宿主系统的执行要求,例如PowerPC程序就不能在x86宿主上执 行。也就是说,Docker为了轻量化,抛弃了虚拟机独立于硬件和操作系统的优 势。
上手搭建Redmine
我用的Redmine是这个版本,google的第一个结果XD. 这货的“Quick Start” 实际上是start不起来的,因为数据库其实要自己另外装……所以在这把我自己的 步骤记下来。
-
下载数据库容器映像:
1
$ docker pull sameersbn/mysql:latest
-
在宿主系统上建立数据库目录:
1 2 3
$ mkdir -p /where/ever/you/like/mysql $ # 如果宿主机上有跑SELinux的话,还要改一下目录的类型,否则会Permission denied: $ sudo chcon -Rt svirt_sandbox_file_t /where/ever/you/like/mysql
-
启动数据库容器:
1 2
$ docker run --name mysql -it --rm \ -v /where/ever/you/like/mysql:/var/lib/mysql sameersbn/mysql
-
进入MySQL的控制台给Redmine指定一个用户,并创建数据库:
1
$ docker run -it --rm --volumes-from=mysql sameersbn/mysql mysql -uroot
-
下载Redmine容器映像:
1
$ docker pull sameersbn/redmine:latest
-
在宿主系统上建立Redmine配置目录:
1 2
$ mkdir -p /where/ever/you/like/redmine $ # 同样,如果宿主机上有跑SELinux的话,这里还要改一下目录的类型,参考第2步。
-
启动Redmine容器:
1 2 3
$ docker run --name=redmine -p 10080:80 -it --rm --link mysql:mysql \ -e "DB_USER=redmine" -e "DB_PASS=password" -e "DB_NAME=redmine_production" \ -v /where/ever/you/like/redmine:/home/redmine/data sameersbn/redmine
这时访问http://localhost:10080
,就可以看到部署好的Redmine界面了。
上面的部署过程为数据库和Redmine分别建立了一个容器,而且每个容器的数
据保存路径都用-v
参数映射到宿主的文件系统上,这是Docker容器常见的部
署模式。
为什么要进行目录映射呢?因为Docker的容器映像在运行时是只读的。例 如我们有一个映像A,然后使用这个映像运行了一个容器C,那么运行时对容器 内容的修改只存在于容器C中,映像A是不会发生改变的。假设我们想要保存对 容器C的修改,就要将修改内容commit到一个新的映像中。但是如果我们 进行了目录映射,修改内容就可以直接保存在宿主的文件系统上,不需要在每 次退出容器后都进行一次commit.
至于其他的参数,其实不难理解,请参考Docker文档。