Mac使用Docker快速构建Nginx+PHP开发环境

一、前言

为什么要用docker构建,直接在主机上装一个nginx和一个php不就行了吗。

其实如果是单机应用,这样做自然可以。但是我们后面用到的基本都会做负载均衡,包括Nginx、PHP、MySQL、RabbitMQ、Consul、Keepalived、Haproxy等等。

甚至于说多个Nginx、多个PHP可能安装在不同的主机上,这样为了保证环境的一致,且高效快速安装,使用docker镜像无疑是最好的选择。

当然,我们也可以通过dockerfile构建镜像,或者通过docker-compose编排一组服务,不过这里我们为的就是速度,因此我们直接使用已经构建好的镜像。

 

二、准备工作

1、拉取Nginx镜像
docker pull haveyb/nginx
docker tag haveyb/nginx nginx1.21
docker rmi haveyb/nginx
2、拉取PHP镜像
docker pull haveyb/php
docker tag haveyb/php:latest php7.4:latest
docker rmi haveyb/php:latest
3、创建网络,用于nginx容器和php容器的网络连接
docker network create --driver bridge haveyb

当然,直接通过ip地址连接也可行,但是既然使用了docker,还是追求灵活,ip可能会变,但容器名称不会变。

4、添加测试站点的hosts解析
sudo vi /etc/hosts

127.0.0.1     test.cn

因为这里直接把macbook作为docker容器的宿主机,所以我们这里的ip填写的就是127.0.0.1 test.cn

如果nginx容器并不是直接在mac上,而是在mac的虚拟机上的linux环境,我们这里添加的记录就应该填写为 容器所在虚拟机的ip,举例192.168.78.200 test.cn

 

三、构建PHP环境

1、创建PHP容器
docker run -itd --name php74 --privileged -p 9000:9000 -v /Users/SH-Server:/data php7.4
2、将PHP容器加入我们创建的网络
docker network connect haveyb php74
3、创建测试文件index.php
# 这里进入的是宿主机目录,因为已经做宿主机和容器的目录映射了,在这里编辑就相当于在容器内的/data目录下编辑
cd /Users/SH-Server
vi index.php
<?php
phpinfo();

wq保存成功后,通过exit命令退出容器,返回宿主机

 

四、构建Nginx环境

1、创建Nginx容器
docker run -itd --name nginx1.21 --privileged -p 80:80 -p 443:443 nginx1.21

说明:这里本来是想将nginx的conf通过-v映射到Mac上的目录的,但是不论是用直接目录映射还是数据卷挂载都不行,其中有nginx的问题,也有Mac自身的问题,因为在Linux环境虽然不能直接通过目录映射,但是是可以通过数据卷挂载方式来映射的,但是Mac上这两种方式都不行,所以只能进入容器内部来修改了,这种无法进行目录映射的情况当前仅出现在nginx镜像上,当然也有方式解决,就是把Mac上映射目录和Nginx容器内的映射目录的用户名和用户组都改为一模一样,但我懒( ̄▽ ̄)~*

2、将Nginx容器加入我们创建的网络里
docker network connect haveyb nginx1.21
3、编写Nginx配置文件nginx.conf
docker exec -it nginx1.21 bash
cd /etc/nginx
vi nginx.conf

worker_processes  4;
error_log  logs/error.log  error;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;

    server {
        listen       80;
        server_name  localhost;
        error_page   500 502 503 504  /50x.html;

        location = /50x.html {
            root   html;
        }

        location ~ /\.ht {
            deny  all;
        }
    }
    include /etc/nginx/conf.d/*.conf;
}
4、创建conf.d目录及测试站点配置文件
mkdir -p /etc/nginx/conf.d
cd /etc/nginx/conf.d
vi test.conf

server {
    listen       80;
    server_name  test.cn;

    client_max_body_size 128M;

    error_log logs/error.log warn;

    charset utf-8;

    root   /data;
    index  index.html index.htm index.php;

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ ^/assets/.*\.php$ {
        deny all;
    }

    location ~ \.php$ {
        fastcgi_pass   php74:9000;
        fastcgi_index  index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }

    location ~ /\.ht {
        deny  all;
    }

}

这里有一个点要注意,如果是php文件,因为其处理已经被php接管了,所以其读取的文件目录就是php容器的/data目录;如果不是php文件,则读取的是nginx容器的/data目录。

当然,实际生产环境,这两个目录读取的一定是一个项目目录,但测试部署调试时这块如果不注意,可能就会忽略掉。

5、重启Nginx容器,以加载配置
docker restart nginx1.21

 

五、查看结果

在电脑访问 test.cn

 

六、php.ini 在哪里

# /usr/local/etc 目录
|-- pear.conf
|-- php
|   |-- conf.d
|   |   |-- docker-php-ext-sodium.ini
|   |   |-- extension-gd.ini
|   |   |-- extension-igbinary.ini
|   |   |-- extension-memcached.ini
|   |   |-- extension-mongodb.ini
|   |   |-- extension-msgpack.ini
|   |   |-- extension-redis.ini
|   |   |-- extension-sockets.ini
|   |   |-- extension-swoole.ini
|   |   |-- extension-yar.ini
|   |   |-- extension-zip.ini
|   |   `-- extension-zstd.ini
|   |-- php.ini-development
|   `-- php.ini-production
|-- php-fpm.conf
|-- php-fpm.conf.default
`-- php-fpm.d
    |-- docker.conf
    |-- www.conf
    |-- www.conf.default
    `-- zz-docker.conf

可以看到,其实通过docker拉取的php镜像,默认是不带php.ini这个文件的,但用源码编译其实本身也是不带的,都是后面我们人为地通过 cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini 来创建一个php.ini文件。之后我们进行的相关配置都可以在php.ini中进行添加修改,php会自动加载该php.ini文件。

但是需要说明的是为了添加及修改PHP扩展操作起来方便及清晰,后添加的PHP扩展一般不写在php.ini文件里,而是写在了/usr/local/etc/php/conf.d目录下。当然,写在php.ini文件里也是可以的。

 

七、注意-如果报错:

如果报502,极大概率是nginx和php网络通信问题,我们可以尝试将nginx配置文件中的fastcgi_pass 由原来的通过容器名指定改为通过ip指定。

fastcgi_pass   php74:9000;

改为:

# 这里的192.168.78.200是我的虚拟机的网络ip,如果直接在mac上创建的容器,一般不会出现该问题。
fastcgi_pass   192.168.78.200:9000;

另外,也可能是防火墙的问题,或者尝试将虚拟机中的docker重启 systemctl restart docker