构建基于 php7.4 的支持 swoft2 运行的 docker 镜像脚本

构建基于 php7.4 的支持 swoft2 运行的docker 镜像脚本。

其中 imagick 支持库,在未安装的情况下,最终镜像体积大概为162M,安装后,镜像体积增加到336M。所以如果不是必须用到 imagick 支持库,或者可以用 gd 替换的情况下,还是用 gd 库比较简洁,能够保证镜像很小。

支持扩展如下:

bash 复制
/var/www $ php -m
[PHP Modules]
bcmath
Core
ctype
curl
date
dom
fileinfo
filter
ftp
gd
hash
iconv
imagick
json
libxml
mbstring
mysqlnd
opencc
openssl
pcre
PDO
pdo_mysql
pdo_sqlite
Phar
posix
readline
redis
Reflection
session
SimpleXML
sockets
sodium
SPL
sqlite3
standard
swoole
sysvmsg
sysvsem
sysvshm
tokenizer
uuid
xml
xmlreader
xmlwriter
zip
zlib

注意:如果使用 imagick 扩展将 svg 文件转为 png,需要系统有字体支持,而一般在 docker 镜像内,是不会安装多余的字体文件的,所以转换后就会出字体变成“豆腐块”的情况。解决办法就是在执行转换的容器或者系统内,添加字体文件支持。所以,如果不是业务必须如此,尽量在开发环境就将图片处理完最好,这样既不会增加镜像体积,也不用配置许多比较麻烦的支持。

dockerfile 复制
# 使用 php:7.2-cli-alpine 作为基础镜像
FROM docker.m.daocloud.io/php:7.4-cli-alpine AS builder

# --build-arg timezone=Asia/Shanghai
ARG timezone=Asia/Shanghai
# app env: prod pre test dev
ARG app_env=test
# default use www-data user
ARG work_user=www-data
# default swoole version
ARG swoole_version=4.8.13
# default swoole dir
ARG swoole_dir="swoole-src-${swoole_version}"
# default swoole src zip file (https://github.com/swoole/swoole-src)
ARG swoole_src="${swoole_dir}.zip"
# default opencc src zip file (https://github.com/nauxliu/opencc4php)
ARG opencc4php_src="opencc4php-master.zip"
# default opencc_src zip file (https://github.com/BYVoid/OpenCC)
ARG opencc_src="OpenCC-ver.1.1.9.zip"

# 设置工作目录
WORKDIR /var/www

ENV APP_ENV=${app_env} \
    TIMEZONE=${timezone} \
    PHPREDIS_VERSION=5.1.0 \
    SWOOLE_VERSION=${swoole_version} \
    COMPOSER_ALLOW_SUPERUSER=1

# 设置alpinelinux镜像源
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.cloud.tencent.com/g' /etc/apk/repositories

# 安装必要的系统依赖和 PHP 扩展
RUN apk update && apk add --no-cache \
    libzip-dev \
    autoconf \
    g++ \
    make \
    pcre-dev \
    brotli-dev \
    openssl-dev \
    tzdata \
    freetype-dev \
    libjpeg-turbo-dev \
    libpng-dev \
    oniguruma-dev \
    htop \
    zip \
    unzip \
    e2fsprogs \
    e2fsprogs-dev \
    curl-dev \
    pkgconf \
    cmake \
    python3

# install imagick extension
RUN apk add --no-cache imagemagick-dev \
    libwebp-dev \
    librsvg-dev \
    && pecl install imagick \
    && docker-php-ext-enable imagick

# 安装 PHP 扩展
RUN docker-php-ext-install \
        zip bcmath gd pdo_mysql mbstring sockets sysvmsg sysvsem sysvshm

# 复制上下文文件到工作目录
COPY ./${swoole_src} .
COPY ./${opencc_src} .
COPY ./${opencc4php_src} .

# Install OpenCC (C++ library) from source zip
RUN test -f ${opencc_src} || (echo "OpenCC SRC file not found!" && exit 1) \
    && unzip ${opencc_src} -d . \
    && rm -rf ${opencc_src} \
    && dir_name="$(basename "${opencc_src}" .zip)" \
    && mkdir -p "$dir_name/build" \
    && ( \
        cd "$dir_name/build" \
        && cmake .. -DCMAKE_INSTALL_PREFIX=/usr \
        && make -j$(nproc) \
        && make install \
    ) \
    && rm -rf "$dir_name"

# Install opencc4php extension
RUN test -f ${opencc4php_src} || (echo "opencc4php SRC file not found!" && exit 1) \
    && unzip ${opencc4php_src} -d . \
    && rm -rf ${opencc4php_src} \
    && dir_name="$(basename "${opencc4php_src}" .zip)" \
    && ( \
        cd "$dir_name" \
        && phpize \
        && ./configure \
        && make -j$(nproc) \
        && make install \
    ) \
    && rm -rf "$dir_name" \
    && docker-php-ext-enable opencc

# Install UUID extension
RUN apk add --no-cache re2c && \
    pecl install uuid && \
    docker-php-ext-enable uuid

# Install redis extension
RUN wget http://pecl.php.net/get/redis-${PHPREDIS_VERSION}.tgz -O /tmp/redis.tar.tgz \
    && pecl install /tmp/redis.tar.tgz \
    && rm -rf /tmp/redis.tar.tgz \
    && docker-php-ext-enable redis
# Install swoole extension
RUN test -f ${swoole_src} || (echo "SWOOLE_SRC file not found: ${swoole_src}" && exit 1) \
    && unzip ${swoole_src} -d . \
    && mv ${swoole_dir} swoole \
    && rm -rf ${swoole_src} \
    && ( \
        cd swoole \
        && phpize \
        && ./configure --enable-mysqlnd --enable-sockets --enable-openssl --enable-http2 --enable-swoole-curl \
        && make -j$(nproc) \
        && make install \
    ) \
    && rm -r swoole \
    && docker-php-ext-enable swoole
# Timezone
RUN cp /usr/share/zoneinfo/${TIMEZONE} /etc/localtime \
    && echo "${TIMEZONE}" > /etc/timezone \
    && echo -e "[Date]\ndate.timezone=${TIMEZONE}" > /usr/local/etc/php/conf.d/timezone.ini

RUN apk del tzdata

# 替换原来的 composer 安装命令
RUN curl -sS https://mirrors.aliyun.com/composer/composer.phar -o /usr/local/bin/composer \
    && chmod +x /usr/local/bin/composer

FROM docker.m.daocloud.io/php:7.4-cli-alpine

# 通用构建参数
ARG project_name
ARG project_config
ARG service_name

# 不同作用域变量要重新声明才能传递
ARG timezone
ARG app_env
ARG work_user
ARG swoole_version
ARG swoole_dir
ARG swoole_src

# 设置工作目录
WORKDIR /var/www/${project_name}

# 安装扩展运行所需的共享库
RUN apk update && apk add --no-cache \
    e2fsprogs \
    libpng \
    libstdc++ \
    libzip \
    imagemagick \
    libwebp \
    librsvg \
    libgomp

# 拷贝 OpenCC 库和数据(推荐)
COPY --from=builder /usr/lib/libopencc.so* /usr/lib/
COPY --from=builder /usr/share/opencc/ /usr/share/opencc/
# 拷贝 php 扩展
COPY --from=builder /usr/local/lib/php/extensions /usr/local/lib/php/extensions
# 拷贝扩展配置文件
COPY --from=builder /usr/local/etc/php/conf.d /usr/local/etc/php/conf.d
# 拷贝 Composer
COPY --from=builder /usr/local/bin/composer /usr/local/bin/composer
# 拷贝 php.ini
COPY ./${project_config}/${project_name}/${service_name}/php/php.ini /usr/local/etc/php/php.ini
# 拷贝源代码
COPY ./${project_name} .
# 拷贝配置文件
COPY ./${project_config}/${project_name}/${service_name}/app/.env /var/www/${project_name}/.env
COPY ./${project_config}/${project_name}/${service_name}/app/bean.php /var/www/${project_name}/app/bean.php
COPY ./${project_config}/${project_name}/${service_name}/app/config /var/www/${project_name}/config

# 配置 Composer 镜像为阿里云
RUN composer install --no-dev --optimize-autoloader \
    && rm -rf /root/.composer/cache \
    && rm -rf .git \
    && chown -R www-data:www-data /var/www/${project_name}

# 暴露 Swoft 默认端口
EXPOSE 18306 18307 18308
# 设置当前启动用户
USER www-data
# 启动 Swoft 服务
CMD ["php", "bin/swoft", "http:start"]