使用 docker-compose 编排的一套 lnmp 环境,并补充了 nginx / php / mysql / redis 的配置文件,补充了 php 的常用扩展。给到了 fpm / swoole 的部署、运行示例。可以方便大家快速搭建开发、生产环境、学习 docker 技能(涉及了镜像打包、Entrypoint、yml 高大上的写法 extends & 引用)。

github 完整示例:docker-lnmp

docker-lnmp

.env

CONTAINER_NAME_NGINX=nginx
CONTAINER_NAME_PHP_FPM=php-fpm
CONTAINER_NAME_SWOOLE=swoole
CONTAINER_NAME_REDIS=redis
CONTAINER_NAME_MYSQL=mysql
CONTAINER_NAME_NODE=node

common-services.yml

# 抽出来的php类容器的配置模板 只用来被 extends 载入 不会创建额外容器
# 这里用的是我自己打包的一个镜像,官方的好多扩展没开启 这里我开启了
services:
    php-tpl:
        restart: always
        stdin_open: true
        tty: true
        # image: php:8.2-fpm
        image: sqrtcat/php-swoole:0.0.2
        # platform: linux/amd64
        # platform: linux/x86_64
        # build: #自定义镜像构建
        #   context: ./php
        #   dockerfile: Dockerfile
        ports:
            - :9000 # php-fpm 的默认端口 配置在 /usr/local/etc/php-fpm.d/zz-docker.conf 中
        volumes:
            - /etc/localtime:/etc/localtime:ro # 修正时间 centos
            - /etc/timezone:/etc/timezone:ro # 修正时区 centos
            - ./php/conf/php.ini:/usr/local/etc/php/php.ini # php.ini
            - ./php/conf/conf.d/docker-php-z-exts.ini:/usr/local/etc/php/conf.d/docker-php-z-exts.ini # 额外加载的扩展
            - ./php/conf/php-fpm.d/www.conf:/usr/local/etc/php-fpm.d/www.conf # php-fpm 进程池的相关配置

docker-compose.yml

version: '3'

# x- 前缀声明为引用 &foo
# 可以在别处取值填充 *foo
x-common-config: &common_config
    restart: always
    stdin_open: true
    tty: true

services:
    nginx:
        <<: *common_config
        container_name: ${CONTAINER_NAME_NGINX} # .env 环境变量
        # image: nginx:latest # 直接使用原镜像 或 build 定制镜像
        build: # 如果之前没有生产镜像,可以直接用这个
          context: ./nginx
          dockerfile: Dockerfile
        ports:
            - 8050:80 # 端口 / 域名映射多站点 自行选择
            - 8051:81
            - 8052:82
        volumes:
            - ./nginx/conf/nginx.conf:/etc/nginx/nginx.conf # 主配置
            - ./nginx/conf/proxy.conf:/etc/nginx/proxy.conf # 代理配置
            - ./nginx/conf/fastcgi.conf:/etc/nginx/fastcgi.conf # fastcgi配置
            - ./nginx/conf/fastcgi_params:/etc/nginx/fastcgi_params # fastcgi配置
            - ./nginx/conf/pathinfo.conf:/etc/nginx/pathinfo.conf # pathinfo配置
            - ./nginx/conf/enable-php.conf:/etc/nginx/enable-php.conf # php开启
            - ./nginx/conf.d:/etc/nginx/conf.d # 放站点hosts的配置
            - /var/logs:/www/wwwlogs # 日志
            # 站点挂载
            - ../sites/default:/var/www/default:rw
            - ../sites/foo:/var/www/foo:rw
            - ../sites/swoole:/var/www/swoole:rw
        links:
          - php-fpm
          - swoole

    php-fpm:
        <<: *common_config
        container_name: ${CONTAINER_NAME_PHP_FPM}
        extends:
            # 载入配置模板
            file: common-services.yml
            service: php-tpl
        volumes:
            # 站点挂载
            - ../sites/default:/var/www/default:rw
            - ../sites/foo:/var/www/foo:rw
        links:
            - redis
            - mysql
        depends_on:
            - redis
            - mysql

    swoole:
        <<: *common_config
        container_name: ${CONTAINER_NAME_SWOOLE}
        extends:
            # 载入配置模板
            file: common-services.yml
            service: php-tpl
        ports:
            - 9501:9501
        volumes:
            # 站点挂载
            - ../sites/swoole:/var/www/swoole:rw
        working_dir: /var/www/swoole
        entrypoint: ["php", "server.php"] # 覆写 entrypoint 启动 swoole server 阻塞模式可以防止容器退出
        links:
            - redis
            - mysql
        depends_on:
            - redis
            - mysql

    redis:
        <<: *common_config
        container_name: ${CONTAINER_NAME_REDIS}
        image: redis:latest
        ports:
            - 6397:6379
        volumes:
            - ./redis/log:/var/log/redis # 日志目录
            - ./redis/data:/data # 数据目录 redis.conf->dir
            - ./redis/conf/redis.conf:/etc/redis/redis.conf # 配置文件
        command: redis-server /etc/redis/redis.conf # 使用自定义配置文件启动服务

    mysql:
        <<: *common_config
        container_name: ${CONTAINER_NAME_MYSQL}
        image: mysql:latest
        ports:
            - 3360:3306
        volumes:
            - ./mysql/log:/var/log/mysql # 挂载日志 为了保存二进制日志
            - ./mysql/data:/var/lib/mysql # 挂载数据 一定要外挂出来 不然容器销毁数据全无 提桶跑路
            - ./mysql/my.cnf:/etc/my.cnf # 自定义配置文件 可配置 datadir
            - ./mysql/conf.d:/etc/mysql/conf.d # 额外的配置文件目录
        environment:
            MYSQL_USER: www # 普通用户
            MYSQL_PASSWORD: 123456 # 普通用户密码
            MYSQL_ROOT_PASSWORD: 123456 # root密码
            MYSQL_DATABASE: test # 默认新建数据库名称
        
    node: #node.js 个人目前主要用于编译
        <<: *common_config
        container_name: ${CONTAINER_NAME_NODE}
        platform: linux/x86_64
        image: node
        volumes:
            - ../sites:/root/sites #项目

nginx 镜像

Dockerfile 主要为了创建多级目录

FROM nginx:latest

# nginx 无权创建二级目录 需使用命令提前创建
# for proxy.conf
RUN mkdir -p /tmp/nginx/proxy_temp_dir
RUN mkdir -p /tmp/nginx/proxy_cache_dir

镜像配置文件路径

# nginx 的主配置目录
# tree /etc/nginx/
/etc/nginx/
|-- conf.d # 站点配置目录
|-- fastcgi_params
|-- mime.types
|-- modules -> /usr/lib/nginx/modules
|-- nginx.conf # 主配置文件
|-- scgi_params
`-- uwsgi_params

php 镜像

Dockerfile 为了开启更多必要扩展

FROM php:8.2-fpm

RUN apt-get update
RUN apt-get install -y \
        libmcrypt-dev \
        libfreetype6-dev \
        libjpeg62-turbo-dev \
        libpng-dev \
        libwebp-dev \
        libevent-dev \
        libssl-dev

# 解压源码
RUN docker-php-source extract

# 安装扩展
RUN docker-php-ext-install -j$(nproc) iconv exif fileinfo

# 如果安装的扩展需要自定义配置时
RUN docker-php-ext-configure gd --with-webp=/usr/include/webp --with-jpeg=/usr/include --with-freetype=/usr/include/freetype2/
RUN docker-php-ext-install -j$(nproc) gd

# docker-php-ext 安装扩展会被自动加载 /usr/local/etc/php/conf.d/docker-php-ext-xxx.ini
RUN docker-php-ext-install pdo_mysql
RUN docker-php-ext-install sockets
RUN docker-php-ext-install sodium

# event 中默认 --enbale-event-socket 选项需要先安装 sockets 扩展后才可以
# pecl 安装的扩展不会被自动加载 需要手动配置引入 在宿主机上定义并挂在至容器的如下目录即可
# /usr/local/etc/php/conf.d/docker-php-z-exts.ini
# 加载顺序按文件名 ASCII 正序 比如 event 扩展依赖 sockets 需要在其后加载
# 所以我们自定义的文件名是用 -z- 来排在最后
RUN pecl install event
RUN pecl install swoole
RUN pecl install redis

# 删除源码
RUN docker-php-source delete

php:{version}-fpm 镜像在编译时
通过 --with-config-file-path 指定了配置目录 /usr/local/etc/php
通过 --with-config-file-scan-dir 指定了额外载入的配置目录 /usr/local/etc/php/conf.d

php-cli 会加载 :

  • /usr/local/etc/php/php.ini
  • /usr/local/etc/php/conf.d/*.ini

php-fpm -t 可以查看 fpm 加载的配置文件,会加载:

  • 加载 php-cli 的配置。
  • /usr/local/etc/php-fpm.conf
  • /usr/local/etc/php-fpm.d/*.conf

不过我没搞清楚 php-fpm 是如何被指定配置文件路径是 /usr/local/etc/ 的,毕竟 php 声明的 configDir/usr/local/etc/php。传统的 fpm 配置文件也是在 {prefix}/etc/php-fpm.conf(如有知晓的同学欢迎留言解惑)。

镜像配置文件路径

# tree /usr/local/etc
/usr/local/etc
|-- pear.conf
|-- php # 主配置目录 --with-config-file-path
|   |-- conf.d # 扩展配置目录 --with-config-file-scan-dir
|   |   |-- docker-fpm.ini
|   |   |-- docker-php-ext-exif.ini
|   |   |-- docker-php-ext-gd.ini
|   |   |-- docker-php-ext-pdo_mysql.ini
|   |   |-- docker-php-ext-sockets.ini
|   |   `-- docker-php-ext-sodium.ini
|   |-- php.ini-development
|   `-- php.ini-production # 默认没有 php.ini 文件,可以挂载
|-- php-fpm.conf # fpm 主配置 会引入 php-fpm.d 下的扩展配置
|-- php-fpm.conf.default
`-- php-fpm.d  # php-fpm 启动时会自动加载 php-fpm.d 下的配置文件
    |-- docker.conf # fpm 日志相关
    |-- www.conf # fpm 进程池配置
    |-- www.conf.default
    `-- zz-docker.conf # fpm 监听端口

查看容器启动的 entrypoint 看下启动的命令

# 宿主机执行 看到 entrypoint 是启动了一个 bin
docker inspect --format '{{ .Config.Entrypoint }}' <container_id>
[docker-php-entrypoint]

# 登录容器查找这个 bin
docker -it exec <container_id> bash
# which docker-php-entrypoint
/usr/local/bin/docker-php-entrypoint
# cat /usr/local/bin/docker-php-entrypoint

#!/bin/sh
set -e

# first arg is `-f` or `--some-option`
if [ "${1#-}" != "$1" ]; then
        set -- php-fpm "$@"
fi

exec "$@

mysql

镜像配置文件路径

/etc/my.cnf #主配置文件
/etc/mysql/conf.d # 扩展配置目录

redis

redis配置文件下载

镜像配置文件路径

/etc/redis/redis.conf #主配置文件

big_cat
1.7k 声望130 粉丝

规范至上