Dockerを使ってMacでもWindowsでもコマンド一発で動作するAngular開発環境を作る話

こんにちは、@yusuke_yasuoです。

Angular Advent Calendar 2016の9日目は、Dockerを使ってMacでもWindowsでもコマンド一発で動作するAngular開発環境を作る方法について書きたいと思います。

また今回は範囲外ですが、CI・CD周りも整備していきたいため、Angular CLI (https://github.com/angular/angular-cli) を使って開発してみました。

#Docker使う理由
今回のDocker利用には主に2点ほど理由がありました。
1. 社内にMac派とWindows派がいるため、環境が違うことによって起こる問題の吸収
2. 今後メンバーが増えていく予定があるため、環境構築時間の短縮

#今回のゴール
Angular公式サイトのTUTORIAL (https://angular.io/docs/ts/latest/tutorial/) をDocker上で動かせるところまでを今回のゴールにしようと思います。

検証したgithubリポジトリはこちら↓
https://github.com/yusukeyasuo/angular-cli-example

#まずはDockerを意識せずに作っていく
まずはDockerのことは考えずにただただTUTORIALに従いつつ、雛形を作ったりcomponentやclassを追加する際はAngular CLIを使って作っていきます。


#次にDockerの設定を追加する
Dockerを使うために以下の4つのファイルを追加しました。
1. .dockerignore
2. Dockerfile
3. docker-compose.yml
4. npm-shrinkwrap.json

## 1. .dockerignore
その名の通りで.gitignoreのようにdockerで無視するファイルを指定することができるファイルです。
Dockerfileからイメージをビルドする際には、Dockerfileの存在するディレクトリの中身はtarで固められdaemonへと送られ流のですが、不要なファイルが含まれるとビルドに余計な時間がかかってしまうため、無視したいファイル、ディレクトリはこちらに追加します。

```.dockerignore
node_modules
typings
```

## 2. Dockerfile
Dockerコンテナの構成内容をまとめて記述するシンプルなテキスト形式のファイルです。

```Dockerfile
FROM kenjiskywalker/dockerfile-angular-cli-with-phantomjs
d
ARG APP_HOME

RUN mkdir -p $APP_HOME


COPY package.json npm-shrinkwrap.json $APP_HOME/
WORKDIR $APP_HOME

RUN npm install .
```

## 3. docker-compose.yml
yamlでDockerコンテナに関する起動オプションを記述したファイルです。

```docker-compose.yml
version: '2'
services:
  serve:
    build:
      context: .
      args:
        - APP_HOME=/myapp
    command: ng serve --host 0.0.0.0
    ports:
     - "4200:4200"
    volumes:
     - .:/myapp/
     - /myapp/typings
     - /myapp/node_modules
  test:
    build:
      context: .
      args:
        - APP_HOME=/myapp
    command: ng test --single-run
    ports:
     - "4200:4200"
    volumes:
     - .:/myapp/ 
     - /myapp/typings
     - /myapp/node_modules
  e2e:
    build:
      dockerfile: Dockerfile-e2e
      context: .
      args:
        - APP_HOME=/myapp
    # command: ng e2e
    ports:
     - "4200:4200"
    volumes:
     - .:/myapp/
     - /myapp/typings
     - /myapp/node_modules
```

## 4. npm-shrinkwrap.json
node_modulesにインストールされている全モジュールのバージョン情報が記述されたファイル

```npm-shrinkwrap.json
{
  "name": ":angular-cli-example",
  "version": "0.0.0",
  "dependencies": {
    "@angular/common": {
      "version": "2.2.1",
      "from": "@angular/common@2.2.1",
      "resolved": "https://registry.npmjs.org/@angular/common/-/common-2.2.1.tgz"
    },
    "@angular/compiler": {
      "version": "2.2.1",
      "from": "@angular/compiler@2.2.1",
      "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-2.2.1.tgz"
    },
    "@angular/core": {
      "version": "2.2.1",
      "from": "@angular/core@2.2.1",
      "resolved": "https://registry.npmjs.org/@angular/core/-/core-2.2.1.tgz"
    },
    "@angular/forms": {
      "version": "2.2.1",
      "from": "@angular/forms@2.2.1",
      "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-2.2.1.tgz"
    },
    "@angular/http": {
      "version": "2.2.1",
      "from": "@angular/http@2.2.1",
      "resolved": "https://registry.npmjs.org/@angular/http/-/http-2.2.1.tgz"
    },
    "@angular/platform-browser": {
      "version": "2.2.1",
      "from": "@angular/platform-browser@2.2.1",
      "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-2.2.1.tgz"
    },
    "@angular/platform-browser-dynamic": {
      "version": "2.2.1",
      "from": "@angular/platform-browser-dynamic@2.2.1",
      "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-2.2.1.tgz"
    },
    "@angular/router": {
      "version": "3.2.1",
      "from": "@angular/router@3.2.1",
      "resolved": "https://registry.npmjs.org/@angular/router/-/router-3.2.1.tgz"
    },
    "core-js": {
      "version": "2.4.1",
      "from": "core-js@>=2.4.1 <3.0.0",
      "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz"
    },
    "rxjs": {
      "version": "5.0.0-beta.12",
      "from": "rxjs@5.0.0-beta.12",
      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.0.0-beta.12.tgz"
    },
    "symbol-observable": {
      "version": "1.0.4",
      "from": "symbol-observable@>=1.0.1 <2.0.0",
      "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.4.tgz"
    },
    "ts-helpers": {
      "version": "1.1.2",
      "from": "ts-helpers@>=1.1.1 <2.0.0",
      "resolved": "https://registry.npmjs.org/ts-helpers/-/ts-helpers-1.1.2.tgz"
    },
    "zone.js": {
      "version": "0.6.26",
      "from": "zone.js@>=0.6.23 <0.7.0",
      "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.6.26.tgz"
    }
  }
}
```

# 結果
上記の対応をすることで、

```
$ git clone https://github.com/yusukeyasuo/angular-cli-example
$ cd angular-cli-example
$ docker-compose up serve
```
たったこれだけでAngularの開発環境が整ってしまいます。

Docker便利だな〜