You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化Puppeteer Docker镜像大小以解决Render部署失败问题?

问题描述

我按照网上教程为正在开发的应用构建了用于生成PDF的Puppeteer Docker镜像,并搭建了独立API。本地构建启动正常,但镜像体积达2GB,部署到Render时无报错但失败,推测是免费账户的镜像大小限制导致该问题。

原Dockerfile:

FROM node:18

RUN apt-get update && apt-get install gnupg wget -y && \
wget --quiet --output-document=- https://dl-ssl.google.com/linux/linux_signing_key.pub | gpg --dearmor > /etc/apt/trusted.gpg.d/google-archive.gpg && \
sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' && \
apt-get update && \
apt-get install google-chrome-stable -y --no-install-recommends && \
rm -rf /var/lib/apt/lists/*

ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true

RUN groupadd -r pptruser && useradd -rm -g pptruser -G audio,video pptruser


WORKDIR /app


# copy configs to /app folder
COPY package*.json ./
COPY tsconfig.json ./


# copy source code to /app/src folder
 COPY src /app/src

RUN npm install axios bcrypt cloudinary cookie-parser cors dotenv    express jsonwebtoken puppeteer

 RUN npm install typescript --save-dev
 RUN npm run build




FROM node:18

RUN apt-get update && apt-get install gnupg wget -y && \
wget --quiet --output-document=- https://dl-ssl.google.com/linux/linux_signing_key.pub | gpg --dearmor > /etc/apt/trusted.gpg.d/google-archive.gpg && \
sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' && \
apt-get update && \
apt-get install google-chrome-stable -y --no-install-recommends && \
rm -rf /var/lib/apt/lists/*

ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true

RUN groupadd -r pptruser && useradd -rm -g pptruser -G audio,video  pptruser

WORKDIR /app



COPY package*.json ./ 

RUN npm install axios bcrypt cloudinary cookie-parser cors dotenv   express jsonwebtoken puppeteer

COPY --from=0 /app/build ./build


RUN npm uninstall typescript




USER pptruser

CMD [ "npm", "start"]


EXPOSE 6000

PDF生成代码:

export const httpCreatePDF = async(req: Request, res:Response)=>{

const url = req.body.url;
const prevPublicURL = req.body.prevPublicURL;
const tripId = req.body.tripId;

res.sendStatus(200);
const browser = await puppeteer.launch({ headless: 'new',
executablePath: '/usr/bin/google-chrome',
ignoreDefaultArgs: ['--disable-extensions'],
            args: ['--no-sandbox', '--disable-setuid-sandbox'],
});
const page = await browser.newPage();
try {
await page.goto(url, {waitUntil: 'networkidle0'});

const pdf = await page.pdf(
    { format: 'A4', });

await browser.close();

//delete prev pdf if it exist in cloudinary

if(prevPublicURL){
    await deleteAllFiles({filesToDelete: [prevPublicURL]});
};

//upload the file to cloudinary
const uploadResponse =  await cloudinaryBufferUpload(pdf) as any;

const response = {
    pdfImageURL: uploadResponse?.secure_url,
    pdfPublicURL: uploadResponse?.public_id,
    tripId: tripId
}


const webHookReq = await axios.post(sanitizedConfig.WEBHOOK_URL_PDF, response);

    if(webHookReq?.status === 200){

        return 
    }
    else{

       await axios.post(sanitizedConfig.WEBHOOK_URL_PDF, response); 
    } 
  return 
 } catch (error) {
 await browser.close();
 throw error
 }

 }
优化方案

1. 复用Chrome安装层,避免重复构建

原Dockerfile在构建和运行阶段重复安装Chrome,直接导致镜像体积翻倍。将Chrome安装流程抽离为基础镜像层,供后续阶段复用。

2. 使用轻量Node镜像

替换完整版node:18为node:18-slim,该镜像基于精简版Debian,体积更小且能满足运行需求。

3. 分离构建与运行依赖

构建阶段安装完整依赖(含开发依赖如typescript),运行阶段仅安装生产依赖,同时用npm ci替代npm install,保证依赖版本一致且清理缓存。

4. 合并冗余命令,清理临时文件

将多个RUN命令合并,减少镜像层数;及时清理apt、npm缓存及无用工具(如gnupg、wget),避免残留文件占用空间。

优化后的Dockerfile

# 基础镜像:安装Chrome及依赖,供构建/运行阶段复用
FROM node:18-slim as base

RUN apt-get update && apt-get install -y --no-install-recommends \
    gnupg wget ca-certificates \
    && wget --quiet --output-document=- https://dl-ssl.google.com/linux/linux_signing_key.pub | gpg --dearmor > /etc/apt/trusted.gpg.d/google-archive.gpg \
    && sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \
    && apt-get update && apt-get install -y --no-install-recommends google-chrome-stable \
    && apt-get purge -y --auto-remove gnupg wget \
    && rm -rf /var/lib/apt/lists/*

ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true

# 创建非特权用户
RUN groupadd -r pptruser && useradd -rm -g pptruser -G audio,video pptruser

# 构建阶段:编译TypeScript代码
FROM base as builder

WORKDIR /app

COPY package*.json tsconfig.json ./
COPY src ./src

# 安装所有依赖(含开发依赖)
RUN npm ci
RUN npm run build

# 运行阶段:仅保留生产依赖与编译后代码
FROM base

WORKDIR /app

# 复制依赖配置,仅安装生产依赖
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force

# 从构建阶段复制编译产物
COPY --from=builder /app/build ./build

USER pptruser

CMD ["npm", "start"]

EXPOSE 6000

额外优化建议

  • 清理package.json中未使用的依赖,进一步缩减体积。
  • 调整Puppeteer启动参数,适配容器环境并减少资源占用:
const browser = await puppeteer.launch({ 
    headless: 'new',
    executablePath: '/usr/bin/google-chrome',
    ignoreDefaultArgs: ['--disable-extensions'],
    args: [
        '--no-sandbox', 
        '--disable-setuid-sandbox',
        '--disable-dev-shm-usage', // 避免共享内存不足
        '--disable-gpu', // 禁用GPU,减少资源占用
        '--single-process' // 单进程模式适配容器
    ],
});

内容的提问来源于stack exchange,提问作者david

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 12:11:01