博客 / 詳情

返回

docker 構建 lnmp 環境

使用 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 #主配置文件
user avatar dominic-giglio 頭像 heyiming 頭像 tangcy 頭像 fizz 頭像 emtalk_qf 頭像 mashubumaopao 頭像 jacob-gube 頭像 dreamlee 頭像
8 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.