Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

Dockerを使ってHeadless Chromeを動かしてみる

More than 1 year has passed since last update.

Chrome 59からChromeをヘッドレス環境で実行するHeadless Chromeが搭載されました。
自動テスト等でこの機能を使えると便利そうな気がしたので、DockerでHeadless Chrome
が使える環境を整えてみます。

Docker Imageの作成

alpine linuxにはgoogle chromeのパッケージはありません。chromeの元となるオープンソース実装のchromiumのpackageを検索してみると、最新版のchromiumが59.0.3071.86-r0
なっています。
これを利用すればHeadlessで動かすことが出来そうなので、今回はこのパッケージを
利用してみました。Branchがedgeとなっていますので、alpine linuxのイメージを
edgeのものを使用しました。

Dockerfile
From alpine:edge

RUN  apk add --update chromium

ENTRYPOINT tail -f /dev/null

まずはchromiumをインストールしたImageを作成します。

$ docker build -t chromium_headless ./
Sending build context to Docker daemon 2.048 kB
Step 1/3 : FROM alpine:edge
 ---> 1673780955f9
Step 2/3 : RUN apk add --update chromium
 ---> Running in de86344e5110
fetch http://dl-cdn.alpinelinux.org/alpine/edge/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/edge/community/x86_64/APKINDEX.tar.gz
(1/78) Installing libxau (1.0.8-r1)
(2/78) Installing libbsd (0.8.3-r3)
...
(78/78) Installing chromium (59.0.3071.86-r0)
Executing busybox-1.26.2-r4.trigger
Executing glib-2.52.1-r0.trigger
Executing shared-mime-info-1.8-r0.trigger
Executing gdk-pixbuf-2.36.6-r0.trigger
Executing gtk-update-icon-cache-2.24.31-r0.trigger
OK: 260 MiB in 89 packages
 ---> 2e0a5a6babb5
Removing intermediate container 92491faa6417
Step 3/3 : ENTRYPOINT tail -f /dev/null
 ---> Running in 87ea1b256a97
 ---> 2772165613b3
Removing intermediate container 87ea1b256a97
Successfully built 2772165613b3

動作確認

イメージの作成が完了したので、コンテナを起動して、chromiumの動作を確認します。

$ docker run -d chromium_headless
b839da3b3b34964390a50c0747df475204977979e3d5192ccc98ec7d3643d66d
$ docker exec -it b83 ash
/ # chromium-browser --version
Chromium 59.0.3071.86
/ # chromium-browser --headless --disable-gpu --dump-dom --no-sandbox https://www.chromestatus.com/
[0613/121607.247566:WARNING:dns_config_service_posix.cc(326)] Failed to read DnsConfig.
[0613/121607.257087:FATAL:udev_loader.cc(38)] Check failed: false.
Received signal 6
  r8: 0000000000000061  r9: 00007fcf9c22a066 r10: 0000000000000008 r11: 0000000000000246
 r12: 00007fcf9c229ed0 r13: 00007fcf9c229e80 r14: 0000000000000000 r15: 0000000000000000
  di: 0000000000000002  si: 00007fcf9c229da0  bp: 00007fcf9c229da0  bx: 0000000000000006
  dx: 0000000000000000  ax: 0000000000000000  cx: 00007fcfb09e86bf  sp: 00007fcf9c229d88
  ip: 00007fcfb09e86bf efl: 0000000000000246 cgf: 002b000000000033 erf: 0000000000000000
 trp: 0000000000000000 msk: 0000000000000000 cr2: 0000000000000000
[end of stack trace]
Calling _exit(1). Core file will not be generated.

chromiumのバージョンまでは表示することが出来て、無事にインストールされていることが確認出来ましたが、
Headlessで起動すると上記のようなエラーが出てしまいました。このエラーを確認する限りudevのパッケージの必要なようです。
最終的にttf-freefontも必要で、以下のようなDockerfileになりました。

Dockerfile
From alpine:edge

RUN apk add --update \
        udev \
        ttf-freefont \
        chromium

ENTRYPOINT tail -f /dev/null

イメージをビルドして、もう動作を確認すると以下のような結果になり、Headlessで動くことが確認できました。

/ # chromium-browser --headless --disable-gpu --dump-dom --no-sandbox https://www.chromestatus.com/
[0613/124631.067381:WARNING:dns_config_service_posix.cc(326)] Failed to read DnsConfig.
<body class="loading">

<!--<div id="site-banner">
  <a href="https://www.youtube.com/watch?v=Rd0plknSPYU" target="_blank">
  <iron-icon icon="chromestatus:ondemand-video"></iron-icon> How we built it</a>
</div>-->
...
// End Google Analytics

lazyLoadWCPolyfillsIfNecessary();
</script>


</body>

pdfの出力とスクリーンショットの取得も試してみましたが、正常に動作していることが確認出来ました。

/ # mkdir outputs && cd outputs
/outputs # chromium-browser --headless --no-sandbox --disable-gpu --print-to-pdf https://www.chromestatus.com
[0613/125229.869694:WARNING:dns_config_service_posix.cc(326)] Failed to read DnsConfig.
[0613/125231.380375:INFO:headless_shell.cc(436)] Written to file output.pdf.
/outputs # chromium-browser --headless --no-sandbox --disable-gpu --screenshot https://www.chromestatus.com
[0613/125243.355846:WARNING:dns_config_service_posix.cc(326)] Failed to read DnsConfig.
[0613/125244.919023:INFO:headless_shell.cc(436)] Written to file screenshot.png.
/outputs # ls
output.pdf      screenshot.png

日本語フォントの追加

前段までの手順でスクリーンショットを取ることは出来ましたが、このままですと
日本語が表示されているサイトのスクリーンショットをとっても日本語の部分が
文字化けした状態でスクリーンショットになってしまいます。
Google Noto Fontsを入れることで日本語を含むサイトでも、文字化けせずに
スクリーンショットが取れるようになります。

Dockerfile
From alpine:edge

RUN apk add --update \
            udev \
            ttf-freefont \
            chromium

RUN mkdir /noto

ADD https://noto-website.storage.googleapis.com/pkgs/NotoSansCJKjp-hinted.zip /noto 

WORKDIR /noto

RUN unzip NotoSansCJKjp-hinted.zip && \
    mkdir -p /usr/share/fonts/noto && \
    cp *.otf /usr/share/fonts/noto && \
    chmod 644 -R /usr/share/fonts/noto/ && \
    fc-cache -fv

WORKDIR /
RUN rm -rf /noto

ENTRYPOINT tail -f /dev/null

Google Noto Fontsを入れたDockerfileは上記のようになります。これで、日本語を含む
サイトでも文字化けせずにスクリーンショットが取れるようになりました。

dd511805
a-hikkoshi
当社は、親会社である株式会社エイチームの経営理念をそのままに、引越しの比較サービス開始以降、大切にしてきた「三方よし」の理念を基本として、世の中に求められるサービスの創造を目指します。 一緒に働けるエンジニアを募集しております。下記URLよりご応募ください。 https://bit.ly/3lwf7QJ
https://hikkoshi.a-tm.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away