cloud-run-puppeteer

$npx mdskill add tranhieutt/software_development_department/cloud-run-puppeteer

Deploys Puppeteer browser automation on Google Cloud Run with Docker.

  • Solves silent failures when deploying headless Chrome to Cloud Run gen1.
  • Depends on Google Cloud Run, Docker, and Puppeteer Node.js library.
  • Recommends gen2 execution environment and installing Chrome system dependencies.
  • Provides a Dockerfile and gcloud command for a working deployment.

SKILL.md

.github/skills/cloud-run-puppeteerView on GitHub ↗
---
name: cloud-run-puppeteer
type: reference
description: "Deploys Puppeteer browser automation on Google Cloud Run with Docker. Use when running headless browser tasks on Cloud Run, or when the user mentions Cloud Run, Puppeteer, headless Chrome, or serverless browser automation."
effort: 2
allowed-tools: Read, Glob, Grep, Bash
user-invocable: true
when_to_use: "When deploying a Node.js + Puppeteer / headless Chrome service to Google Cloud Run"
---

# Cloud Run + Puppeteer Deployment Guide

Hard-won lessons from deploying Puppeteer to Cloud Run. These are non-obvious gotchas that cost significant debug time.

## MUST: Use gen2 Execution Environment

Cloud Run **gen1** uses gVisor sandbox — blocks Linux syscalls Chrome needs to create processes. Puppeteer will hang/timeout silently.

```bash
gcloud run deploy my-service \
  --execution-environment gen2   # <-- required for Chrome/Puppeteer
```

Never deploy a Puppeteer service on gen1.

---

## MUST: Install Chrome System Dependencies

`node:18` base image does not include libraries Chrome needs. Missing any one of these causes launch failure.

```dockerfile
FROM node:18

RUN apt-get update && apt-get install -y \
    ca-certificates fonts-liberation fonts-ipafont-gothic fonts-wqy-zenhei \
    libasound2 libatk-bridge2.0-0 libatk1.0-0 libcairo2 libcups2 \
    libdbus-1-3 libdrm2 libgbm1 libglib2.0-0 libgtk-3-0 libnspr4 libnss3 \
    libpango-1.0-0 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 \
    libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 \
    libxss1 libxtst6 xdg-utils --no-install-recommends \
    && rm -rf /var/lib/apt/lists/*
```

---

## MUST: Secret Manager mount path ngoài WORKDIR

Nếu mount secret vào cùng path với `WORKDIR`, volume mount sẽ **che toàn bộ thư mục** — chỉ còn file secret, code biến mất.

```bash
# SAI — mount trùng WORKDIR /app
--set-secrets "/app/service-account.json=my-secret:latest"

# ĐÚNG — mount ra path riêng
--set-secrets "/secrets/service-account.json=my-secret:latest"
```

```dockerfile
ENV GOOGLE_CREDS_PATH=/secrets/service-account.json
```

> **Windows/Git Bash warning:** `--set-env-vars` với path Unix sẽ bị Git Bash convert thành Windows path. Set `ENV` trực tiếp trong Dockerfile thay vì truyền qua CLI.

---

## Puppeteer Launch Config cho Cloud Run

```javascript
const browser = await puppeteer.launch({
    headless: 'new',
    timeout: 60000,          // cold start cần thời gian — mặc định 30s không đủ
    args: [
        '--no-sandbox',
        '--disable-setuid-sandbox',
        '--disable-dev-shm-usage',   // /dev/shm nhỏ trong container
        '--single-process',
        '--no-zygote',
        '--disable-gpu',
    ],
});
```

---

## waitUntil hợp lệ trong Puppeteer

Chỉ có 4 giá trị hợp lệ — `'commit'` (từ Playwright) KHÔNG tồn tại:

| Giá trị | Ý nghĩa |
|---------|---------|
| `load` | Chờ event `load` (chậm nhất) |
| `domcontentloaded` | Chờ DOM parse xong (khuyên dùng) |
| `networkidle0` | Không còn request nào trong 500ms |
| `networkidle2` | ≤ 2 request đang chờ trong 500ms |

Với trang nặng từ server overseas, dùng `domcontentloaded` + timeout cao + `waitForFunction` chờ content cụ thể:

```javascript
await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 120000 });
await page.waitForFunction(
    () => document.body && document.body.innerText.includes('target-text'),
    { timeout: 60000 }
);
```

---

## Block Resource để Tăng Tốc

Chặn images, CSS, fonts giảm băng thông đáng kể — quan trọng khi crawl từ server overseas:

```javascript
await page.setRequestInterception(true);
page.on('request', (req) => {
    if (['image', 'stylesheet', 'font', 'media'].includes(req.resourceType())) {
        req.abort();
    } else {
        req.continue();
    }
});
```

---

## Recommended Cloud Run Deploy Command

```bash
gcloud run deploy my-service \
  --image gcr.io/PROJECT_ID/my-image \
  --region asia-southeast1 \
  --platform managed \
  --execution-environment gen2 \
  --memory 2Gi \
  --cpu 2 \
  --timeout 300 \
  --set-secrets "/secrets/service-account.json=my-secret:latest" \
  --allow-unauthenticated
```

Puppeteer cần ít nhất **2Gi RAM** — Chrome dùng nhiều memory.

More from tranhieutt/software_development_department

SkillDescription
agent-healthReads production/traces/agent-metrics.jsonl and displays a per-agent performance summary table for the current or a specified session. Highlights agents with high error rates or OPEN circuit breaker state.
agent-styleProvides the vendored agent-style v0.3.5 prose rule pack as a portable Claude skill. Use when installing, syncing, applying, or auditing SDD Agent-Style support in another project, or when a style-review workflow needs the bundled rules.
angular-best-practicesProvides Angular best practices for components, modules, services, and reactive patterns. Use when working with Angular TypeScript files, component templates, NgModules, RxJS observables, or when the user mentions Angular, ng, or Angular CLI.
annotateRecords unexpected API behaviors, undocumented caveats, version bugs, or non-obvious workarounds into .claude/memory/annotations.md. Use immediately when an undocumented behavior or surprising caveat is discovered during development.
aws-serverlessProvides AWS serverless architecture patterns for Lambda, API Gateway, DynamoDB, SQS, and SAM/CDK. Use when working with AWS serverless files (serverless.yml, CDK stacks) or when the user mentions Lambda, API Gateway, serverless, or AWS SAM.
backend-architectDesigns scalable backend architectures covering microservices, event-driven systems, API gateways, and data stores. Use when designing a backend system or when the user mentions backend architecture, scalability, or distributed systems.
codex-sddAdapts SDD for Codex while preserving Claude Code behavior. Use when working in Codex, setting up Codex compatibility, mapping Claude tools to Codex tools, or explaining how SDD should run outside Claude Code.
database-architectDesigns relational and NoSQL database schemas, indexing strategies, migration plans, and data modeling patterns. Use when designing a database or when the user mentions database architecture, schema design, or data modeling.
db-reviewReviews database schemas, queries, and migrations for correctness, performance, security, and best practices. Use when reviewing SQL migration files or when the user mentions database review, schema review, or query audit.
deep-interviewConducts a structured technical deep-dive to gather detailed requirements, constraints, and decisions from the user. Use when starting a complex feature or when the user wants to be asked structured clarifying questions before implementation.