# 为workerman制作跨平台的PHP8.1环境Docker镜像 ## 说明 本方法基于PHP官方`8.1.27-cli`版本的镜像制作,安装好workerman开发常用的依赖和扩展,并通过`docker buildx`构建跨平台的Docker镜像。 ## Dockerfile文件 ```dockerfile # 拉基础镜像 FROM php:8.1.27-cli # 替换源 RUN rm /etc/apt/sources.list.d/debian.sources && \ echo 'deb http://mirror.us.oneandone.net/debian bookworm main' > /etc/apt/sources.list && \ echo 'deb-src http://mirror.us.oneandone.net/debian bookworm main' >> /etc/apt/sources.list && \ echo 'deb http://mirror.us.oneandone.net/debian-security bookworm-security main' >> /etc/apt/sources.list && \ echo 'deb-src http://mirror.us.oneandone.net/debian-security bookworm-security main' >> /etc/apt/sources.list && \ echo 'deb http://mirror.us.oneandone.net/debian bookworm-updates main' >> /etc/apt/sources.list && \ echo 'deb-src http://mirror.us.oneandone.net/debian bookworm-updates main' >> /etc/apt/sources.list && \ echo 'deb http://mirror.us.oneandone.net/debian bookworm-backports main' >> /etc/apt/sources.list && \ echo 'deb-src http://mirror.us.oneandone.net/debian bookworm-backports main' >> /etc/apt/sources.list # 安装一些依赖 RUN apt-get update && apt-get install -y \ libfreetype6-dev libjpeg62-turbo-dev \ libpng-dev libwebp-dev zlib1g-dev \ libzip-dev zip \ libevent-dev libssl-dev \ lsb-release libpq-dev \ libgmp-dev \ libmagickwand-dev \ libzookeeper-mt-dev # 安装扩展 RUN docker-php-ext-configure gd --enable-gd --with-freetype --with-jpeg --with-webp \ && docker-php-ext-install -j$(nproc) gd \ && docker-php-ext-install exif \ && docker-php-ext-install opcache \ && docker-php-ext-install pdo_mysql \ && docker-php-ext-install mysqli \ && docker-php-ext-install zip \ && docker-php-ext-install pcntl \ && docker-php-ext-install fileinfo \ && pecl install https://pecl.php.net/get/redis-6.0.2.tgz \ && docker-php-ext-enable redis \ && docker-php-ext-install sockets \ && pecl install https://pecl.php.net/get/event-3.1.4.tgz \ && docker-php-ext-enable event \ && cat /usr/local/etc/php/conf.d/docker-php-ext-event.ini >> /usr/local/etc/php/conf.d/docker-php-ext-sockets.ini \ && mv /usr/local/etc/php/conf.d/docker-php-ext-sockets.ini /usr/local/etc/php/conf.d/docker-php-ext-event.ini \ && docker-php-ext-install -j$(nproc) pgsql pdo_pgsql \ && pecl install https://pecl.php.net/get/mongodb-1.19.3.tgz \ && docker-php-ext-enable mongodb \ && docker-php-ext-install -j$(nproc) gmp \ && pecl install https://pecl.php.net/get/imagick-3.7.0.tgz \ && docker-php-ext-enable imagick \ && docker-php-ext-install bcmath \ && docker-php-ext-enable bcmath \ && pecl install https://pecl.php.net/get/xlswriter-1.5.5.tgz \ && docker-php-ext-enable xlswriter \ && pecl install https://pecl.php.net/get/zookeeper-1.2.1.tgz \ && docker-php-ext-enable zookeeper # 安装Composer RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \ && php composer-setup.php \ && php -r "unlink('composer-setup.php');" \ && mv composer.phar /usr/local/bin/composer # 创建应用目录 RUN mkdir -p /app/service # 设置工作目录 WORKDIR /app/service ``` > 在`替换源`那一段中,你应该把其中的源地址替换成你的主机可以快速访问的源地址,不建议直接使用本文的源。 ## 用`docker buildx`构建 将上面的Dockerfile脚本直接保存为`Dockerfile`文件。 ### 检查`docker buildx`环境 ```sh docker info ``` 执行以上命令可以看到类似下面的信息: ```txt Client: Docker Engine - Community Version: 27.0.3 Context: default Debug Mode: false Plugins: buildx: Docker Buildx (Docker Inc.) Version: v0.15.1 Path: /usr/libexec/docker/cli-plugins/docker-buildx compose: Docker Compose (Docker Inc.) Version: v2.28.1 Path: /usr/libexec/docker/cli-plugins/docker-compose ... ``` 一般情况下,如果是通过包管理器安装的docker engine或者docker desktop的话,默认就已经安装好了buildx和compose插件了。 ### 跨平台构建并发布 接下来,我们的目标是用上面的Dockerfile构建跨平台的`workerman:8.1.27`镜像并直接推送到`quay.io`平台上: (本文中我的quay.io账号是wandoubaba517,你要替换成你自己的账号。) ```sh docker login quay.io docker buildx create --use docker buildx build --platform linux/386,linux/s390x,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8 --push -t quay.io/wandoubaba517/workerman:8.1.27 . ``` 执行上面的命令,执行过程中会自动从docker hub上拉取名为`moby/buildkit:buildx-stable-1`的镜像并启动容器开始自动构建和推送,整个过程在我的2核4G服务器上会执行数小时,可以使用`tmux`等终端工具异步执行。 ## 使用镜像 ```sh docker pull quay.io/wandoubaba517/workerman:8.1.27 docker run -itd -p 8787:8787 -v ./:/app/service quay.io/wandoubaba517/workerman:8.1.27 ``` ### docker-compose.yml ```yml services: workerman: image: quay.io/wandoubaba517/workerman:8.1.27 container_name: workerman restart: always volumes: - ./:/app/service working_dir: /app/service stdin_open: true ports: - 8787:8787 ommand: ['php', 'start.php', 'start'] healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8787/"] interval: 5s retries: 3 start_period: 5s timeout: 10s ``` ### composer命令脚本 > 仅适用于linux系统 ```sh #!/bin/bash # 使用heredoc构建docker run命令 read -r -d '' DOCKER_COMMAND <<'EOF' docker run --rm \ -v "$(pwd)":/app/service \ -w /app/service \ quay.io/wandoubaba517/workerman:8.1.27 \ composer EOF # 检查是否有传递参数,并将它们附加到命令的末尾 if [ $# -gt 0 ]; then DOCKER_COMMAND+=" $@" fi # 执行docker run命令 eval "$DOCKER_COMMAND" ``` 把上面的脚本保存为`compose`文件,设置可执行权限: ```sh chmod +x ./composer ``` 然后就可以用`./composer`代替composer命令了。 也可以直接把这个composer脚本复制到/usr/bin/目录下以供全局使用(不建议这样,失去了多版本共存的意义)。 ### php命令脚本 ```sh #!/bin/bash # 获取脚本所在目录的绝对路径 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) # 切换工作目录到脚本所在目录 cd "$SCRIPT_DIR" || exit 1 # 使用heredoc构建docker run命令 read -r -d '' DOCKER_COMMAND <<'EOF' docker run --rm \ --network host \ -v "$(pwd)":/app/service \ -v "$(pwd)/php.ini":/usr/local/etc/php/php.ini \ -w /app/service \ quay.io/wandoubaba517/workerman:8.1.27 \ php EOF # 检查是否有传递参数,并将它们附加到命令的末尾 if [ $# -gt 0 ]; then DOCKER_COMMAND+=" $@" fi # 执行docker run命令 eval "$DOCKER_COMMAND" ``` 同样要为`php`脚本赋予可执行权限 ```sh chmod +x ./php ``` 然后就可以执行`./php`代替php命令了。 ### 最佳实践 建议把composer脚本和php脚本都保存在项目工程目录下,另外再把容器内`/usr/local/etc/php/php-production.ini`文件也复制到工程目录下并命名为`php.ini`,在`docker-compose.yml`文件中配置卷映射 ```yml volumes: - ./:/app/service - ./php.ini:/usr/local/etc/php/php.ini ``` ### 工程示例 ```sh git clone git@git.wandoubaba.com:wandoubaba/docker-webman.git cd docker-webman ./composer install ./php start.php start ```