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` したら以下のエラーに遭遇した。

```shell-session
/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 のコンパイル時に止まる…

## 結論

作成するコンテナにて `openssl` と `bash` と `libpng-dev` が必要。

## 前提

作業開始時の Dockerfile は以下。

```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 してみた

```shell-session
/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` 部分でエラーが生じているみたい。

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

```shell-session
> 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-374911339 に `node:9-alpine` で同じ問題に出くわしたよーってコメント発見。

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

どうやら `openssl` と `bash` が必要らしい。

## 試してみる

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 だった。

```shell-session
/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` してみる。

```shell-session
/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` してみる。

```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 \
    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 \`が増えただけ。

```shell-session
/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 が足りてないらしいので、インストールしておく。

```shell-session
/myapp # npm install ajv --save-dev
```

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

### おまけ2: `fsevents` の `WARN optional` と `WARN notsup`

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

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