【Node.js】 Dockerを用いてNode.js Express MySQLの環境を構築するまでの道のり


本記事で作ったdockerfileを整理したものをまとめた記事は⬇️
https://qiita.com/sho_U/items/52e221877a271146ce84

完成イメージ構成
nodoDocker(rootディレクトリ)

Dockerfile:

アプリケーション用(node.js)コンテナを作るためのfile

app.env:

mysqlとの接続設定を記載したファイル

docker-compose.yml:

node.jsコンテナとmysqlコンテナを管理するyml

src:

アプリケーション本体

アプリケーション用のコンテナを作成する

まずはアプリケーション用の仮コンテナを作成し、アプリの雛形を作成する。そのアプリの雛形はホスト側にマウントしておき、その雛形を利用してdocker-composeを作成していく。

nodeDocker配下に
docker-compose.ymlを作成

docker-compose.yml
version: '3'
services:
  app:
    # dockerimageのファイルを指定
    build: .

    # コンテナ名
    container_name: node_docker_app

    # 環境変数を設定
    environment:
      - DEBUG=app:*

    tty: true

    # ホスト側のポート:コンテナのポート
    ports:
      - '3000:3000'

    # ソースコードを格納するフォルダをマウント
    #(ホスト側の./srcをコンテナの/appにマウント)
    volumes:
      - ./src:/app

    # 起動時のカレントフォルダを指定
    working_dir: /app

    # 起動後に実行するコマンドを指定(起動確認用)
    command: npm start


node をプルする。

dockrefile.
FROM node:12
ホスト.
#コンテナを一時的に起動(--rmで停止後削除する。コンテナ起動後、bashに入る)
docker-compose run --rm app /bin/bash
コンテナ.
# express-generatorでアプリケーションのひな形を生成
npx express-generator

# 依存パッケージをインストール
npm install

#コンテナを抜ける(この仮コンテナは削除される)
exit

※この時、コンテナは削除されるが

docker-compose.yml
    volumes:
      - ./src:/app

この記述により、.(docker-compose.ymlがあるディレクトリ。つまりnodoDockerディレクトリの配下のsrcディレクトリにマウントされているため、ホスト側のsrcディレクトリに作成した雛形は残っている。

コンテナを起動させる

host.
docker-compose up
docker-compose.yml
    command: npm start

の記載により、コンテナ起動後、自動的にExpress.jsのアプリケーションが起動する。
http://localhost:3000/
で確認。

コンテナを停止

host.
#再度コンテナを一時的に起動
docker-compose run --rm app /bin/bash

#ソースコードの変更を検知して必要な時にアプリケーションを再起動してくれる、「nodemon」というツールをインストール。
#変更のたびにコンテナの停止・再起動することしなくてよくする。
npm install -D nodemon

package.jsonを修正

src/package.json
"scripts": {
  "dev": "nodemon ./bin/www",
  "start": "node ./bin/www"
},

docker-compose.ymlファイルを編集

docker-compose.yml
(変更前)
command: npm start

(変更後)
command: npm run dev

MySQL用コンテナを追加

docker-compose.ymlにmysqlの設定を追加

docker-compose.yml
version: '3'
services:
  mysql:
    image: mysql:5.7
    env_file: ./mysql/mysql.env
    #環境変数設定。タイムゾーンを日本時間に設定。
    environment:
      - TZ=Asia/Tokyo
    ports:
      - '3306:3306'
    volumes:
      #mysqlのデフォルト設定ファイルを上書き。:roでコンテナ側からは読み取り専用設定。
      - ./mysql/conf:/etc/mysql/conf.d/:ro
      #mysqldataにマウントすることで、コンテナを削除してもデーターは残るように設定。
      - mysqldata:/var/lib/mysql
    networks:
      - backend

  app:
    image: node:12
    env_file: ./app.env
    #環境変数設定。タイムゾーンを日本時間に設定。
    environment:
      - TZ=Asia/Tokyo
      - DEBUG=app:*
    tty: true
    ports:
      - '3000:3000'
    volumes:
      - ./src:/app
    working_dir: /app
    command: npm run dev
    networks:
      - backend
    #mysqlに依存しているので、mysqlコンテナ作成後、appコンテナが作られる。
    depends_on:
      - mysql

networks:
  backend:

volumes:
  mysqldata:

my.confを作成(コンテナ側の/etc/mysql/conf.d/に配置される。)

mysql/conf/my.conf
[client]
default-character-set=utf8mb4

[mysql]
default-character-set=utf8mb4

[mysqldump]
default-character-set=utf8mb4

[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_bin
lower_case_table_names=1

# Enable access from the host machine.
bind-address=0.0.0.0

mysqlフォルダにmysql.envファイルを作成。(env_file: ./mysql/mysql.envの記載により、内容がコンテナ側のmysqlの環境変数に設定される)

mysql/mysql.env
MYSQL_ROOT_HOST=%
MYSQL_ROOT_PASSWORD=(ルートパスワード)
MYSQL_USER=(ユーザー名)
MYSQL_PASSWORD=(パスワード)
MYSQL_DATABASE=todo

app.envファイルを作成(アプリケーションコンテナの環境変数設定)

app.env
MYSQL_SERVER=mysql
MYSQL_USER=(ユーザー名)
MYSQL_PASSWORD=(パスワード)
MYSQL_DATABASE=todo
docker-compose.yml
version: '3'
services:
  mysql:
    image: mysql:5.7
    container_name: node_docker_db
    env_file: ./mysql/mysql.env
    environment:
      - TZ=Asia/Tokyo
    ports:
      - '3306:3306'
    volumes:
      - ./mysql/conf:/etc/mysql/conf.d/:ro
      - mysqldata:/var/lib/mysql
    networks:
      - backend

  app:
    image: node:12
    container_name: node_docker_app
    env_file: ./app.env
    environment:
      - TZ=Asia/Tokyo
      - DEBUG=app:*
    tty: true
    ports:
      - '3000:3000'
    volumes:
      - ./src:/app
    working_dir: /app
    command: npm run dev
    networks:
      - backend
    depends_on:
      - mysql

#使用するネットワークを作成。docker-composeの場合service以下の名前を使って名前解決されるため、appとmysqlが自動的に接続される。
networks:
  backend:

volumes:
  mysqldata:

mysqlにログイン

host.
docker-compose exec mysql mysql -uroot -p

できない、、、

ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)

いろいろ試した結果

host.
docker-compose down --volumes

volumeを削除したら、ログインできた。原因は不明。

ejsをテンプレートエンジンに使用するためインストールを記載したdockerfileをルート直下に配置。

#node.jsのイメージをプル。
FROM node:12
#作業ディレクトリをアプリケーションディレクトリにする。
WORKDIR /app
ejsをインストール。
RUN npm install ejs

アプリ件ーションコンテナはDockerfileでビルドするようにしたため(元々はnode:12イメージをプルしてた)修正

docker-compose.yml
(変更前)
image: node:12

(変更後)
build: .

ひとまず完了。