LoginSignup
3
2

More than 3 years have passed since last update.

AngularのためのDockerfileの書き方

Last updated at Posted at 2019-08-16

皆さん、Angular使ってますか?

私は仕事でも趣味でもAngularを使うAngular大好き人間ですが、共同開発なんかで動作確認してもらうとき、node入れて@angular/cli入れてng serveして…となってしまい、結構環境が汚れてしまうのが難点だなーと思っていました。

あと、本番環境のときng build --prodして出来たビルドファイルをWinSCPで直上げするのも何とかしたい。いちいちコマンド叩いてWinSCP開くのめんどくせぇ…

でも@angular/cliの便利さは捨てがたい…特にオートリロードが…

というわけで、「AngularアプリをDockerの上で動かす」ことに挑戦してみましたので、知見を残しておきます。

仕様

  • 本番環境としても開発環境としても使えること
  • 本番環境ではnginxを用いること
  • 開発環境ではオートリロードしたい
  • 一つのDockerfileにまとめる

方法

Dockerのマルチステージビルドを使います。

Dockerfile
### ベースステージ ###
FROM node:lts-alpine as base

# @angular/cliをグローバルインストール
RUN npm install -g @angular/cli

# ワーキングディレクトリの設定
WORKDIR /some-angular-app

# package.jsonをコピー
COPY ./package*.json /some-angular-app/

# 一度node_modulesを削除してからnpm install
RUN rm -rf node_modules && npm install


### ビルドステージ ###
FROM base as build

# 全てのソースファイルをコピー
COPY ./ /some-angular-app/

# 本番用ビルド
RUN ng build --prod --output-path=./dist/build-by-docker


### プロダクションステージ ###
FROM nginx:alpine as prod

# ビルドステージで生成されたファイルをnginxの公開用ディレクトリにコピー
COPY --from=build /some-angular-app/dist/build-by-docker /usr/share/nginx/html

# nginx.confをコピー
COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf

Dockerfileではソースのコピーとビルド処理、ビルド結果のコピーのみを行い、
主たるコマンドはdocker-compose.ymlに書きます。

docker-compose.yml
version: "3.4"

services:
    node:
        build:
            context: ./
            dockerfile: "Dockerfile"
            target: base
        ports:
            - "4200:4200"
        command: sh -c "ng serve --host 0.0.0.0 --poll=1000"
        volumes:
            - .:/some-angular-app
            - node_modules:/some-angular-app/node_modules
        tty: true
volumes:
    node_modules:
        driver: "local"

こちらは開発環境用のdocker-compose.ymlです。Dockerfileにおけるbaseステージを継承して動きます。

volumesでソースコードをマウントしているため、Dockerfile内で特にCOPYをしなくてもこれで動きます。
node_modulesをマウント対象から除外するのを忘れないようにして下さい。

commandですが、ng serve --host 0.0.0.0 --poll=1000がミソです。

Dockerコンテナは、ホストPCとlocalhostを共有していますが、コンテナ内で動いている@angular/cliにはそんなことは知ったこっちゃないため、@angular/cliが言うところの「localhost」は、Dockerコンテナの「localhost」だけなのです。

つまり、--hostオプションで「同ネットワークに接続しているすべてのIPアドレス」からのアクセスを許可してあげなければなりません。

また、オートリロードを正しく作動させるために、--pollオプションでファイル変更状況をポーリングするように設定しています。単位はmsです。

docker-compose.prod.yml
version: "3.4"

services:
    node:
        build:
            context: ./
            dockerfile: "Dockerfile"
            target: prod
        ports:
            - "8080:80"
        tty: true

こちらは本番用のdocker-compose.prod.ymlです。prodステージを継承して動きますが、特筆して何かをしているわけではありません。

.dockerignore
.git
dist
*Dockerfile*
*docker-compose*
node_modules

COPY時にnode_modulesがコピーされないよう、.dockerignoreに書いておきます。

default.conf
server {
    listen 80;
    server_name  localhost;

    root   /usr/share/nginx/html;
    index  index.html index.htm;
    include /etc/nginx/mime.types;

    gzip on;
    gzip_min_length 1000;
    gzip_proxied expired no-cache no-store private auth;
    gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    location / {
        try_files $uri $uri/ /index.html;
    }
}

最後に、nginxのconfフォルダにコピーしているdefault.confです。
Angularをnginxで動かすために必要な「すべてのURIに対するアクセスをindex.htmlに流す」処理を行っているだけです。適宜変更してください。

立ち上げ方

# 開発
$ docker-compose up --build

# 本番
$ docker-compose -f docker-compose.prod.yml up --build 

まとめ

マルチステージビルドを使って、docker-composeコマンド一発でAngularアプリを立ち上げる環境を構築することができましたが、予想通りというかなんというか、直接ホストPCでng serveしたときよりはかなりビルドが重いです。

他人の環境を汚さないようにするだけでもかなりメリットはありますが、自分がゴリゴリ開発する立場だったら素直にホストPCに@angular/cli入れた方がいいと思いました。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2