docker-compose で gulp コンテナを立てる時の注意点 (2018/06)

> 個人で docker-compose を使って開発環境を立ててるんですが、 Gulp を導入する時に色々と躓いたので備忘録も兼ねて書かせて頂きました。私もまだまだ経験不足なので、問題・改善点などご指摘がある方はバンバン突っ込んで頂けたらと思います。

## 要点
- このコンテナは起動と同時に、Gulp タスクの Watch を開始するサービスを行うものです。
- ここでは自分で debian へ node.js をインストールする方法ですが、公式の node イメージを使う方法もあるかと思います。そちらはまた機会があれば紹介します。
- Gulp はグローバル・プロジェクトローカル双方へのインストールが必要
- n のインストールが必要
- gulp を使うための sass のインストールが必要
- volume のマウント先と gulp のローカルインストール先の重複はダメ

# ファイル構成

下の Compose には Gulp しか載せてませんが、本当はもっとたくさんコンテナがあります。

```yml:docker-compose.yml
version: "3.2"

services:
  # gulp: CSS/JavaScript Compilation Automating
  gulp:
    container_name: gulp
    build:
      context: d_gulp
    # volume 設定するところが一番躓いたので Docker の知識が浅い人は特に注意
    volumes:
      - resources:/home/dest
      - ./app/resources:/home/gulp

volumes:
  resources:
```
```docker:Dockerfile
FROM debian:jessie

MAINTAINER Name <E-mail Address>

RUN apt-get -y update && apt-get -y dist-upgrade
RUN apt-get -y install \
    curl \
    git

# node.js インストール → n をインストールするため
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash --
RUN apt-get -y install \
    nodejs \
    vim \
    ruby \
    ruby-dev \
    rubygems \
    gcc \
    build-essential \
    patch

# sass インストール
RUN gem update --system
RUN gem install sass

# npm を最新にアップデート
# n をインストール → latest にアップデート
RUN npm install -g npm && npm cache verify
RUN npm i -g n && n latest

# gulp のグローバルインストール
RUN npm i -g gulp gulp-cli

# gulp の実行場所の一つ上のディレクトリへ移動
WORKDIR /home

# package.json の自動作成
RUN npm init -y

# ローカルインストール
RUN npm install --save-dev \
    gulp \
    gulp-sass \
    gulp-csscomb \
    gulp-autoprefixer \
    gulp-changed \
    gulp-plumber \
    gulp-notify

# gulp を実行するディレクトリへ移動
WORKDIR gulp

CMD ["gulp"]
```

## 注意点①：node.js のインストール時

```dockerfile

RUN curl -sL https://deb.nodesource.com/setup_10.x | bash --
```
`https://deb.nodesource.com/` に curl するとかなり古いバージョンを取ってきちゃうので `setup_10.x` など新しいバージョンの URL を指定する。

#### Error Message (WARN) <- `$ docker-compose build`

```docker
================================================================================
================================================================================

                           SCRIPT DEPRECATION WARNING

  This script, located at https://deb.nodesource.com/setup, used to
  install Node.js 0.10, is deprecated and will eventually be made inactive.

  You should use the script that corresponds to the version of Node.js you
  wish to install. e.g.

   * https://deb.nodesource.com/setup_8.x 窶・Node.js 8 LTS "Carbon" (recommended)
   * https://deb.nodesource.com/setup_10.x 窶・Node.js 10 Current

  Please see https://github.com/nodejs/Release for details about which
  version may be appropriate for you.

  The NodeSource Node.js Linux distributions GitHub repository contains
  information about which versions of Node.js and which Linux distributions
  are supported and how to use the install scripts.
    https://github.com/nodesource/distributions

================================================================================
================================================================================
```

## 注意点②：Sass インストール用のパッケージインストール

Sass のインストールに必要なパッケージのインストール：

- Ruby 関連：ruby / ruby-dev / rubygems  
- Make(コンパイル) 関連：gcc / build-essential / patch

#### Error Message <- `docker-compose build`
```docker

ERROR:  Error installing sass:
        ERROR: Failed to build gem native extension.

    current directory: /var/lib/gems/2.1.0/gems/ffi-1.9.25/ext/ffi_c
/usr/bin/ruby2.1 -r ./siteconf20180630-6-o2i9ue.rb extconf.rb
checking for ffi.h... *** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.
```

## 注意点③：Gulp のインストール
### グローバルとプロジェクトローカルの両方にインストールする
まず `npm i -g gulp gulp-cli` してから、プロジェクトディレクトリ内で `npm install --save-dev gulp` する。

> ※ グローバルにインストールすることで gulp コマンドを利用できるようにし、その上でローカルインストールによってパッケージごとに gulp を管理する。最近ではパッケージの依存関係の解決やその他の管理のしやすさからローカルでの管理が主流になっているようです。
> ※ ローカルだけにインストールすることも可能ですが、コマンドの使いやすさから自分はグローバルにインストールをしておく方法を選択しました。

### Compose の volume マウント先と Gulp ローカルインストール先は同じにしない

ローカルに Gulp をインストールするとそのディレクトリに `Node_modules` が追加されるのですが、Gulp の実行先だからと volume をマウントすると、ホスト側のファイルがコンテナの起動後にそこにコピーされ、せっかくインストールされたローカルの Gulp が削除されてしまいます。
この問題への解決策は、

- Gulp のタスクを実行するディレクトリの一つ上にローカルインストール (私の場合、/home)
- `WORKDIR`でタスク実行ディレクトリへ移動 (私の場合、/home/gulp )
- docker-compose.yml ではこの `/home/gulp` に volume をマウント

こうすれば、このコンテナの起動後にローカルの Gulp を消されずに済みます。

```dockerfile:Dockerfile
RUN npm i -g gulp gulp-cli

WORKDIR /home
RUN npm init -y

RUN npm install --save-dev \
    gulp \
    gulp-sass \
    gulp-csscomb \
    gulp-autoprefixer \
    gulp-changed \
    gulp-plumber \
    gulp-notify

WORKDIR gulp
```
```yml:docker-compose.yml
version: "3.2"

services:
  # gulp: CSS/JavaScript Compilation Automating
  gulp:
    container_name: gulp
    build:
      context: d_gulp
    volumes:
      - resources:/home/dest
      - ./app/resources:/home/gulp

volumes:
  resources:
```

#### Error Message <- `docker-compose up -d`
```docker
Attaching to nginx, gulp
gulp     | [08:53:33] Local gulp not found in /home
gulp     | [08:53:33] Try running: npm install gulp
gulp exited with code 1
```