M1 Docker PHP 开发环境搭建(容器独立方式)


M1 Docker PHP 开发环境搭建(容器独立方式)

Docker 下载 安装步骤省略
Docker 官方镜像库

PHP(7.0)+MySQL(8.0)+Nginx+Redis(单实例)/Redis集群

??????注意??????

声明:

  1. 本文中出现的huoxiao文件夹为本人电脑用户目录。
  2. 本文中出现的 192.168.1.68 为本人在指定网络下的内网固定IP,请勿混淆。

所有镜像拉取前需要注意支持 ARM64

docker run 命令的常用参数如下:

  • -d:创建自动式守护容器(后台运行)
  • -i:以交互模式运行容器,通常与 -t 一起使用
  • -t:为容器重新分配一个伪输入终端,通常与 -i 一起使用
  • -p:指定端口映射
  • -P:随机端口映射
  • -v:目录(文件夹)映射
  • -name:容器名
  • --privileged:true=提权 默认: false

1. PHP (本人是拉取的php-fpm-7.0镜像)

这里可能会有人担心本地代码是5.x版本,高版本能否适用?

首先, 只要你高于你本地代码要求版本就没有问题,官方兼容
其次, 此方式搭建环境是本人目前正在使用的方式

    docker pull php-fpm-7.0
    
    docker run -dit --name=php-fpm-7.0 -p 9000:9000 -P -v /Users/huoxiao/Documents/data/dev/:/data/www/ -v /etc/localtime:/etc/localtime --privileged=true php-fpm-7.0
??命令释义

1. 拉取 php-fpm7.0 镜像(拉取 phpphp-fpm 均可, php-fpm 目前已被 php 集成为官方内容)
2. 创建一个名称为 php-fpm-7.0 的容器

  • 端口映射(宿主机端口:容器端口 注意 -p 和 -P 区分大小写, 且含义不一)
  1. -p 9000:9000
  2. -P 随机端口映射 备用端口, 可在需要其它端口情况下, 直接取用
  • 目录映射方式(即 本地目录:容器目录)如下:
  1. 项目目录:-v /Users/huoxiao/Documents/data/dev/:/data/www/
  2. 宿主机时间:-v /etc/localtime:/etc/localtime
  • 使用镜像:命令最后的参数 php-fpm-7.0
    docker run -dit --name=php-fpm-8.1 -p 9001:9000 -P -v /Users/huoxiao/Documents/data/dev/:/data/www/ -v /etc/localtime:/etc/localtime --privileged=true php:8.1.5-fpm
??本人的另一个 8.0 版本的容器,只需要本地的另外一个端口 9001 映射到容器的 9000 端口即可

2. MySQL

    docker pull mysql/mysql-server
    
    docker run -dit --name=mysql-8.0 -p 3306:3306 -P -v /etc/localtime:/etc/localtime -e MYSQL_ROOT_PASSWORD=密码 --privileged=true mysql/mysql-server
??命令释义

1. 拉取 mysql/mysql-server 镜像(8.0版本,无需担心太高)
2. 创建一个名称为 mysql-8.0 的容器

  • 端口映射、目录映射同PHP方式
  • 需要注意的是在创建MySQL容器时, 需要设置密码, 即参数: MYSQL_ROOT_PASSWORD
  • MySQL的配置文件 my.cnf 可在本地新建后映射到容器中, 本人未映射

3. Nginx

    docker pull nginx
    
    docker run -dit --name=nginx -p 80:80 -p 8088:8088 -p 8089:8089 -P -v /Users/huoxiao/Documents/data/env/nginx/:/etc/nginx -v /etc/localtime:/etc/localtime -v /Users/huoxiao/Documents/data/dev/:/data/www --privileged=true nginx
??命令释义

1. 拉取nginx镜像
2. 创建一个名称为nginx的容器

  • 由于需要本人映射了 80、8088、8089 端口, 根据实际情况按需即可
  • 解释一下为什么把项目目录分别映射到PHP容器和Nginx容器:
    因为 Nginx 服务器负责将 PHP 内容转发到 PHP 容器解析, 而 静态文件(图片、Css、Js等)需要 Nginx 解析
    因此需要分别将项目目录映射到PHP容器和Nginx容器
在这里说明一下 Nginx 与 PHP 容器的通信
location ~ .*\.(php|php5)?$ {
    fastcgi_pass 172.17.0.1:9000; # 使用docker网卡通过端口将php内容转发到php-fpm中
    fastcgi_index index.php; # 入口文件
    include conf/fastcgi.conf; # fastcgi.conf 
}

4. Redis

    docker pull redis
    
    docker run -dit --name=redis-6379 -p 6379:6379 -P -v /etc/localtime:/etc/localtime --privileged=true redis
??命令含义同PHP/MySQL/Nginx

5. Redis集群

需要的文件较多, 以下所需文件需要看清目录, 均是我本地的目录, 注意区分

  1. 运行 redis-cluster-config.sh 将 redis-cluster.tmpl 配置内容批量生成配置文件

redis-cluster-config.sh 内容如下??:

for port in `seq 6391 6396`; do \
  mkdir -p /Users/huoxiao/Documents/data/env/redis/redis-cluster/${port}/conf \
  && PORT=${port} envsubst < ./redis-cluster.tmpl > /Users/huoxiao/Documents/data/env/redis/redis-cluster/${port}/conf/redis.conf \
  && mkdir -p /Users/huoxiao/Documents/data/env/redis/redis-cluster/${port}/data; \
done

redis-cluster.tmpl 内容如下??:

# redis端口
port ${PORT}
#redis 访问密码
# requirepass 密码
#redis 访问Master节点密码
# masterauth 密码
# 关闭保护模式
protected-mode no
# 开启集群
cluster-enabled yes
# 集群节点配置
cluster-config-file nodes.conf
# 超时
cluster-node-timeout 15000
# 集群节点IP host模式为宿主机IP # 注意此处为本机IP
cluster-announce-ip 192.168.1.68 
# 集群节点端口 6391 - 6396
cluster-announce-port ${PORT}
cluster-announce-bus-port 1${PORT}
# 开启 appendonly 备份模式
appendonly yes
# 每秒钟备份
appendfsync everysec
# 对aof文件进行压缩时,是否执行同步操作
no-appendfsync-on-rewrite no
# 当目前aof文件大小超过上一次重写时的aof文件大小的100%时会再次进行重写
auto-aof-rewrite-percentage 100
# 重写前AOF文件的大小最小值 默认 64mb
auto-aof-rewrite-min-size 64mb

# 日志配置
# debug:会打印生成大量信息,适用于开发/测试阶段
# verbose:包含很多不太有用的信息,但是不像debug级别那么混乱
# notice:适度冗长,适用于生产环境
# warning:仅记录非常重要、关键的警告消息
loglevel notice
# 日志文件路径
logfile "/data/redis.log"

  1. docker-compose -f docker-compose.yml up -d 后台启动容器, 容器生成完成 docker ps 查看是否创建成功

执行命令如下??:

    docker-compose -f docker-compose.yml up -d

docker-compose.yml 内容如下??:

version: "3.6"
services:
    master-1: 
        image: redis:latest # 基础镜像
        container_name: master-1 # 容器服务名
        working_dir: /data # 工作目录
        environment: # 环境变量
            - PORT=6391 # 跟 redis.conf 里的配置一样的端口
            - TZ=Asia/Shanghai # 设置时区为上海,否则时间会有问题
        ports: # 映射端口,对外提供服务
            - "6391:6391" # redis 的服务端口
            - "16391:16391" # redis 集群监控端口
        stdin_open: true # 标准输入打开
        networks: # docker 网络设置
            master:
                ipv4_address: 172.50.0.2
        tty: true
        privileged: true # 拥有容器内命令执行的权限
        volumes:  [ # 映射数据卷,配置目录
                "/Users/huoxiao/Documents/data/env/redis/redis-cluster/6391/conf:/etc/redis", 
                "/Users/huoxiao/Documents/data/env/redis/redis-cluster/6391/data:/data"
            ]
        # entrypoint: # 设置服务默认的启动程序
        #     - /bin/bash
        #     - redis.sh
        command: ["redis-server", "/etc/redis/redis.conf"]

    master-2:
        image: redis:latest
        working_dir: /data
        container_name: master-2
        environment:
            - PORT=6392
            - TZ=Asia/Shanghai
        networks:
            master:
                ipv4_address: 172.50.0.3
        ports:
            - "6392:6392"
            - "16392:16392"
        stdin_open: true
        tty: true
        privileged: true
        volumes: [ # 映射数据卷,配置目录
                "/Users/huoxiao/Documents/data/env/redis/redis-cluster/6392/conf:/etc/redis", 
                "/Users/huoxiao/Documents/data/env/redis/redis-cluster/6392/data:/data"
            ]
        # entrypoint:
        #     - /bin/bash
        #     - redis.sh
        command: ["redis-server", "/etc/redis/redis.conf"]

    master-3:
        image: redis:latest
        container_name: master-3
        working_dir: /data
        environment:
            - PORT=6393
            - TZ=Asia/Shanghai
        networks:
            master:
                ipv4_address: 172.50.0.4
        ports:
            - "6393:6393"
            - "16393:16393"
        stdin_open: true
        tty: true
        privileged: true
        # volumes: ["/Users/huoxiao/Documents/data/env/redis:/etc/redis"]
        volumes:  [ # 映射数据卷,配置目录
                "/Users/huoxiao/Documents/data/env/redis/redis-cluster/6393/conf:/etc/redis", 
                "/Users/huoxiao/Documents/data/env/redis/redis-cluster/6393/data:/data"
            ]
        # entrypoint:
        #     - /bin/bash
        #     - redis.sh
        command: ["redis-server", "/etc/redis/redis.conf"]

    slave-1:
        image: redis:latest
        container_name: slave-1
        working_dir: /data
        environment:
            - PORT=6394
            - TZ=Asia/Shanghai
        networks:
            slave:
                ipv4_address: 172.30.0.2
        ports:
            - "6394:6394"
            - "16394:16394"
        stdin_open: true
        tty: true
        privileged: true
        # volumes: ["/Users/huoxiao/Documents/data/env/redis:/etc/redis"]
        volumes:  [ # 映射数据卷,配置目录
                "/Users/huoxiao/Documents/data/env/redis/redis-cluster/6394/conf:/etc/redis", 
                "/Users/huoxiao/Documents/data/env/redis/redis-cluster/6394/data:/data"
            ]
        # entrypoint:
        #     - /bin/bash
        #     - redis.sh
        command: ["redis-server", "/etc/redis/redis.conf"]

    slave-2:
        image: redis:latest
        working_dir: /data
        container_name: salve-2
        environment:
            - PORT=6395
            - TZ=Asia/Shanghai
        ports:
            - "6395:6395"
            - "16395:16395"
        stdin_open: true
        networks:
            slave:
                ipv4_address: 172.30.0.3
        tty: true
        privileged: true
        # volumes: ["/Users/huoxiao/Documents/data/env/redis:/etc/redis"]
        volumes:  [ # 映射数据卷,配置目录
                "/Users/huoxiao/Documents/data/env/redis/redis-cluster/6395/conf:/etc/redis", 
                "/Users/huoxiao/Documents/data/env/redis/redis-cluster/6395/data:/data"
            ]
        # entrypoint:
        #     - /bin/bash
        #     - redis.sh
        command: ["redis-server", "/etc/redis/redis.conf"]

    slave-3:
        image: redis:latest
        container_name: slave-3
        working_dir: /data
        environment:
            - PORT=6396
            - TZ=Asia/Shanghai
        ports:
            - "6396:6396"
            - "16396:16396"
        stdin_open: true
        networks:
            slave:
                ipv4_address: 172.30.0.4
        tty: true
        privileged: true
        volumes:  [ # 映射数据卷,配置目录
                "/Users/huoxiao/Documents/data/env/redis/redis-cluster/6396/conf:/etc/redis", 
                "/Users/huoxiao/Documents/data/env/redis/redis-cluster/6396/data:/data"
            ]
        command: ["redis-server", "/etc/redis/redis.conf"]
        # entrypoint:
            # - /bin/bash
            # - redis.sh

networks:
    master:
        driver: bridge # 创建一个docker 的桥接网络
        ipam:
            driver: default
            config:
                -
                    subnet: 172.50.0.0/16
    slave:
        driver: bridge
        ipam:
            driver: default
            config:
                -
                    subnet: 172.30.0.0/16
  1. 进入第一个容器中, 执行 redis-cluster-create.conf 中内容, 注意文件中的IP地址要与redis-cluster.tmpl 中的ip保持一致

执行如下命令进入容器??(master-1 为刚创建的集群容器主节点1):

    docker exec -it master-1 /bin/bash

redis-cluster-create.conf 内容如下??,创建集群:

redis-cli --cluster create 192.168.1.68:6391 192.168.1.68:6392 192.168.1.68:6393 192.168.1.68:6394 192.168.1.68:6395 192.168.1.68:6396 --cluster-replicas 1