npm
laravel
docker
pngquant
alpine

laravel 5.6 + laravel-mix 2.x (docker with alpine linux)にて、 npm install したら pngquant で libpng-dev のエラーが出たから暫定対応したメモ

2018-04-18 時点で、 Laravel 5.6 では、 laravel-mix:2.0 が使われるようになってる。

Docker container のベースイメージを php:7.2-fpm-alpine とした環境で # npm install したら以下のエラーに遭遇した。

/myapp # npm install
// (中略)
Error: pngquant failed to build, make sure that libpng-dev is installed

このエラーに取り敢えず対応したメモ。

※ 2018-04-19 01:34 以下の内容に一部修正しました。

Docker のベースイメージを php:7.2-fpm-alpine3.7 に変更しました。 php:7.2-fpm-alpine だと、 nodejs が v6.10.3, npm が 3.10.10 となっていて、 # npm run dev を行った際に、 app.scss のコンパイル時に止まる…

結論

作成するコンテナにて opensslbashlibpng-dev が必要。

前提

作業開始時の Dockerfile は以下。

FROM php:7.2-fpm-alpine3.7

RUN apk --no-cache update && \
    apk --no-cache upgrade && \
    apk --no-cache add \
    curl-dev \
    freetype-dev \
    libjpeg-turbo-dev \
    libpng-dev \
    libxml2-dev \
    zlib-dev \
    pcre-dev \
    g++ \
    make \
    autoconf \
    openssl \
    nodejs-npm \
  && docker-php-ext-install \
    curl \
    dom \
    mbstring \
    pdo \
    pdo_mysql \
    simplexml \
    zip \
    opcache \
  && docker-php-ext-configure gd \
    --with-freetype-dir=/usr/include/ \
    --with-jpeg-dir=/usr/include/ \
    --with-png-dir=/usr/include/ \
  && docker-php-ext-install gd \
  && curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \
  && chmod +x /usr/local/bin/composer \
  && rm -rf /var/cache/apk/*

php 関連諸々と、 composer と nodejs-npm にて、 Nodejs と npm をインストールした状態。

npm install してみた

/myapp # node -v
v8.9.3
/myapp # npm -v
5.5.1
/myapp # npm install
// 略
> pngquant-bin@4.0.0 postinstall /myapp/node_modules/pngquant-bin
> node lib/install.js

  ⚠ spawn /myapp/node_modules/pngquant-bin/vendor/pngquant ENOENT
  ⚠ pngquant pre-build test failed
  ℹ compiling from source
  ✔ pngquant pre-build test passed successfully
  ✖ Error: pngquant failed to build, make sure that libpng-dev is installed
    at Promise.all.then.arr (/myapp/node_modules/pngquant-bin/node_modules/bin-build/node_modules/execa/index.js:231:11)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:188:7)
npm WARN ajv-keywords@3.1.0 requires a peer of ajv@^6.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.1.3 (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.1.3: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! pngquant-bin@4.0.0 postinstall: `node lib/install.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the pngquant-bin@4.0.0 postinstall script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2018-04-18T16_45_59_338Z-debug.log

ひとまず WARN は無視するとして、 pngquant-bin@4.0.0 postinstall 部分でエラーが生じているみたい。

具体的には、以下の箇所が該当する。

> pngquant-bin@4.0.0 postinstall /myapp/node_modules/pngquant-bin
> node lib/install.js

  ⚠ spawn /myapp/node_modules/pngquant-bin/vendor/pngquant ENOENT
  ⚠ pngquant pre-build test failed
  ℹ compiling from source
  ✔ pngquant pre-build test passed successfully
  ✖ Error: pngquant failed to build, make sure that libpng-dev is installed
    at Promise.all.then.arr (/myapp/node_modules/pngquant-bin/node_modules/bin-build/node_modules/execa/index.js:231:11)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:188:7)

エラー内容を見る限り、 libpng-dev が入ってるか確認してってことらしい。

が、前述の Dockerfile の通り libpng-dev はインストール済み。

別の何かに問題があるっぽい。

原因を探す

pngquant-bin にて、何かが起きているだろうと考えられるので pngquant-bin の Repository の Issue で libpng-dev を検索してみる。

https://github.com/imagemin/pngquant-bin/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+libpng-dev

と、「node_modules/pngquant-bin/vendor/pngquant` binary doesn't seem to work correctly」という、それっぽいタイトルの Issue があるので、取り敢えず中を見てみる。

で、読み進めてると https://github.com/imagemin/pngquant-bin/issues/78#issuecomment-374911339node:9-alpine で同じ問題に出くわしたよーってコメント発見。

そのコメントの次の投稿である https://github.com/imagemin/pngquant-bin/issues/78#issuecomment-374913757 にて、「エラーメッセージ間違ってるやんけ!!!」ってコメント発見。

どうやら opensslbash が必要らしい。

試してみる

https://github.com/imagemin/pngquant-bin/issues/78#issuecomment-374913757 には、

wget http://pngquant.org/pngquant-2.10.1-src.tar.gz
Connecting to pngquant.org (83.169.2.68:80)
Connecting to pngquant.org (83.169.2.68:443)
wget: can't execute 'ssl_helper': No such file or directory
wget: error getting response: Connection reset by peer

~/pngquant-2.10.1 # ./configure --prefix=/root/test/
env: can't execute 'bash': No such file or directory

とある。

前述の Dockerfile にある通り、 openssl は入っているので、 wget は問題なく通るはず。

で、 ./configure 部分でエラーになるはず。

やってみる。

https://pngquant.org/ に行き、 all releases から pngquant-2.11.7-src.tar.gz の URL を調べておく。

http://pngquant.org/pngquant-2.11.7-src.tar.gz だった。

/myapp # wget http://pngquant.org/pngquant-2.11.7-src.tar.gz
Connecting to pngquant.org (83.169.2.68:80)
Connecting to pngquant.org (83.169.2.68:443)
pngquant-2.11.7-src. 100% |********(略)******|   138k  0:00:00 ETA

無事にダウンロード出来たので ./configure してみる。

/myapp # tar -zxvf pngquant-2.11.7-src.tar.gz
/myapp # cd pngquant-2.11.7/
/myapp/pngquant-2.11.7 # ./configure
env: can't execute 'bash': No such file or directory

お! bash が必要です、とのことです。

どうやら正解っぽい。

※なんで bash が必要なのかまでは見てない。。

Dockerfile に bash を追加して再び npm install してみる。

FROM php:7.2-fpm-alpine3.7

RUN apk --no-cache update && \
    apk --no-cache upgrade && \
    apk --no-cache add \
    curl-dev \
    freetype-dev \
    libjpeg-turbo-dev \
    libpng-dev \
    libxml2-dev \
    zlib-dev \
    pcre-dev \
    g++ \
    make \
    autoconf \
    openssl \
    nodejs-npm \
    bash \
  && docker-php-ext-install \
    curl \
    dom \
    mbstring \
    pdo \
    pdo_mysql \
    simplexml \
    zip \
    opcache \
  && docker-php-ext-configure gd \
    --with-freetype-dir=/usr/include/ \
    --with-jpeg-dir=/usr/include/ \
    --with-png-dir=/usr/include/ \
  && docker-php-ext-install gd \
  && curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \
  && chmod +x /usr/local/bin/composer \
  && rm -rf /var/cache/apk/*

※前提にて記載した内容に bash \が増えただけ。

/myapp # npm install
// 略
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN ajv-keywords@3.1.0 requires a peer of ajv@^6.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.1.3 (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.1.3: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})

インストール出来た!

おまけ1: ajv

npm WARN ajv-keywords@3.1.0 requires a peer of ajv@^6.0.0 but none was installed. とある通り、 ajv が足りてないらしいので、インストールしておく。

/myapp # npm install ajv --save-dev

package.jsondevDependencies 節に "ajv": "^6.4.0", とかが増えてるはず。

おまけ2: fseventsWARN optionalWARN notsup

http://mimirswell.cliptrash.com/blog-221

Dockerfile 記載の通り、 alpine なので、 --no-optional を付けて npm コマンドを実行すれば警告は消える。