Docker: 使用容器技术快速搭建独立WordPress环境

现在Docker CI 什么的这么火,我也赶紧学一套。熟话说,学以致用,那么我就把自己使用的wordpress-nginx-php-mysql一套容器化了。

Docker是目前最火的开源容器解决方案。你把他理解为基于软件层面的虚拟机技术,类似于目前安卓平台的双开,多开软件的实现效果。

阅读此文,你需要先学习基本的docker知识,docker-compose脚本的编写。


分析:

整个服务器主要分了三块,一个是web服务器,一个是php,最后是mysql。也就是需要创建3个Docker容器来存放这3部分,当然你喜欢的话也可以塞一起,但不推荐这么做。

基础镜像

现在我们需要找几个合适的基础镜像用于构建容器

  • 1.web服务器用的是nginx,直接使用了官方仓库的最新版本(hub.c.163.com/library/nginx:latest)
  • 2.php-fpm模块不能直接使用官方的,因为php-fpm还需要安装php-mysql模块,直接用官方的话没办法连接数据库的,所以github上找了一个第三方库(nanoninja/php-fpm) 这个库用的人很多,而且脚本是开源并基于此自动构建的,所以还是很安全的。
  • 3.mysql的话也可以直接用官方仓库的

配置容器

现在容器有了,但这些容器实例化后使用的都是默认的配置,你想一个刚安装好的nginx跑起来后你能访问什么页面,貌似就一个欢迎页面吧。
我们可以使用docker的links功能,将我们宿主机上的已经写好的配置文件映射到容器内,或者直接拷贝到容器内部

  • 1.一个ngixn服务器配置,你需要提供一个default.conf配置文件,包含了你的网站的一些配置,比如域名啊,端口号啊,网站根路径啊

参考配置

#监听80端口(也就是http) 重写url 全部跳转到https
server {
    listen 80 ;
    server_name blog.coderstory.cn;
    rewrite ^(.*) https://$server_name$1 permanent;
}
#监听443端口(也就是https)
server {
    server_name blog.coderstory.cn;
	
    #配置网站根目录
	root /var/www/html/htdocs;
	
    #配置网站的首页
	index index.html index.htm index.nginx-debian.html;
    #location ^~ /.well-known/acme-challenge/ {
	#	alias /var/www/html/.well-known/acme-challenge/;
    #    try_files $uri =404;
    #}

    # 配置URL重写 解决wp中文章页404
	location / {  
        if ($http_user_agent ~* (Scrapy|Curl|HttpClient)) {  
			return 403;  
        }  
		#禁止指定UA及UA为空的访问  
		if ($http_user_agent ~ "CPython|python|Firefox/29.0|FeedDemon|JikeSpider|Indy Library|Alexa Toolbar|AskTbFXTV|AhrefsBot|CrawlDaddy|CoolpadWebkit|Java|Feedly|UniversalFeedParser|ApacheBench|Microsoft URL Control|Swiftbot|ZmEu|oBot|jaunty|Python-urllib|lightDeckReports Bot|YYSpider|DigExt|YisouSpider|HttpClient|MJ12bot|heritrix|EasouSpider|LinkpadBot|Ezooms|^$" )  {  
		  return 403;  
		}  
		#禁止非GET|HEAD|POST方式的抓取  
		if ($request_method !~ ^(GET|HEAD|POST)$) {  
		  return 403;  
		}  
		if (-f $request_filename/index.html){
			rewrite (.*) $1/index.html break;
        }
        if (-f $request_filename/index.php){
            rewrite (.*) $1/index.php;
        }
        if (!-f $request_filename){
            rewrite (.*) /index.php;
        }
        #检查url是否合法(是否存在) 不存在的返回404页面
		try_files $uri $uri/ =404; 
	}
	
     #配置URL重写 后台管理页面404的问题
     rewrite /wp-admin$ $scheme://$host$uri/ permanent;
	 
     #配置PHP页面的处理方法 转发到php
    location ~ \.php$ {
		fastcgi_pass  php7.1:9000;
        add_header Strict-Transport-Security max-age=63072000;
        add_header X-Frame-Options DENY;
        add_header X-Content-Type-Options nosniff;
	    try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }

    #SSL 配置段 包括开启ssl 监听端口 以及证书路径
    listen 443 ssl http2 default_server;
    ssl on;
    ssl_certificate /var/www/html/mypem.pem;
    ssl_certificate_key /var/www/html/mykey.key;
    ssl_prefer_server_ciphers on;
    ssl_dhparam /var/www/html/dhparam.pem;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4";
    keepalive_timeout 70;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m; 
    #ssl_stapling               on; 
    #ssl_stapling_verify        on;
    ssl_trusted_certificate /var/www/html/chain.pem;
    #add_header Public-Key-Pins 'pin-sha256="TOBBREP700HCbZjmW8CUdvJCjF/Nsz8Hrt4GhqQAXdk="; max-age=2592000; includeSubDomains';
}


  • 2.php模块默认不需要额外的配置,自动监听9000端口
  • 3.mysql数据库也不需要额外的配置,默认的数据库访问用户名密码什么的都是动态配置的

当然,如果你想自定义一些额外的配置,则你只要提供相应的配置文件,然后在构建容器的时候复制到容器内部就行了。



构建docker-compose.yml

因为整个项目包含了三个容器,每次开启关闭都是操作三次比较麻烦,所以需要一个统一管理工具docker-compose。
它可以批量化的处理多个容器。

docker-compose需要自己写一个配置文件.配置文件并不多,参考如下配置你可以看到一共定义了三个容器:nginx mysql php7.1

容器定义又包含如下属性:

1.image 表是引用的镜像来源

2.ports 表是端口映射,比如 - "80:80" 表是绑定宿主机的80端口和容器nginx的80端口,访问宿主机的80端口就等于访问nginx上的80端口

3.volumes 表是挂载数据卷,宿主机上的指定文件会共享到容器中,如果容器中已经存在则覆盖,你可以理解为引用关系。有些带了 ":ro" 的后缀,表是这个是只读挂载,容器中能查看这个文件但不能修改。

4.environment 是用来设置环境变量的

5.expose 表示开放端口,但这个端口只能在容器间访问,外部是访问不到的。

version: '2'
services:
  nginx:
    image: hub.c.163.com/library/nginx:latest
    ports:
      - "80:80"
      - "443:443" 
    volumes:
      # 挂载网站的目录
      - ./app:/var/www/
      # 挂载日志目录
      - ./docker/logs:/var/log/nginx/
      # nginx configs
      - ./docker/nginx/:/etc/nginx/:ro
      - ./docker/letsencrypt:/etc/letsencrypt:ro
  mysql:
    image: hub.c.163.com/library/mysql:latest
    expose:
      - "3306"
    volumes:
      - ./docker/mysql:/var/lib/mysql
    environment:
      - MYSQL_DATABASE=wpp
      - MYSQL_USER=root
      - MYSQL_PASSWORD=password
      - MYSQL_ROOT_PASSWORD=password
  php7.1:
    image: nanoninja/php-fpm
    links:
      - mysql
    volumes:
      # app
      - ./app:/var/www/
      # log
      - ./docker/logs:/var/log/
      - ./docker/php:/etc/php/

整个配置的目录结构
app目录是网站的目录,chained.pem之类的是ssl的证书,htdocs才是网站主题的根目录
config下包含了nginx配置,数据库目录以及日志目录
docker-compose.yml是构建配置文件

coderstory@jdu4e00u53f7:~/dockerfile$ tree -L 3
.
├── app
│   └── html
│       ├── chained.pem
│       ├── chain.pem
│       ├── dhparam.pem
│       ├── htdocs
│       ├── mykey.key
│       └── mypem.pem
├── config
│   ├── logs
│   │   ├── access.log
│   │   └── error.log
│   ├── mysql
│   │   ├── auto.cnf
│   │   ├── debian-5.7.flag
│   │   ├── ib_buffer_pool
│   │   ├── ibdata1
│   │   ├── ib_logfile0
│   │   ├── ib_logfile1
│   │   ├── ibtmp1
│   │   ├── mysql
│   │   ├── performance_schema
│   │   ├── sys
│   │   └── wp
│   └── nginx
│       └── default.conf
└── docker-compose.yml

创建容器实例

终端下执行

docker-compose up

它会自动下载相应的镜像并创建实例,创建网络,映射文件等等。。。

coderstory@jdu4e00u53f7:~/dockerfile$ docker-compose up
dockerfile_mysql_1 is up-to-date
dockerfile_php7.1_1 is up-to-date
dockerfile_nginx_1 is up-to-date
Attaching to dockerfile_mysql_1, dockerfile_php7.1_1, dockerfile_nginx_1
mysql_1   | 2017-10-14T05:34:23.143720Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
mysql_1   | 2017-10-14T05:34:23.145248Z 0 [Note] mysqld (mysqld 5.7.18) starting as process 1 ...
mysql_1   | 2017-10-14T05:34:23.152471Z 0 [Note] InnoDB: PUNCH HOLE support available

参考

docker-compose配置
https://github.com/nanoninja/docker-nginx-php-mysql
网易docker
https://c.163.com/hub