alpine安装wkhtmltopdf构建Docker容器

引言

项目需要将HTML页面转换为PDF,由于使用laravel开发,选用了laravel-snappy,它是snappy的laravel版本。snappy是一个PHP库,可以从 url 或 HTML页面生成缩略图、快照或PDF,底层调用的是wkhtmltopdf。wkhtmltopdf是一个开源软件,可以将HTML页面转换为PDF或图片。
wkhtmltopdf有2种安装方法,一种是用命令行直接在服务器上安装,另一种是使用composer安装。如果采用composer安装,会有如下的二进制文件/vendor/h4cc/wkhtmltoimage-amd64/bin/wkhtmltoimage-amd64/vendor/h4cc/wkhtmltopdf-amd64/bin/wkhtmltopdf-amd64

Docker

为了让镜像尽量小一些,这里采用了alpine构建镜像。但是遇到的问题是在alpine内无法使用wkhtmltopdf-amd64,会报如下错误

The exit status code '127' says something went wrong:\nstderr: \"sh: /www/my-protect/vendor/h4cc/wkhtmltopdf-amd64/bin/wkhtmltopdf-amd64: not found

原因不是很清楚,可以看看这里。所以要采用第一种安装方式,Dockerfile文件如下

FROM php:7.2.24-fpm-alpine
# 更改为阿里的镜像源
RUN  sed -i "s/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g" /etc/apk/repositories

# install unpatched wkhtmltopdf
RUN apk add --no-cach wkhtmltopdf

这里需要说明wkhtmltopdf有with unpatched qt和with patched qt两个版本,alpine默认安装的是unpatched版本,这个版本不能支持例如页眉、页脚、边距等高级操作,所以我们需要安装patched版本。

安装wkhtmltopdf with patched qt

网上有大佬已经造好了轮子,真香!!!基本原理是先通过容器把wkhtmltopdf with patched qt的二进制文件编译好,然后从容器内考出来,构建自己镜像的时候COPY进去替换默认的wkhtmltopdf二进制文件,为了支持中文,把字体文件一起拷进去就好了。上面Dockerfile中的wkhtmltopdf和wkhtmltoimage就是这样来的,至于字体文件可以从原宿主机上拷贝出来。
本地构建用于编译wkhtmltopdf的镜像可能比较慢,大佬已经将构建好的镜像传到docker hub上了,看这里。步骤如下

$ docker pull aantonw/alpine-wkhtmltopdf-patched-qt
$ docker run -d --name wkhtmltopdf aantonw/alpine-wkhtmltopdf-patched-qt
$ docker cp wkhtmltopdf:/bin/wkhtmltopdf wkhtmltopdf
$ docker cp wkhtmltopdf:/bin/wkhtmltoimage wkhtmltoimage

最后完整版的Dockerfile如下

FROM php:7.2.24-fpm-alpine
# 更改为阿里的镜像源
RUN  sed -i "s/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g" /etc/apk/repositories

# install unpatched wkhtmltopdf
RUN apk add --no-cach wkhtmltopdf
# replace binary and lib 
COPY wkhtmltopdf /usr/bin/wkhtmltopdf
COPY wkhtmltoimage /usr/bin/wkhtmltoimage
# 拷贝宋体字体文件
COPY ./wkhtmltopdf/fonts/simsun.ttc /usr/share/fonts/simsun.ttc

最后需要修改配置文件

return array(
    'pdf' => array(
        'enabled' => true,
        'binary'  => base_path('/usr/bin/wkhtmltopdf'),
        'timeout' => false,
        'options' => array(),
        'env'     => array(),
    ),
    'image' => array(
        'enabled' => true,
        'binary'  => base_path('/usr/bin/wkhtmltoimage'),
        'timeout' => false,
        'options' => array(),
        'env'     => array(),
    ),
);

参考

posted @ 2022-06-08 17:47  whyly  阅读(1746)  评论(0编辑  收藏  举报