- 本篇文件對應的程式碼:https://github.com/LiangJunro...
- Docker 系列文件:https://github.com/LiangJunro...
一、前文回顧 & 前言
經過前文的講解,想必大家已經對 Docker 有比較深的印象了,那麼這篇文章我們將長話短說:
- 如何將 Puppeteer 這種無頭瀏覽器塞到 Docker 中
二、Puppeteer 目錄結構
管理,我們的服務還是基於之前的 Node.js 服務改造,所以 jsliang 拿了自己寫的一個基礎 Node.js + TypeScript 的服務。
它的目錄結構如下:
docker-puppeteer
啟動這個 Demo 只需要 2 步:
- 安裝包:
npm i
- 啟動服務:
npm run robot-test
等到每分鐘的第 0 秒的時候,終端操作開啟 Puppeteer,並將圖片存放到 src/source
上。
關鍵程式碼是:
src/index.ts
// ……程式碼省略
console.log('你好,已進入程式');
let time = 0;
await schedule.scheduleJob('0 * * * * *', async () => {
const browser = process.env.NODE_ENV === 'production' ?
// 正式環境需要開啟沙盒模式
await puppeteer.launch({
args: ['--no-sandbox', '--disable-setuid-sandbox'],
}) :
// 非正式環境則隨意
await puppeteer.launch({
headless: false, // 非無頭模式,
devtools: true, // 除錯模式,可以在控制檯看到 console
});
// 建立新標籤頁並開啟
const page = await browser.newPage();
await page.goto('https://www.baidu.com/s?wd=jsliang');
// 等待 5 秒載入
await page.waitForTimeout(5 * 1000);
// 獲取快照並儲存到本地
await page.screenshot({
path: `./src/source/baidu_${++time}.png`,
});
// 關閉視窗
await browser.close();
});
// ……程式碼省略
感興趣的小夥伴可以停下來開啟倉庫,先看下 Demo,不感興趣的可以繼續往下看。
我們看下關鍵中的關鍵:
src/index.ts
const browser = process.env.NODE_ENV === 'production' ?
// 正式環境需要開啟沙盒模式
await puppeteer.launch({
args: ['--no-sandbox', '--disable-setuid-sandbox'],
}) :
// 非正式環境則隨意
await puppeteer.launch({
headless: false, // 非無頭模式,
devtools: true, // 除錯模式,可以在控制檯看到 console
});
因為如果是通過 Docker 構建 Node.js 服務的話,我們是沒法正常啟動 Puppeteer 的,所以需要:
- 設定 Dockerfile
- 設定
launch
的姿勢
這裡我們的 package.json
程式碼:
package.json
"scripts": {
"robot": "cross-env NODE_ENV=production ts-node ./src/index.ts robot",
"robot-test": "cross-env NODE_ENV=test ts-node ./src/index.ts robot"
},
所以,我們設定到 launch
後,只需要在在正式環境執行 npm run robot
,即可啟動沙盒模式。
三、編寫 Dockerfile
話不多說,我們直接編寫 Dockerfile:
Dockerfile
# 官方文件 https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#running-puppeteer-in-docker
# 基於 Alpine Linux 的最小 Docker 影像,具有完整的包索引,大小僅為 5 MB!
FROM alpine:edge
# 指定執行 CMD 的目錄,即先 cd 到該目錄上
WORKDIR /home/docker/we_render
# 安裝最新版 Chromium(89) 的包
RUN apk add --no-cache \
chromium \
nss \
freetype \
harfbuzz \
ca-certificates \
ttf-freefont \
nodejs \
yarn
# 跳過自動安裝 Chrome 包. 使用上面已經安裝的 Chrome
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true \
PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser
# Puppeteer v6.0.0 配套 Chromium 89
RUN yarn add puppeteer@6.0.0
# 拷貝宿主機的檔案到容器中的 we_render 目錄
COPY . /home/docker/we_render
# 通過 yarn 設定淘寶源和裝包,並清除快取
RUN yarn config set registry 'https://registry.npm.taobao.org' && \
yarn global add pm2 && \
yarn install && \
yarn cache clean
# 宣告容器提供的服務埠
EXPOSE 9527
# 容器主程式的啟動命令
CMD ["yarn", "run", "robot"]
然後只需要按部就班建立映象和建立容器等操作即可。
四、啟動服務
注意:強烈建議先切換映象,否則下載內容會非常慢,之前我在公司操作還行,回來自己掛科學上網也整了好久(3000s)。
修改映象方法:03 - 入門 & 概念解疑
- 建立映象(Image):
docker image build ./ -t docker-node:1.0.0
- 建立容器(Container):
docker container create -p 3333:80 docker-node:1.0.0
- 啟動容器(Container):
docker restart dd420fc4267ad3bdb9eadfdbf37d89e2592dbc9d030a501b96fe10b07ac565ff
- 檢視容器(Container)執行情況:
docker ps -a
- 檢視容器(Container)的日誌:
docker logs -f dd420fc4267a
- 進入容器(Container):
docker exec -it dd420fc4267a bash
- 前往目錄:
cd src/source
- 檢視目錄內容:
ls
可以看到,我們已經有幾張截圖了:
使用前面學習的方法,將容器的內容拷貝出來,並檢視下:docker cp f5000c4a530b:/home/docker/we_render/src/source E:\MyWeb\all-for-one
雖然不懂 ??? 是什麼鬼,但是好歹能正常運轉了!
那麼,我們將 Puppeteer 塞到 Docker 上就成功啦,剩下的只需要將時區和 Hosts 設定下就可以了,這裡就不一一贅述了。
這樣,我們的 Docker 之旅就先告一段落了,感興趣的小夥伴歡迎催更,後續的 本地編寫 Git 倉庫程式碼,然後 push 到 GitHub 後,走 CI/CD 並更新到伺服器…… 操作,只能等 jsliang 有時間了再進一步更新啦!
我是 jsliang,一個充滿探索欲,喜歡折騰,樂於擴充套件自己知識面的終身學習斜槓程式設計師,讓我們一起來折騰探索吧!
不折騰的前端,和鹹魚有什麼區別!
覺得文章不錯的小夥伴歡迎點贊/點 Star。
如果小夥伴需要聯絡 jsliang:
個人聯絡方式存放在 Github 首頁,歡迎一起折騰~
爭取打造自己成為一個充滿探索欲,喜歡折騰,樂於擴充套件自己知識面的終身學習斜槓程式設計師。
jsliang 的文件庫由 樑峻榮 採用 知識共享 署名-非商業性使用-相同方式共享 4.0 國際 許可協議 進行許可。<br/>基於 https://github.com/LiangJunrong/document-library 上的作品創作。<br/>本許可協議授權之外的使用許可權可以從 https://creativecommons.org/licenses/by-nc-sa/2.5/cn/ 處獲得。