构建 puppeteer docker 镜像

有时候需要在服务端生成PDF,可是在服务端生成的PDF不如浏览器中看到的页面美观,就想到了浏览器headless模式,在服务端访问前端,然后以PDF格式打印网页。
前端大神安利了puppeteer,确实很不错,还支持定制页眉页脚。
再者服务端程序是使用docker管理的,所以需要创建含有puppeteerdocker镜像。

先看Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 基于`alpine`版本的`node`10
FROM node:10.15.2-alpine

# 安装 Chromium (72)。从 alpine/v3.9 版本库中下载
RUN apk update && apk upgrade && \
echo @v3.9 http://dl-cdn.alpinelinux.org/alpine/v3.9/community >> /etc/apk/repositories && \
echo @v3.9 http://dl-cdn.alpinelinux.org/alpine/v3.9/main >> /etc/apk/repositories && \
apk add --no-cache \
freetype@v3.9 \
chromium@v3.9 \
harfbuzz@v3.9 \
nss@v3.9

# 安装 Puppeteer 时不让它自动下载 Chromium
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true
# 选择 Chromium 72 对应的 Puppeteer 版本
RUN yarn add puppeteer@1.11.0

# 添加用户
RUN addgroup -S pptruser && adduser -S -g pptruser pptruser \
&& mkdir -p /home/pptruser/Downloads \
&& chown -R pptruser:pptruser /home/pptruser

# 添加 cjk 字体以支持中文
COPY NotoSansCJK-Regular.ttc /usr/share/fonts/TTF

USER pptruser

Dockerfile部分说明

  • 选择alpine版,是因为已有alpine版的java镜像。其实docker不支持合并镜像,还需要基于原java镜像再安装Puppeteer组成新的镜像
  • 没有选择edge版仓库, edge是在开发中的, 有不确定性
  • 已有java镜像alpine版本是v3.7, 有些工具包和此次版本不兼容,需要安装v3.9的freetype
  • 字体选择开源字体,防止被告

构建 docker image

1
docker build -t node-puppeteer:puppeteer1_11-node10-alpine .

下载该镜像

执行example

1
2
3
4
5
# 当你执行时,最好使用`--volume`选项,方便取出后面生成的文件
docker run -it --rm node-puppeteer:puppeteer1_11-node10-alpine sh
cd /tmp
vi example.js # 内容如下
node example.js # 得到 example.png

example.js文件内容(此处以生成图片快照为例,若要生成PDF,请参考puppeteer文档):

1
2
3
4
5
6
7
8
9
10
11
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
executablePath: '/usr/bin/chromium-browser',
args: ['--no-sandbox', '--disable-setuid-sandbox'],
});
const page = await browser.newPage();
await page.goto('https://www.baidu.com');
await page.screenshot({path: 'example.png'});
await browser.close();
})();

参考