Googleさんが新しいJPEGエンコーダー『Guetzli』を発表したとのことで、
自分のブログ環境でも試してみました。

from Google、JPEGを35%小さくできるエンコーダー「Guetzli」をオープンソースで公開

まずは、私のブログ環境のご紹介

  1. ローカルでmarkdownを使って記事を書く(静的ジェネレータにHugoを利用)
  2. Gitlabへgit push
  3. Gitlab CI上のHugoで自動ビルドされ、Netlifyにアップロード
  4. Netlifyが良きに公開してくれる

というわけで、Gitlab CIでのビルド時に、
Guetzliの画像エンコードを実行したいと思います。

Gitlab CIの設定を行う(gitlab-ci.yml)

Gitlab CIの設定は、プロジェクトのルート上に.gitlab-ci.ymlを置くことで行えます。
下記を参考にGuetzliを使う設定に変更しました。

from GitLabCIでNetlifyにアップロードしたGitLabページをHTTPSで配信

  • .gitlab-ci.yml
stages:
  - deploy

run_hugo:
  stage: deploy
  image: aota/hugo
  script:
    # update for theme
    - git submodule init
    - git submodule update
    # image encoding
    - pngquant --ext .png --speed 1 static/images/*.png --force || true
    - find static/images/ -name "*.jpg" -type f -exec guetzli {} {} \;
    # create public
    - hugo
    - zip -r -q public.zip public
    - curl -silent --header "Content-Type:application/zip" --header "Authorization:Bearer [Netlify認証キー]" --data-binary "@public.zip" https\://api.netlify.com/api/v1/sites/[サイトID]/deploys > /dev/null
  only:
    - master

DockerHub上にGuetzliを入れたDockerイメージを作成

gitlab-ci.ymlのimageに指定してある『aota/hugo』イメージをDockerHub上に作成します。 これは、GitHubにDockerfileをpushしておいて、AutomatedBuildを使ってDockerHubと連動させると楽です。

上記サイトを参考にこんな感じでDockerfileを作りました。

  • Dockerfile
FROM debian:jessie

MAINTAINER mail@aota.blog

RUN apt-get -qq update \
        && DEBIAN_FRONTEND=noninteractive apt-get -qq install -y --no-install-recommends apt-utils ca-certificates curl zip

# Install git (for git submodule)
RUN apt-get -qq update \
        && DEBIAN_FRONTEND=noninteractive apt-get -qq install -y --no-install-recommends git-core

# Install pngquanti (for image resize)
RUN apt-get -qq update \
        && DEBIAN_FRONTEND=noninteractive apt-get -qq install -y --no-install-recommends pngquant

RUN rm -fr /var/lib/apt/lists/*

# Download and install guetzli
ENV GUETZLI_VERSION 1.0

ADD https://github.com/google/guetzli/releases/download/v${GUETZLI_VERSION}/guetzli_linux_x86-64 /usr/local/bin/guetzli
RUN chmod 755 /usr/local/bin/guetzli

# Download and install hugo
ENV HUGO_VERSION 0.19
ENV HUGO_TARBALL hugo_${HUGO_VERSION}_Linux-64bit.tar.gz
ENV HUGO_BINARY hugo_${HUGO_VERSION}_linux_amd64

ADD https://github.com/spf13/hugo/releases/download/v${HUGO_VERSION}/${HUGO_TARBALL} /usr/local/
RUN tar xzf /usr/local/${HUGO_TARBALL} -C /usr/local/ \
        && ln -s /usr/local/${HUGO_BINARY}/${HUGO_BINARY} /usr/local/bin/hugo \
        && rm /usr/local/${HUGO_TARBALL}

# Create working directory
RUN mkdir /usr/share/blog
WORKDIR /usr/share/blog

# Expose default hugo port
EXPOSE 1313

# Automatically build site
ONBUILD ADD site/ /usr/share/blog
ONBUILD RUN hugo -d /usr/share/nginx/html/

# By default, serve site
ENV HUGO_BASE_URL http://localhost:1313
CMD hugo server -b ${HUGO_BASE_URL}

以上で、GitlabにpushするとGuetzliを使って、
static/images/配下のjpgファイルが自動エンコードされるようになりました。

例えば下記画像の場合、177.24KB から、150.75KBに圧縮できました。

Guetzliはスイスドイツ語でクッキーのこと

メモリの制限について

Guetzliは、1Mピクセルの画像変換ごとに300MB程もメモリをもぐもぐします( ‘ω’)モグモグ
時間もけっこうかかるので、shared runnerではテスト以外やらないほうがいいかも

実際、うっかり5307×3549の画像をエンコードしようとすると、

guetzli' terminated by signal 9や、

Unhandled expection. Most likely insufficient memory available.
Make sure that there is 300MB/MPix of memory available.

とでてエンコードできませんでした。(5307×3549=18Mなので、5.4GBのメモリが必要?) また、Dockerコンテナ上のfreeコマンドってあてになるのかなぁとメモリ確認したところこんな感じ。

$ free -mt
             total       used       free     shared    buffers     cached
Mem:          2004       1207        797          0          1          9
-/+ buffers/cache:       1197        807
Swap:         2047       1786        261
Total:        4052       2993       1059

Gitlab CIで実際に処理を行っているrunnerは、 クラウドサービスDigitalOceanのメモリ4GBのマシンと書いてるし合ってるのかな。
(Swapと合わせて4GBなの?よく分からない(´・ω・`))