作为一个 freelancer,经常能够接到很多的开发工作,这些金主,有喜欢 PHP 的,有习惯撒手不管的;有偏好 sqlite 的,也有喜欢 PG 的,我甚至见过 mysql、PG 一起使用的项目;同一门语言下,使用的框架也不尽相同,有用 CI 的,也有用 Yaf 的。
在平时开发时,我有一台 10 年(或者是 11 年)的 thinkpad E50,在家里当作 linux 服务器,还有一个 rMBP 来做开发和展示用。对于一般的开发工作,他们两个的环境还是比较类似的,但是(权利的游戏里说的, “but”之前的,都是放 P),在一些特殊场景下,他们的差别还是让人很不爽 (比如 ubuntu 下装 yaf 和 OS X 下并不相同;在 coffee 查找路径也有细微区别,尤其是在 brew 跟着操作系统升级之后……)。这些差别虽然不大,但是在某个项目上,还是花费了我一些时间来搭建环境。
最近研究了一下 docker,然后发现 docker 可以很完美的解决在开发时由于宿主机差异造成的环境问题(线上环境我没试过,其实我也没线上环境), 下面我演示一下在 linux 宿主机上,从 0 开始搭建一个开发环境需要的 docker 镜像并到处的过程。
docker 安装
按照 https://docs.docker.com/ 的介绍安装即可。当然,如果你使用 ubuntu,那么执行下面的命令就好了:
sudo apt-get install docker.io
从网络上 Pull 一个 docker 镜像下来
忽略你从网上看到的各种教程吧,直接使用下面这个命令(如果你不是 root 用户,别忘记加 sudo)
docker pull ubuntu
经过或长或短的一段时间,你会从 docker 官方拉一个 ubuntu 的镜像到你磁盘上。你可以使用
docker images
看到它, 像这样:
启动下载的镜像,并进入运行该镜像的容器
使用 run 命令,启动对应的镜像
docker run -itd ubuntu
然后使用 ps 命令,找到刚才启动的容器 ID,在使用 attach 命令,进入该容器(注意截图中 attach 的参数,就是 ps 列出的容器的 ID)
安装开发环境需要的软件
这一步的具体操作,取决于你需要的开发环境都有哪些,我一般会安装 nginx、php5-fpm、mysql、mongodb、redis 和 python 的环境,使用 apt-get 安装(别忘了先 apt-get update) 即可。当然还会有一些其他操作,比如 nginx 的配置,这些和平时在 liunx 上安装服务是一样的。
等你安装完了环境,先不要着急 stop 掉对应容器。
保存更改的容器
上一步修改容器之后,如果直接关掉容器,这些改动不会在下次启动时保留,所以需要把它存储到本地另外一个镜像中。
方法很简单,同样需要 attach 那一步获取的 ID
docker commit 028ce7fa5596 ptj:dev
我把我本地的镜像,取名叫做 "ptj:dev", 这里名字你可以随便起。
现在你可以放心的停掉前面的容器了:
docker stop 028ce7fa5596
然后我们再使用 images 命令,看一下 docker 镜像:
ptj:dev 现在已经在我们磁盘上了。
增加启动服务、端口映射
现在“ptj:dev" 里面有了我们开发所需要的软件,但是并不能让 nginx、mysql 这些服务自动启动,下面需要把 ptj:dev 中的服务,随镜像一起启动。
具体步骤虽然繁琐,但是也不困难。
1. 新建一个目录,我们就叫它 ptj
mkdir ptj ; cd ptj
2. 在目录下,新建两个文件
touch Dockerfile start.sh
Dockerfile 告诉 docker 怎么制作一个镜像, start.sh 是我们自己的启动脚本
3. 将需要启动的 services 写入 start.sh,然后在最后加上"/bin/bash"
#!/bin/bash
service nginx start
service mysql start
service php5-fpm start
service mongodb start
service redis-server start
/bin/bash # 最后这行千万不要漏
4. 从 ptj:dev 复制镜像,并且将 start.sh 放入镜像内,自动启动
From ptj:dev
ADD start.sh /usr/local/start.sh
RUN chmod +x /usr/local/start.sh
EXPOSE 80 22 3306 6379 27017
CMD ["/usr/local/start.sh"]
From 那行,代表从哪个镜像复制
ADD 表示把文件放入镜像
RUN 需要把 start.sh 变为可执行
EXPOSE 是暴露 docker 内的端口给宿主机,将来可以通过 -P 让宿主机访问 docker 内的服务
CMD 则是指明了该镜像需要执行的程序
5. 制作新镜像
在我们前面的 ptj 目录下,执行一条指令即可:
docker build -t ptj .
启动新镜像,检查服务是否运行正常
再次祭出 images 命令:
可以发现 ptj 下面多了一个 latest, 这个就是我们刚才修改的镜像;
使用前面介绍的 run、 attach,看看我们服务运行的情况:
可以看到我们的服务已经全部随着镜像的启动运行起来了。
剩下的就是把 docker 导出成 tar 包,在不同机器之间拷贝、导入然后开发了。