Mithrilで書いたフロントアプリをdockerコンテナに入れる～EHW2018「アプリ③」

# 概要

このエントリは、「Enterprise "hello, world" 2018 Advent Calendar 2018」の12/17向けのものです。このAdvent Calendarでは、複数個のエントリにまたがる話の流れも鑑みつつ、なるべく1エントリで１つのトピックをカバーできるようにする予定です。

このエントリで記載するトピックは、第15日目の「[Mithrilで書いたフロントアプリ](https://qiita.com/hrkt/items/bcf8b58d6d51763d0439)をdockerコンテナに入れることです。

# 前提

## おことわり

- このEnterpfise "hello, world"シリーズは、ネタのためのエントリです。実環境でそのまま利用ことを目的とはしていません。
- 動かしやすさを優先してセキュリティを意図的に低くする設定など入れてありますのでご注意ください。

## 想定読者

「Enterprise "hello, world" 2018」的なネタとしては、下記のような状況を想定しています。

> k8sでアプリを動かすために、まずはDockerコンテナにアプリを入れる必要がある。

# Dockerコンテナに押し込める

[第15日目のフロントアプリ](https://qiita.com/hrkt/items/bcf8b58d6d51763d0439)をNginxでホストする構成を作ります。


## 参考にしたサイト

以下のサイトを参考にしました。

- [Vue.js アプリケーションを Docker 化する](https://jp.vuejs.org/v2/cookbook/dockerize-vuejs-app.html)
- [Docker Hubのnginxサイト](https://hub.docker.com/_/nginx/)

## Dockerfile

ビルド用と稼働用の2ステージで動作するDockerfileです。nginxは、エントリ執筆時点の一番新しいものを使っています。

```
# Build
FROM node:9.11.1-alpine as build-stage
WORKDIR /app
COPY package.json ./
RUN npm install
COPY . .
RUN npm run build

# Production
FROM nginx:1.15.7-alpine as production-stage
COPY ./index.html /usr/share/nginx/html
COPY --from=build-stage ./bin/* /usr/share/nginx/html/bin/
EXPOSE 80
CMD /usr/sbin/nginx -g "daemon off;"
```

## Makefile

下記のようなMakefileを用意しました。

```
LABEL=front-test:latest

build:
        sudo docker build -t $(LABEL) .

run:
        sudo docker run -p 8080:80 $(LABEL)

clean-container:
        sudo docker image prune
        sudo docker container prune

clean:
        rm -rf bin
```

## コンテナをビルド

実行結果は以下のようになります。

```
$ make build
sudo docker build -t front-test:latest .
Sending build context to Docker daemon   52.8MB
Step 1/11 : FROM node:9.11.1-alpine as build-stage
 ---> 9cc7800b3f3c
Step 2/11 : WORKDIR /app
 ---> Using cache
 ---> 1c39a218079f
Step 3/11 : COPY package.json ./
 ---> Using cache
 ---> 2442cc90e4a8
Step 4/11 : RUN npm install
 ---> Using cache
 ---> 1cb579f128bf
Step 5/11 : COPY . .
 ---> 01f64c788ea5
Step 6/11 : RUN npm run build
 ---> Running in 7294ef22f5fc

> frontend-mithril@0.0.1 build /app
> webpack src/index.js --output bin/app.js -p

Hash: 7582df46dbea680b6752
Version: webpack 4.28.1
Time: 5090ms
Built at: 2018-12-22 23:32:33
 Asset      Size  Chunks             Chunk Names
app.js  27.9 KiB       0  [emitted]  main
Entrypoint main = app.js
[0] (webpack)/buildin/global.js 472 bytes {0} [built]
[2] ./src/index.js 136 bytes {0} [built]
[6] ./src/helloworld-component.js 121 bytes {0} [built]
    + 4 hidden modules
Removing intermediate container 7294ef22f5fc
 ---> ebce0550a3e4
Step 7/11 : FROM nginx:1.15.7-alpine as production-stage
 ---> 63356c558c79
Step 8/11 : COPY ./index.html /usr/share/nginx/html
 ---> Using cache
 ---> 5c5df16090a4
Step 9/11 : COPY --from=build-stage ./bin/* /usr/share/nginx/html/bin/
 ---> Using cache
 ---> 2b7ba0215c44
Step 10/11 : EXPOSE 80
 ---> Using cache
 ---> 5416d0e51d6f
Step 11/11 : CMD /usr/sbin/nginx -g "daemon off;"
 ---> Using cache
 ---> 33cf834141e9
Successfully built 33cf834141e9
Successfully tagged front-test:latest
```

## 動かしてみる

ターミナルを2つ用意し、一方でサーバを動かします。

```
$ make run
sudo docker run -p 8080:80 front-test:latest
172.17.0.1 - - [22/Dec/2018:23:34:11 +0000] "GET / HTTP/1.1" 200 179 "-" "curl/7.58.0" "-"
```

もう一方で、クライアントを動かしてアクセスしてみます。

```
$ make check
curl http://localhost:8080/
<!DOCTYPE html>
<html>
  <head>
    <title>Enterprise "hello,world"</title>
    <meta charset="UTF-8">
  </head>
  <body>
    <script src="bin/app.js"></script>
  </body>
```

無事ページが表示されたようです。


# まとめ

このエントリでは、「Enterprise "hello, world" 2018 Advent Calendar 2018」(EHW2018)の17日目として、Mithrilで書いたフロントアプリをdockerコンテナに入れることをトピックとして取り上げました。

本エントリのソースコードは、[https://github.com/hrkt/frontend-mithril/releases/tag/0.0.2](https://github.com/hrkt/frontend-mithril/releases/tag/0.0.2)にあげてあります。

EHW2018のネタとしては、このあと、バック側もコンテナ化して、設定できる項目を増やしたうえで、k8sにデプロイすること考えています。