BLOG

Docker+VuejsでTODOリストを作る

こんにちは!りゅうです。
今回はVuejsの学習をDocker環境で行ったので、DockerとVuejsの環境構築からTODOリストを作るまでの流れを書いてみました。

この記事で実現したいこと
Docker+Vuejsの環境構築とTODOアプリを作れるようにする

参考にしたサイト
Vue.jsで作るtodoアプリ
docker-composeでシンプルにvue.js環境構築

Docker+Vuejsの環境を構築する

Vueのアプリを動かすコンテナを作成していきます。

フォルダ構成は以下の通りです。serverフォルダはwebコンテナのappフォルダのマウント先です。

PS C:\Users\User\Desktop\DockerVuejs> tree /f
フォルダー パスの一覧
ボリューム シリアル番号は 105F-A1E1 です
C:.
│  docker-compose.yml
│
├─docker
│  └─web
│          Dockerfile
│
└─server

docker-compose.yml

version: '3.8'

services: 
    web:
        container_name: web
        build: ./docker/web
        ports: 
            - 8080:8080
        volumes: 
            - ./server:/app:cached
        tty: true
        stdin_open: true
        privileged: true
        command: /bin/sh

Dockerfile

FROM node:14.15.0-alpine
WORKDIR /app
RUN apk update && \
    npm install && \
    npm install -g npm && \
    npm install -g vue-cli

docker-compose.ymlとDockerfieを作成したら、以下のコマンドでコンテナイメージの作成とコンテナの起動を実行

# イメージのビルドとコンテナ起動を同時に行う --buildは強制ビルドするオプション
docker-compose up -d --build

# 別々に行う場合
# イメージのビルド
docker-compose build

# コンテナの起動 -dはバックグラウンドで行うオプション
docker-compose up -d

ビルドと起動ができたら、コンテナに入りvueのデフォルトAppを作成

# コンテナに入る
docker-compose exec web /bin/sh

# VueのデフォルトApp作成
/app # vue init webpack

デフォルトApp作成時、色々聞かれますが、特になければ回答はYesと基本的なパッケージを選択で問題ないです。

ホスト側のserverフォルダに色々追加されるので、その中から config>index.js を探して、修正していきます。

# hostをlocalhot→0.0.0.0
host: '0.0.0.0', // can be overwritten by process.env.HOST
0.0.0.0にすることでコンテナのlocalhostにコンテナ外部からアクセスが可能
# pollをfalse→true
poll: true, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-

pollをfalse→trueでファイルの変更を起動中に検知

デフォルトAppの作成が終わったら、以下のコマンドでAppを起動

# デフォルトAppの起動(コンテナに入った状態で実行)
/app # npm run dev

localhost:8080にアクセスしてデフォルトの画面が表示されればOKです。

ポート8080が使用されている場合は使用しているものを閉じるか、 config>index.js のport:8080 を空いているポートに変更し、docker-compose.ymlもそれに合わせて修正してあげれば、再設定したポートで表示できるようになります。
docker-compose.ymlを修正した場合は再ビルドをお忘れなく、自分はよくやらかしてます(笑)

ポート7080で設定し直す場合

// 8080→7080
port: 7080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
ports: 
    - 7080:7080
# イメージのビルドとコンテナ起動を同時に行う
docker-compose up -d --build

TODOアプリの作成

TODOアプリに必要なものを作成、修正していきます。
作成
server\src\components\List.vue

修正
server>src>App.vue
server>src>router>index.js

2つの修正ファイルから修正していきます。

<template>
  <div id="app">
    <router-view/>
  </div>
</template>
<img src=”./assets/logo.png”> (Vueのロゴ画像)を削除
export default new Router({
  routes: [
    // /→/helloに変更
    {
      path: '/hello',
      name: 'HelloWorld',
      component: HelloWorld
    },
    // 元々のHelloWorldの3行をそのままコピペしてHelloWorldを→Listに変更
    {
      path: '/',
      name: 'List',
      component: List
    }
  ]
})

server\src\router\index.js ルーターと呼ばれどの画面に遷移するかの制御をします。
Listはこれから作成するTODOリストのファイル名(List.vue)です。

ここまでで、不要なロゴ画像の削除と、ルーターにTODOリスト画面のパスと呼び出すコンポーネントを登録しました。

TODOリストの画面部分を作成していきます。
入力部分とボタン押下時リストを追加するメソッド(ロジックは後述)をまず記述

<template>
    <div id="app">
        <h2>TODO List</h2>

        <form v-on:submit.prevent>
            <input type="text" v-model="newItem">
            <button v-on:click="addItem">Add</button>
        </form>
        <pre>{{$data}}</pre>

    </div>
</template>

<script>
export default {
  data () {
    return {
      newItem: ''
    }
  },
  methods: {
    addItem: function (event) {
      alert()
    }
  }
}
</script>

9行目の<pre>{{$data}}</pre> で newItem の中身を確認
addItem メソッドにalert()を書いて追加ボタン押下時のメソッド呼び出し確認

addItemメソッドにロジックの追加、data()に入力内容を複数格納する配列(todos)の追加

<template>
    <div id="app">
        <h2>TODO List</h2>

        <form v-on:submit.prevent>
            <input type="text" v-model="newItem">
            <button v-on:click="addItem">Add</button>
        </form>
        <pre>{{$data}}</pre>

    </div>
</template>

<script>
export default {
  data () {
    return {
      newItem: '',
      todos: []
    }
  },
  methods: {
    addItem: function (event) {
      if (this.newItem === '') {
        return
      }
      var todo = {
        item: this.newItem
      }
      this.todos.push(todo)
      this.newItem = ''
    }
  }
}
</script>

複数追加できるか確認

一覧表示のテーブル、リストのチェックと削除ボタンを追加
一覧を中央表示、文字を左寄せ、チェック後の取り消し線を<style>タグで調整
確認できたら<pre>{{$data}}</pre>は削除

<template>
    <div id="app">
        <h2>TODO List</h2>

        <form v-on:submit.prevent>
            <input type="text" v-model="newItem">
            <button v-on:click="addItem">Add</button>
        </form>

        <table>
            <tr v-for="(todo, key) in todos" :key="key">
                <td><input type="checkbox" v-model="todo.isDone"></td>
                <td><span v-bind:class="{done: todo.isDone}">{{todo.item}}</span></td>
                <td><button v-on:click="deleteItem(key)">Delete</button></td>
            </tr>
        </table>
    </div>
</template>

<script>
export default {
  data () {
    return {
      newItem: '',
      todos: []
    }
  },
  methods: {
    addItem: function (event) {
      if (this.newItem === '') {
        return
      }
      var todo = {
        item: this.newItem
        isDone: false
      }
      this.todos.push(todo)
      this.newItem = ''
    },
    deleteItem: function (key) {
      this.todos.splice(key, 1)
    }
  }
}
</script>

<style>
  #app table{
    margin-left: auto;
    margin-right: auto;
    text-align: left;
  }
  #app span.done{
    text-decoration:line-through;
  }
</style>

リストを3つ追加、取り消し線と削除の確認

以上で、完成です。

最後に

Vuejsは初歩的な内容だったので、これを機により実用的な部分も学習できたらと思います。
それからDocker、イメージ作成時やコンテナ起動時に多少エラーで悩まされたりしますが、ローカルに一切パッケージをダウンロードせず学習が進められる点は、改めて便利だなと実感しました。

今回は以上になります。
ご覧いただき、ありがとうございました。

BLOGトップへ戻る