Docker上にVue.js開発環境を作る

DockerでVue開発環境を構築したのでメモしておきます。

## 私の作業マシン
- OS :Windows10 Pro
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178016/e5dcd859-f670-5050-b7e3-7c8e12829fad.png)

```
PS C:\Users\607> docker --version
Docker version 19.03.13, build 4484c46d9d
```

## 手順
### 作業用フォルダにDockerfileとdocker-composeファイルを作成
適当な作業用フォルダの中に2つのファイルを作成します。

#### Dockerfile

```:Dockerfile
FROM node:lts-alpine

WORKDIR /app

RUN apk update && \
    npm install -g npm @vue/cli && \
    yarn install

ENV HOST 0.0.0.0
```
 `FROM` ：ベースとするDockerイメージを指定
 `WORKDIR` ：ワークディレクトリを指定
 `RUN` ：イメージ生成時に実行するコマンドを指定
 `ENV` ：ENV <key> <value>で環境変数 <key> に <value> という値を設定


#### docker-compose.yml

```
version: "3"
services:
  vue-app:
    build:
      context: .
    ports:
      - 9000:8080
    privileged: true
    volumes:
      - .:/app
    tty: true
    working_dir: /app
    stdin_open: true
command: yarn serve
```
`version` ：Compose ファイルの書式のバージョン
`services` ：起動するコンテナーの設定の定義。詳細の設定は[ここ](https://docs.docker.jp/compose/compose-file.html#id15)参照
`command` ：デフォルトのコマンドを上書きする設定

この２ファイルが作成できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178016/d6d9d5e5-1d58-d692-9648-256f8ff0a984.png)

### コンテナを起動
イメージのビルドとコンテナ起動を `docker-compose up` で行います。途中、赤メッセージも出力されますがコンテナが起動してプロンプトが止まった状態になればOKです。
(2回目以降は`docker-compose up -d`でバックグラウンド実行）

```:terminal
PS C:\Users\607\code\docker-vue> docker-compose up
Building vue-app
Step 1/4 : FROM node:lts-alpine
 ---> 9db54a688554
Step 2/4 : WORKDIR /app
 ---> Using cache
 ---> 3010f33e1c7e
Step 3/4 : RUN apk update &&     npm install -g npm @vue/cli
 ---> Running in 5dde1c59a150
fetch http://dl-cdn.alpinelinux.org/alpine/v3.11/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.11/community/x86_64/APKINDEX.tar.gz
v3.11.6-195-g7300bf0a98 [http://dl-cdn.alpinelinux.org/alpine/v3.11/main]
v3.11.6-191-g6405156b94 [http://dl-cdn.alpinelinux.org/alpine/v3.11/community]
OK: 11270 distinct packages available
npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142
npm WARN deprecated @hapi/joi@15.1.1: Switch to 'npm install joi'
npm WARN deprecated @hapi/bourne@1.3.2: This version has been deprecated and is no longer supported or maintained
npm WARN deprecated @hapi/address@2.1.4: Moved to 'npm install @sideway/address'
npm WARN deprecated @hapi/hoek@8.5.1: This version has been deprecated and is no longer supported or maintained
npm WARN deprecated @hapi/topo@3.1.6: This version has been deprecated and is no longer supported or maintained
npm WARN deprecated har-validator@5.1.5: this library is no longer supported
npm WARN deprecated urix@0.1.0: Please see https://github.com/lydell/urix#deprecated
npm WARN deprecated resolve-url@0.2.1: https://github.com/lydell/resolve-url#deprecated
npm WARN deprecated chokidar@2.1.8: Chokidar 2 will break on node v14+. Upgrade to chokidar 3 with 15x less dependencies.
npm WARN deprecated fsevents@1.2.13: fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.

> yarn@1.22.10 preinstall /usr/local/lib/node_modules/@vue/cli/node_modules/yarn
> :; (node ./preinstall.js > /dev/null 2>&1 || true)

/usr/local/bin/vue -> /usr/local/lib/node_modules/@vue/cli/bin/vue.js
/usr/local/bin/npm -> /usr/local/lib/node_modules/npm/bin/npm-cli.js
/usr/local/bin/npx -> /usr/local/lib/node_modules/npm/bin/npx-cli.js

> core-js@3.6.5 postinstall /usr/local/lib/node_modules/@vue/cli/node_modules/core-js
> node -e "try{require('./postinstall')}catch(e){}"

Thank you for using core-js ( https://github.com/zloirock/core-js ) for polyfilling JavaScript standard library!

The project needs your help! Please consider supporting of core-js on Open Collective or Patreon: 
> https://opencollective.com/core-js 
> https://www.patreon.com/zloirock 

Also, the author of core-js ( https://github.com/zloirock ) is looking for a good job -)


> @apollo/protobufjs@1.0.5 postinstall /usr/local/lib/node_modules/@vue/cli/node_modules/@apollo/protobufjs
> node scripts/postinstall


> nodemon@1.19.4 postinstall /usr/local/lib/node_modules/@vue/cli/node_modules/nodemon
> node bin/postinstall || exit 0

Love nodemon? You can now support the project via the open collective:
 > https://opencollective.com/nodemon/donate


> ejs@2.7.4 postinstall /usr/local/lib/node_modules/@vue/cli/node_modules/ejs
> node ./postinstall.js

Thank you for installing EJS: built with the Jake JavaScript build tool (https://jakejs.com/)

npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.2.7 (node_modules/@vue/cli/node_modules/chokidar/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
npm WARN @vue/compiler-sfc@3.0.2 requires a peer of vue@3.0.2 but none is installed. You must install peer dependencies yourself.

+ @vue/cli@4.5.8
+ npm@6.14.8
added 1325 packages from 698 contributors and updated 1 package in 198.97s
Removing intermediate container 5dde1c59a150
 ---> 0b2440267419
Step 4/4 : ENV HOST 0.0.0.0
 ---> Running in fad95ea455a3
Removing intermediate container fad95ea455a3
 ---> 87ed001d6177

Successfully built 87ed001d6177
Successfully tagged docker-vue_vue-app:latest
WARNING: Image for service vue-app was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `do-compose build` or `docker-compose up --build`.
Creating docker-vue_vue-app_1 ... done
                      Attaching to docker-vue_vue-app_1
vue-app_1  | Welcome to Node.js v14.15.0.
vue-app_1  | Type ".help" for more information.
```

### Vueプロジェクトを作成
別のターミナルを開き、コンテナ内にログインしてVueプロジェクトを作成します。

```:terminal
PS C:\Users\607\code\docker-vue> docker exec -it docker-vue_vue-app_1 sh
/app # 
```

上記の状態になればコンテナ内にアクセスできた状態になってますので、Vueプロジェクトを作成します。私は「my-app」という名前で作りましたがなんでもOK。

```:terminal
/app # vue create my-app
?  Your connection to the default yarn registry seems to be slow.
   Use https://registry.npm.taobao.org for faster installation? Yes

Vue CLI v4.5.8
? Please pick a preset: Default (Vue 3 Preview) ([Vue 3] babel, eslint)
? Pick the package manager to use when installing dependencies: Yarn

Vue CLI v4.5.8
✨  Creating project in /app/my-app.
Vue CLI v4.5.8
✨  Creating project in /app/my-app.
⚙️  Installing CLI plugins. This might take a while...

yarn install v1.22.5
info No lockfile found.
[1/4] Resolving packages...                                                                                                 --------] 439/1095
[2/4] Fetching packages...
[#####################################################---------------------------------------------------------------------------------] 440/1095[#####################################################-------------------------------------------------------[#####################################################-------------------------------------------------------------------------[##############################################-----------------------------------------------------------------95[##############################################------------------------------------------------------------------] 450/10info fsevents@2.1.3: The platform "linux" is incompatible with this module.
info "fsevents@2.1.3" is an optional dependency and failed compatibility check. Excluding it from installation.
info fsevents@1.2.13: The platform "linux" is incompatible with this module.
info "fsevents@1.2.13" is an optional dependency and failed compatibility check. Excluding it from installation.

success Saved lockfile.
Done in 486.21s.
�🚀  Invoking generators.
�📦  Installing additional dependencies.

yarn install v1.22.5
[1/4] Resolving packages...
[2/4] Fetching packages...
info fsevents@2.1.3: The platform "linux" is incompatible with this module.
info "fsevents@2.1.3" is an optional dependency and failed compatibility check. Excluding it from installation.
info fsevents@1.2.13: The platform "linux" is incompatible with this module.
info "fsevents@1.2.13" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
Done in 124.87s.
⚓  Running completion hooks...

�📦  Generating README.md...

�🎉  Successfully created project my-app.
�👉  Get started with the following commands:

 $ cd my-app
 $ yarn serve

/app #
```

この時点でフォルダ構成は以下のようになってます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178016/e09f4176-ec1e-1e43-67a7-95d461ff0e61.png)

### Vueアプリ起動確認
試しにVue起動できるか動作確認します。

```:terminal
/app # pwd
/app
/app # ls
Dockerfile          docker-compose.yml  my-app
/app # cd my-app/
/app/my-app # yarn serve
yarn run v1.22.5
$ vue-cli-service serve
 INFO  Starting development server...
98% after emitting CopyPlugin

 DONE  Compiled successfully in 95698ms                                                                       11:32:53 AM

  App running at:
  - Local:   http://localhost:8080/ 

  It seems you are running Vue CLI inside a container.
  Access the dev server via http://localhost:<your container's external mapped port>/

  Note that the development build is not optimized.
  To create a production build, run yarn build.    

```

ブラウザから http:localhost:9000にアクセスして以下の表示になることを確認します。Docker内なら8080ポートですが、Dockerホスト上だと9000ポートにしてますので間違えないように。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178016/006f6347-8912-184c-d0b2-94f0079a1c73.png)

`Ctrl`+Cで戻ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178016/e84bc25b-083b-c0dc-b946-35bd23ab7257.png)

### docker-composeファイルにVue起動コマンドを追加
Web起動コマンドが自動で投入されるようにdocker-composeファイルに`command: yarn serve` １行を追記します。

```:docker-compose.yml
version: "3"
services:
  vue-app:
    build:
      context: .
    ports:
      - 9000:8080
    privileged: true
    volumes:
      - .:/app
    tty: true
    working_dir: /app
    stdin_open: true
command: yarn serve
```

これの応用で色々できそうです。