docker模拟多机环境


Docker基础

这里不多说,借助docker官方文档可以学习到大部分内容,而且很详细。

本次配置中用到的镜像:

并且使用docker-compose来管理容器,它在pdf文档中有介绍,这里不再赘述。

多机结构

为了实现一台真机模拟多台机,引入逻辑主机的概念。例如现在只有一台云主机,但是我们又要把测试环境(dev)正式环境(online)分开。

以下是项目完成后的目录结构,每一个目录对应一个逻辑主机 和独立数据卷

.
├── dev
│   ├── docker-compose.yml
│   └── php
│       └── Dockerfile
├── online
│   ├── docker-compose.yml
│   └── php
│       └── Dockerfile
└── _self
    └── docker-compose.yml

这里需要做以下说明:

  • 测试环境(dev)正式环境(online) 除了数据卷 不一样,其他配置都一样
  • _self 目录表示宿主主机,上面有nginx

dev 配置

dev 环境下有php和mysql,两个app都在独立的容器中,两者通过 sock文件 或网络进行通信,以下是dev环境的docker-compose.yml 文件内容:

php1:
    #build: ./php
    #image: php:7.1-fpm-alpine
    image: php-fpm-composer:1.0
    container_name: dev_php1
    expose:
        - "9000"
    volumes:
        - "/data-dev/data1/:/data1/"
        - "/data-dev/data2/:/data2/"
        - "/data-dev/data2/php/conf/:/usr/local/etc/"
    links:
        - mysql1:server_mysql

mysql1:
    image: mysql/mysql-server:5.7.20
    container_name: dev_mysql1
    expose:
        - "11308"
    volumes:
        - "/data-dev/data1/:/data1/"
        - "/data-dev/data2/:/data2/"
        - "/data-dev/data2/mysql/conf/:/etc/mysql/"
    environment:
        - MYSQL_ROOT_PASSWORD=123456789

volumes

先看数据卷。以 dev_php1 容器为例,我们可以看到 宿主/data-dev/data1/data-dev/data2 被映射到了php容器的/data1/data2 目录。是的,宿主的/data-dev 目录就是专门为dev 环境划分的逻辑目录。

再看dev_mysql1 容器,道理和上述一样。

端口配置

先看dev_php1,根据 php-fpm 配置文件中监听了9000 端口,所以开放容器的9000端口。

mysql 配置文件中设置的是11308 端口,所以我们开放容器的11308 端口。

其实在实际使用中,两者也都支持 sock文件方式进行连接。

自定义的php镜像

由于官方的php缺少一些扩展,所以我基于该镜像添加了扩展和compose,Dockerfile如下:

FROM php:7.1-fpm-alpine
RUN apk add --no-cache \
        libpng-dev \
    && docker-php-ext-install pdo_mysql gd zip \
    && php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \
    && php -r "if (hash_file('SHA384', 'composer-setup.php') ===                                                                  '544e09ee996cdf60ece3804abc52599c22b1f40f4323403c44d44fdfdd586475ca9813a858088ffbc1f233e9b180f061') { echo 'Installer verified';  } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" \
    && php composer-setup.php --install-dir=/usr/local/bin --filename=composer \
    && php -r "unlink('composer-setup.php');"

为了避免构建多层镜像又保证命令的整洁性,使用 \ (表示换行)把要执行的命令分开。

可以看到我这里添加了pdo_mysqlgdzip 扩展,其中zip 镜像是安装compose必要的,且为了安装gd 扩展,系统必须要先安装libpng-dev 库。

后面四行命令是安装composer的,安装后放在了/usr/local/bin 目录下,文件名是composer

根据这个Dockerfile构建了名为php-fpm-composer:1.0 的镜像。

其他配置

dev_mysql1MYSQL_ROOT_PASSWORD 表示数据库初始密码,如果数据库初始化过了(数据卷中已有数据)则没效了。

online配置

online 环境的docker-compose.yml 文件内容如下:

php1:
    #build: ./php
    #image: php:7.1-fpm-alpine
    image: php-fpm-composer:1.0
    container_name: online_php1
    expose:
        - "9000"
    volumes:
        - "/data-online/data1/:/data1/"
        - "/data-online/data2/:/data2/"
        - "/data-online/data2/php/conf/:/usr/local/etc/"
    links:
        - mysql1:server_mysql

mysql1:
    image: mysql/mysql-server:5.7.20
    container_name: online_mysql1
    expose:
        - "11308"
    volumes:
        - "/data-online/data1/:/data1/"
        - "/data-online/data2/:/data2/"
        - "/data-online/data2/mysql/conf/:/etc/mysql/"
    environment:
        - MYSQL_ROOT_PASSWORD=123456789

部署步骤

可以看到online 环境除了逻辑目录/data-onlie 以外,其他的配置都和dev 一样,当然容器名是不一样的。

如果我们已经成功部署了dev 环境,那么只需把/data-dev copy一份为 /data-online 即可完成数据卷的部署,保证online的数据和dev是一样的(主要是php、mysql等app的配置一样)。

nginx的配置

本项目采取的方式是nginx 单例,所以nginx必须放在宿主主机上,稍后讨论多例nginx的配置。

目前已经有了devonline 两个环境,且分别运行了php和m ysql,单例nginx模式的架构如下:

圆圈 表示逻辑主机矩形框 内是英文的表示容器,英文表示容器名称。

宿主环境 (nginx)的docker-compose.yml 文件内容如下:

nginx1:
    image: nginx:1.12-alpine
    container_name: nginx1
    ports:
        - "80:80"
        - "443:443"
    expose:
        - '80'
        - '443'
    volumes:
        - "/data/:/data/"
        - "/data1/:/data1/"
        - "/data2/:/data2/"
        - "/data2/nginx/conf/:/etc/nginx/"
        - "/data-dev/:/data-dev/"
        - "/data-online/:/data-online/"

可以看到,为了devonline 提供服务,需要将两个逻辑主机数据目录 映射到nginx容器中去,从而达到nginx与宿主主机的文件系统是一样的。

文件路径

在进行nginx配置的时候,需要非常注意的是文件路径。

dev 逻辑主机中,网站根目录是/data1/sites/html,这个目录对应于宿主主机的/data-dev/data1/sites/html ,那么在nginx中配置的时候,就需要特别注意。

下面是nginx 为dev 环境提供服务所写的配置信息:

...
    listen 80;
    server_name dev.domain.com;
    root /data-dev/data1/sites/html/;
    index index.html index.htm index.php;

    access_log  /data2/nginx/logs/dev/html_access.log  main;
    error_log  /data2/nginx/logs/dev/html_error.log  warn;


    # use php-fpm.sock
    location ~ \.php$ {
        fastcgi_pass   unix:/data-dev/data2/socks/php-fpm.sock;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  /data1/sites/html$fastcgi_script_name;
        include        fastcgi_params;
    }
...

由于nginx运行在宿主主机,所以使用的是宿主主机的文件系统:(下面的/data2 是宿主主机上的)

root /data-dev/data1/sites/html/;
access_log  /data2/nginx/logs/dev/html_access.log  main;
error_log  /data2/nginx/logs/dev/html_error.log  warn;

根据web请求流程和CGI原理,所以fastcgi在寻找文件时使用的是 dev 主机的文件系统:

fastcgi_param  SCRIPT_FILENAME  /data1/sites/html$fastcgi_script_name;

注意:不能写成$document_root$fastcgi_script_name,因为$document_root是宿主主机的文件系统

静态文件测试

根据上述配置文件,配置好root 路径即可进行静态文件测试。

现有两个文件,他们在宿主主机 文件系统中的路径如下:

/data-dev/data1/sites/html/index.html
/data-online/data1/sites/html/index.html

可以看到,一个在 dev 中,一个在 online 环境中

那么在dev 的文件系统中,则是:

/data1/sites/html/index.html

文件内容是:

This is dev

online 的文件系统中,则是:

/data1/sites/html/index.html

文件内容是:

This is online

可以发现,在两个逻辑主机中,他们并不知道宿主主机的存在,也就是宿主主机对于他们来说是透明的

/etc/hosts配置如下,同步修改nginxserver_name

127.0.0.1 dev.domain.com
127.0.0.1 online.domain.com

进行测试:

curl dev.domain.com
curl online.domain.com

输出:

This is dev
This is online

php测试

php的测试主要看nginx是否正确使用了对应环境的php-fpm.sock,如果你是用9000端口通信的,那就看ip是否填对了,方式与静态页面类似,不再赘述。

总结

详情:https://github.com/JerryCheese/docker-architecture


文章作者: jerrycheese
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 jerrycheese !
  目录