🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Express

ExpressはNode.jsのWebアプリケーションフレームワークです。 マルチページを構築するための機能セットおよびハイブリッドのWebアプリケーションを提供します。

Docker

Dockerは、Docker社が開発したオープンソースのコンテナー管理ソフトウェアの1つです

Q&A

解決済

2回答

1664閲覧

DockerでExpressとMysqlを使いたい

yusuke.y

総合スコア17

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Express

ExpressはNode.jsのWebアプリケーションフレームワークです。 マルチページを構築するための機能セットおよびハイブリッドのWebアプリケーションを提供します。

Docker

Dockerは、Docker社が開発したオープンソースのコンテナー管理ソフトウェアの1つです

0グッド

0クリップ

投稿2021/02/28 17:10

Dockerを使ってExpressとMysqlをコンテナにして使いたいです。
docker-composeはできたのですが、Mysqlのデータベースからテーブルのデータを持ってこようとすると以下の処理になり、上手いことデータを持って来れません。
たまに持って来れることがあったり、Nodemonが壊れたりすることがあります。
問題解決の糸口が見つからない状態です。

非同期の問題かな?とかMysqlが立ち上がる前にデータベースに通信しようとしているのかな?とか考えましたが、如何せんDockerは初めてなものでよくわかっておりません…。

お力添えよろしくお願いいたします。

ターミナルでdocker-compose up --buildした結果

WARNING: Found orphan containers (my-app_myapp_1) for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up. Building dockerexpress Step 1/7 : FROM node:12.18-alpine ---> e13d60032d4d Step 2/7 : WORKDIR /usr/src/app ---> Using cache ---> 0fadda011d2f Step 3/7 : COPY ["package.json", "package-lock.json*", "npm-shrinkwrap.json*", "./"] ---> Using cache ---> f40abbaecc46 Step 4/7 : RUN npm install ---> Using cache ---> ac5841f3ebc7 Step 5/7 : COPY . . ---> Using cache ---> a75795cfafbc Step 6/7 : EXPOSE 3000 ---> Using cache ---> 5e579518cd77 Step 7/7 : CMD ["npm", "start"] ---> Using cache ---> c698a73f40f6 Successfully built c698a73f40f6 Successfully tagged dockerexpress:latest Starting my-app_my_mysql_1 ... done Starting my-app_dockerexpress_1 ... done Attaching to my-app_dockerexpress_1, my-app_my_mysql_1 my_mysql_1 | 2021-02-28 16:54:40+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.23-1debian10 started. my_mysql_1 | 2021-02-28 16:54:40+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql' my_mysql_1 | 2021-02-28 16:54:40+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.23-1debian10 started. dockerexpress_1 | dockerexpress_1 | > my-app@0.0.0 start /usr/src/app dockerexpress_1 | > nodemon ./bin/www dockerexpress_1 | dockerexpress_1 | [nodemon] 2.0.7 dockerexpress_1 | [nodemon] to restart at any time, enter `rs` dockerexpress_1 | [nodemon] watching path(s): *.* dockerexpress_1 | [nodemon] watching extensions: js,mjs,json dockerexpress_1 | [nodemon] starting `node ./bin/www` my_mysql_1 | 2021-02-28T16:54:40.622700Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.23) starting as process 1 my_mysql_1 | 2021-02-28T16:54:40.629675Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started. my_mysql_1 | 2021-02-28T16:54:40.778756Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended. dockerexpress_1 | error connectiong: Error: connect ECONNREFUSED 172.21.0.3:3306 dockerexpress_1 | at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1141:16) my_mysql_1 | 2021-02-28T16:54:40.853760Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /var/run/mysqld/mysqlx.sock my_mysql_1 | 2021-02-28T16:54:40.884467Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed. my_mysql_1 | 2021-02-28T16:54:40.884624Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel. my_mysql_1 | 2021-02-28T16:54:40.886643Z 0 [Warning] [MY-011810] [Server] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory. my_mysql_1 | 2021-02-28T16:54:40.899965Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.23' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server - GPL. dockerexpress_1 | --------------------- dockerexpress_1 | undefined dockerexpress_1 | --------------------- dockerexpress_1 | GET / 304 7.820 ms - - dockerexpress_1 | GET /stylesheets/style.css 304 0.971 ms - -

Dockerfile

FROM node:12.18-alpine WORKDIR /usr/src/app COPY ["package.json", "package-lock.json*", "npm-shrinkwrap.json*", "./"] RUN npm install COPY . . EXPOSE 3000 CMD ["npm", "start"]

index.js

JavaScript

1var express = require('express'); 2var router = express.Router(); 3const mysql = require('mysql2'); 4const connection = mysql.createConnection({ 5 host: 'my_mysql', 6 user: 'root', 7 password: 'root', 8 database: 'my_mysql_db' 9}); 10 11connection.connect((err) => { 12 if (err) { 13 console.log('error connectiong: ' + err.stack); 14 return; 15 } 16 console.log('success'); 17}); 18 19/* GET home page. */ 20router.get('/', function(req, res, next) { 21 connection.query('select * from users;', (err, users) => { 22 console.log('---------------------'); 23 console.log(users); 24 console.log('---------------------'); 25 res.render('index', { title: 'Express' }); 26 }); 27}); 28 29module.exports = router; 30

package.json

JavaScript

1{ 2 "name": "my-app", 3 "version": "0.0.0", 4 "private": true, 5 "scripts": { 6 "start": "nodemon ./bin/www" 7 }, 8 "dependencies": { 9 "cookie-parser": "~1.4.4", 10 "debug": "~2.6.9", 11 "ejs": "~2.6.1", 12 "express": "~4.16.1", 13 "http-errors": "~1.6.3", 14 "morgan": "~1.9.1", 15 "mysql2": "^2.2.5", 16 "sequelize": "^6.5.0" 17 }, 18 "devDependencies": { 19 "nodemon": "^2.0.7" 20 } 21} 22

docker-conpose.yml

JavaScript

1version: '3.4' 2 3services: 4 my_mysql: 5 image: mysql 6 environment: 7 MYSQL_ROOT_PASSWORD: root 8 MYSQL_DATABASE: my_mysql_db 9 ports: 10 - '3300:3300' 11 volumes: 12 - my_volume:/var/lib/mysql 13 14 dockerexpress: 15 image: dockerexpress 16 build: 17 context: dockerExpress 18 dockerfile: ./Dockerfile 19 ports: 20 - 3000:3000 21 22volumes: 23 my_volume: 24

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

docker-composeにはlinkやdepends_onという仕組みが用意されていますが、
これはコンテナ自体の起動順番を保証するだけで、
実際にはMySQLのコンテナが立ち上がり、実際にTCP3306番で通信を待ち受ける待機完了状態になるまでの僅かな空白時間があります。

まぁ、これを指定しておくだけで
そこそこ確実に動作するかと思いますが100%ではないのでちょっと怖いですね。
そのへんの回避策を挙げるとこんな感じになるかと思います。

  • Dockerizeを利用する
  • MySQLのコンテナだけを先に起動する(ちょっとダサいが仕方ないか?)
  • コネクション確保に失敗した時起動を待つような処理を入れる

1個目、Dockerizeに興味があれば下記の参考記事を見てください。
Dockerizeを使って他のコンテナの起動を待つ - Qiita

2個目、MySQLのコンテナだけを先に起動するというのはこういうことです。
Docker Composeでコンテナを走らせる時、バックグラウンド動作を意味する-dオプションを指定すると裏で起動しっぱなしになります。

bash

1# 先にmy_mysqlだけ起動 2$ docker-compose up -d my_mysql 3 4# 改めてdockerexpressを起動 5$ docker-compose up -d dockerexpress 6 7# ログを閲覧する (-f: Ctrl+Cで終了するまで開きっぱなしになる) 8$ docker-compose logs -f [コンテナ名] 9 10# 停止させる場合 11$ docker-compose stop [コンテナ名] 12$ docker-compose rm -f [コンテナ名]

3個目、初回コケた場合に関しても同様の手法で行けるかどうかはわかりませんが、
それらしい回避策をされている方の記事を見つけました。
初回接続失敗時のエラーは何処かで拾えるはずなので、
適当にsetTimeout(fn, 数百ミリ秒)みたいな指定で再度待つようなコードを書けば実現出来るはずです。

参考記事: node-mysqlで接続が切れる点を改善 - node-mysqlで接続が切れる点を改善

投稿2021/02/28 17:47

miyabi-sun

総合スコア21203

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yusuke.y

2021/02/28 17:55

動作しました!詳しくありがとうございます! depends_onでエラーの回避はできました!
miyabi-sun

2021/02/28 18:32

まぁ、ローカルで自分一人で作ってるならdepends_onの指定だけで十分ですね。 回避策はざっと目を通して「あー、そんなのもあったなぁ」と思い出せるようにしておくといざというときに役に立つかもしれませんね。
guest

0

depends_onを書くとmy_mysqlのコンテナが立ち上がったあとでdockerexpressが動きますよ

dockerexpress: image: dockerexpress build: context: dockerExpress dockerfile: ./Dockerfile ports: - 3000:3000 depends_on: - my_mysql

投稿2021/02/28 17:23

hentaiman

総合スコア6426

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yusuke.y

2021/02/28 17:56

動作しました!ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問