前回はdocker-composeを使ってdocker-compose.ymlファイルを記述しました。今回はこれにMySQLの記述をした後、実際に接続します。
前回はdocker-compose.ymlの記述内容をよく理解していないまま進みましたのでnodeとMySQLの接続にかなり苦労しました。同じ事で悩み、無駄な時間を使わなくてよいように誰かのためにこの記事を書きます。
この記事を読むことでdockerのコンテナ nodeとMySQLを接続することが来ます。
前提条件
- DockerでNode.jsアプリケーションを開発する (1) Express.jsをコンテナ内で動かすを完了していること。
- DockerでNode.jsアプリケーションを開発する (3) MySQL用コンテナを追加
docker-compose.yml
version: '3'
volumes:
mysqldata:
services:
app:
# Dockerfileのビルドディレクトリ
build: .
# 環境変数を設定
environment:
- TZ=Asia/Tokyo
- DEBUG=app:*
tty: true
# ホスト側のポート:コンテナのポート
ports:
- '3000:3000'
# ソースコードを格納するフォルダをマウント
#(ホスト側の./srcをコンテナの/appにマウント)
volumes:
- ./src:/app
# 起動時のカレントフォルダを指定
working_dir: /app
# 起動後に実行するコマンドを指定
command: npm run dev
#command: npm start
networks:
- backend
depends_on:
- db
links:
- db
#MySQLを追加
db:
image: mysql:5.7
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
networks:
backend:
上記コードの紫部分を追加しました。
意味を理解せよ
ググりながらコピペで作っていったので後にかなり苦労しました。重要なのは意味を理解することです、当たり前ですが。全てを理解しているわけではないのですが(というよりは不明の部分が多いです)、重要だと思った部分について解説します。
Volumes:
volumes:
mysqldata:
冒頭のvolumes: これは、docker内のどこか(例えばMacならば仮想Linux上に)に(docker voluemという)ボリュームをつくります。今回だとmysqldataというボリュームが作られることになります。何故作るのか?これはコンテナ上でデータベースを操作した後exitした際にデータが消えてしまわないようにするためです。このdocker volumeはホスト側に作られるためコンテナを出た後でも保存されたままになります。
volumes:
– mysqldata:/var/lib/mysql
サービスdb側に記載した
volumes:
– mysqldata:/var/lib/mysql
これは、ホスト側のmysqldata(冒頭のvolumes:で作ったヤツ)をコンテナ側の/var/lib/mysqlにマウントするということを意味します。/var/lib/mysqlはMySQLのデータの保存場所になります。したがって、コンテナ側で操作されるボリュームはホスト側のボリュームを操作していることになります。
./mysql/conf:/etc/mysql/conf.d/:roについては正直よく分かりません。
ホスト側の./mysql/confをコンテナ側のetc/mysql/conf.d/にマウントするという想像は出来ますが最後の:roは何か分かりません。
depends_on:
– db
これ、すごく大事でした。意味って言うか – dbの名前。depends_on:にネストされる- dbの名前はサービス名だと思われます。ここで云うサービス名はymlに記載している任意のサービス名。
<省略>
#MySQLを追加
db: #これがサービス名
image: mysql:5.7
<省略>
この場合だとdbになりますね。
depends_onの意味は、今ケースでは、サービスdbを起動した後に自身のサービス(ここではapp)を起動しなさい、ということです。実際にターミナルを見てみると私の環境ではappがdbに1秒遅れて起ち上がっていました。何故そうするかというと、appサービスはdbを見に行くのでその時にdbがないと困るわけですだそうです。
links:
– db
これは、appサービスからdbサービスにアクセス出来るようにするためです。したがってlinks:でネストするのはdbということになります。
わからんちん?
networks:
backend:
いまのところ、これが何のためにあるのか分かりません。なくてもよいかもしれません。
MySQLコンテナを作る準備
ここからは、MySQLコンテナを作っていく準備をします。DockerでNode.jsアプリケーションを開発する (3) MySQL用コンテナを追加 を参考にしてます。
mysqlフォルダにmysql.envファイルを作成
MySQLフォルダ直下にmysql.envファイルを作成します。ここに以下の記述をします。
MYSQL_ROOT_HOST=%
MYSQL_ROOT_PASSWORD=password
MYSQL_USER= user
MYSQL_PASSWORD=password
MYSQL_DATABASE=todo
envファイルで記述したものがdocker-composeをup した時に影響を与えるようです。ここでは、以下の様に記述しました。
MYSQL_ROOT_PASSWORD=password
MYSQL_USER= user
MYSQL_PASSWORD=password
MYSQL_DATABASE=todo ←はデータベースの名前になる
MYSQL_ROOT_HOST=% の%が何か分かりません。正規表現でしょうか?
rootフォルダにapp.envファイルを作成
rootフォルダ内にapp.envファイルを作成します。今回のケースでは下のように記述しました。実験していないので分かりませんが、ひょっとしたらyml内にlink:db:を記載したことや後に書くapp.jsないで接続先に関する記述をしていることからapp.env自体不要かもしれません。
MYSQL_SERVER=mysql
MYSQL_USER=root
MYSQL_PASSWORD=password
MYSQL_DATABASE=todo
app.jsファイル
srcフォルダ内のapp.jsファイルに以下の様に記述しました。
const express = require('express')
const app = express()
const port = 3000
const mysql = require('mysql');
// フォームから送信された値を受け取れるように
app.use(express.urlencoded({extended: false}));
const con = mysql.createConnection({
host: 'db',
user: 'root',
password: 'password',
database: 'todo'
});
con.connect((err) => {
if (err) {
console.log('error connecting you are wrong: ' + err.stack);
return;
}
console.log('success');
});
app.get('/', (req, res) => res.send('Hello World!'));
app.listen(port, () => console.log(`Example app listening on port ${port}!`));
ここ重要!はまったこと
この後、docker-compose up -dでコンテナを起ち上げていくのですが、どうやってもエラーになってしまいます。はまったのはここです。
const con = mysql.createConnection({
host: ‘db’,
user: ‘root’,
password: ‘password’,
database: ‘todo’
});
当初、ホストの部分をhost:’localhost’としていました。
con.connect((err) => {
if (err) {
console.log(‘error connecting you are wrong: ‘ + err.stack);
return;
}
console.log(‘success’);
});
このようにしているのでターミナル上にエラーがですので、そのままエラーをググってみました。すると、全く同じ事でつまずいていた人がいました。
こちらの記事、『docker上でexpress + mysqlの環境構築をしたいが、立ち上げたアプリ内でmysqlに接続できない。Error: connect ECONNREFUSED 127.0.0.1:3306』が大変参考になりました。
ここから推察するに、host: ‘db’の‘db’部分にはデータベースのサービス名を入れる必要があるようです。実際にymlのサービス名をmysqlに変更した時にhost:’mysql’とすると何事もなかったようにターミナルにsuccessと表示されました(console.log(‘success’);となっているので接続に成功するとsuccessが表示じされます)。
docker-compose uo -d でコンテナ起動
ここまで来たらあとはdocker-compose uo -d でコンテナ起動するだけです。
ターミナルに下のように表示されほっとしました!
参考記事
- DockerでNode.jsアプリケーションを開発する (1) Express.jsをコンテナ内で動かす
- 【Node.js express Docker】 Dockerを用いてNode.js Express MySQLの環境を構築する
- Express.js(node.js)からMySQLへの接続とCRUD操作
- Node.jsアプリケーションとMySQLを接続しよう!
- docker上でexpress + mysqlの環境構築をしたいが、立ち上げたアプリ内でmysqlに接続できない。Error: connect ECONNREFUSED 127.0.0.1:3306
コメントを残す