docker搭建并部署LNMP环境(二)

上一篇blog介绍了nginx的部署,这篇将介绍php和mysql的部署和容器的连接。

php-fpm

因为php运行时可能会用到很多外部扩展,所以Dockerfile文件会复杂一些:

1
2
3
4
5
6
7
8
9
10
11
12
FROM php:5.6-fpm

ADD php.ini /usr/local/etc/php/php.ini
ADD php-fpm.conf /usr/local/etc/php-fpm.conf

RUN apt-get update && apt-get install -y \
libfreetype6-dev \
libjpeg62-turbo-dev \
libpng12-dev \
&& docker-php-ext-install pdo_mysql \
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
&& docker-php-ext-install gd

其中命令docker-php-ext-install可以方便地安装php等常用扩展。

mysql

mysql的安装较简单,因为一般的需求在官方的镜像里都已经被实现了,直接继承官方镜像便可,目录文件应该映射到本地,否刚容器一旦停止,所有的数据文件就丢失了。
有一点要注意的是,如果是在mac上用boot2docker,以挂载工作目录的方式来run mysql的镜像:

1
docker run  -v /opt/data/mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -it mysql

会报错:

1
[ERROR] Can't open the mysql.plugin table. Please run mysql_upgrade to create it.

需要在Dockerfile中加入一句:

1
RUN usermod -u 1000 mysql && chown mysql.mysql /var/run/mysqld/

容器的连接

因为容器与容器之间是相互隔离的,没有办法直接通讯,如果要建立容器间的通信,可以给每个容器做端口映射的方法,但是这样就背离了docker“隔离”的思想。好在docker原生提供了link(连接)方法,使容器间的通信变得简单和安全。
容器连接的命令格式为:

1
--link container_name:alias

要进行nginx和php的连接,先启动php的container,—name指定该容器的名字:

1
docker run -d --name php -v /opt:/opt  zyeee/php-fpm

然后启动带着连接指令的nginx容器

1
docker run -p 80:80 -v /opt:/opt -d --link php:php zyeee/nginx

这里指定别名的作用是,docker会把php所在容器的ip以host的形式写入到nginx容器的/etc/hosts里,还会在nginx的环境变量中添加有关php的信息。另外要注意的是,在nginx的fastcgi的设置里,要把fastcgi_pass从127.0.0.1:9000改为php:9000,因为此时php-fpm服务并不是运行在本地。
通过这样的连接,我们就有了一个非常安全的模型,在这个模型里,容器化的应用程序限制了可被攻击的界面,减少了公开暴露的网络。

Docker-compose

如上所示,nginx和php的连接只是一个简单的例子,如果要连接的容器多的话每回启动的连接指令将会非常繁琐。好在官方提供了compose工具,可以通过yaml文件来一键管理构建运行所有的容器。
docker-compose的安装不难,通过pip一条指令就可以:

1
pip install docker-compose

因为这个工具是python写的,所以实际运行起来碰到了一些问题,基本上是由于python的版本不同导致,在较新的linux发行版上一般都能够直接运行,在这里记录一下遇到的问题。

osx

osx直接安装执行docker-compose后会报ImportError: cannot import name _thread,通过trace知道是mac自带python的six扩展引起了这个问题。于是强制重装了python和six之后问题解决。

1
2
3
brew reinstall python
pip install --ignore-installed six
pip install --ignore-installed docker-compose

centos6.6

因为用的VPS预装的是centos6.6的系统,所以也遇到了不少坑。首先运行的时候会提示缺少很多第三方的包,比如说enum34, requests之类,但是通过pip list又能够看到这些包已经被安装。尝试后发现把这些报缺失的包用easy_install的方式安装一遍,就能够正常运行,easy_install会在指定目录生成一个.egg文件。

关于这个版本的系统还有一个坑,就是如果用自带的源yum安装docker只能安装到1.7.1版本的,而docker-compose最低要求是1.9.1的docker版本。所以只能到github上clone源码包来编译。但是在编译安装完成后docker daemon &来启动docker服务的时候会报Devices cgroup isn't mounted的错误。经过google发现,这是因为默认的cgroup的cpu,memory等没有被挂载,需要使用一个脚本来挂载,具体使用脚本是https://github.com/tianon/cgroupfs-mount/blob/master/cgroupfs-mount

正常运行后就可以开始编辑YAML文件了,YAML文件非常简明易懂,一个简单的demo如下 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
nginx:
build: ./nginx
ports:
- "80:80"
links:
- "php"
volumes:
- /opt:/opt

php:
build: ./php
links:
- "mysql"
volumes:
- /opt:/opt

mysql:
build: ./mysql
volumes:
- /opt/data/mysql:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: 123456

如此写好之后,运行docker-compose up,就能完成所有的挂载和连接操作。(加入-d可在后台运行)
综上,一个简音的docker运行环境就已经搭建好了,所有服务也已经正常运行。
把如下代码加进/etc/rc.local后就可以开机自动启动了。

cd /home/zhuye/docker
./cgroupfs-mount.sh >> /tmp/error
docker daemon & >> /tmp/error
su - zhuye -c "cd /home/zhuye/docker && docker-compose up -d"

以上docker的全部配置代码在github