Closed8

dockerコンテナからmysqlに接続できたはいいが、appコンテナからmysqlに接続できない

kobaryokobaryo

タイトルの通り、appコンテナからmysqlに接続できなかったので試したことの記録として書き残す。

ディレクトリ構成

├── Dockerfile
├── README.md
├── __tests__
├── components
├── db
├── docker-compose.yml
├── jest.config.js
├── lib
├── next-env.d.ts
├── node_modules
├── package-lock.json
├── package.json
├── pages
├── postcss.config.js
├── posts
├── prisma
├── public
├── styles
├── tailwind.config.js
├── test
└── tsconfig.json

docker-compose.yml

version: '3'
services:
  node:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - ./:/usr/src/app
    depends_on:
      - mysql
    command: sh -c "npm run dev"
    ports:
      - '3000:3000'
    tty: true
  mysql:
    image: mysql:latest
    command: --default-authentication-plugin=mysql_native_password
    env_file:
      - .env
    environment:
      MYSQL_ROOT_PASSWORD: root
    ports:
      - 3306:3306
    # データを永続化させる場合
    volumes:
      # 初期データを投入するSQLが格納されているdir
      - ./db/mysql_init:/docker-entrypoint-initdb.d
      # 永続化するときにマウントするdir
      - ./db/mysql_data:/var/lib/mysql
    tty: true
kobaryokobaryo

まず、コンテナを起動

$ docker-compose up -d
Starting nextjs-blog_mysql_1 ... done
Starting nextjs-blog_node_1  ... done

起動完了。次に、mysqlのコンテナに接続

$ docker-compose exec mysql sh
#

次にmysqlにログイン

# mysql -u root -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.19 MySQL Community Server - GPL

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

mysqlに接続することはできた。ちなみにshow databases;を実行すると、

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mydb               |
| mysql              |
| performance_schema |
| sample_db          |
| sys                |
+--------------------+
6 rows in set (0.02 sec)

こんな感じでdbが表示される。

kobaryokobaryo

問題はここから。
アプリケーションのコンテナを起動する。

$ docker-compose exec node sh
/usr/src/app # 

起動できた。
mysqlにログインしようとして、

$ mysql -u root -p
sh: mysql: not found

mysql自体インストールされてない???
別のターミナルを開いて、

$ mysql --version
mysql  Ver 8.0.23 for osx10.16 on x86_64 (Homebrew)

インストールされてる。(mysqlコンテナでは接続できてたし、当たり前か。。)

ちなみにmysqlのパッケージをinstall済み。
package.json

色々省略
"dependencies": {
    "mysql": "^2.18.1",
}

アプリのコンテナでmysql-client的なものをインストールする必要がある?
Dockerのコンテナ内でアプリからmysqlに接続したい。
Debianのdockerイメージでmysql-clientが無くてハマった人へ

npmでmysql-clientと検索してみたものの、mysql-clientは最終更新が10年前なので、next.js+docker+prisma+mysqlで使っている人はいなそう。。

nabeyangnabeyang

別のターミナルでmysqlが動くのはホスト(macOS)にmysqlがインストールされているからで、nodeサービスのとは無関係のように思います。docker-composeで起動しているコンテナ同士はportsでポートを開けなくても<サービス名>:<ポート>でアクセス出来ます。今回の場合はmysqlサービスにportsを書かなくても、nodeサービスからmysql:3306で繋がると思います。

あとはnodeのmysqlですが、これはcliはなさそうなのでinstall -g mysqlしてもmysqlで起動出来ないのでは?と思います。

kobaryokobaryo

コメントありがとうございます!!
なんとなく理解はできた気がするのですが、mysql:3306というのは、nodeサービスのportsに書けばいいのでしょうか?一度そのように書いてbuildを試してみたのですが、書き方が正しくないみたいな趣旨のエラーが出ました。一応エラーは下記です。

ERROR: The Compose file './docker-compose.yml' is invalid because:
services.node.ports contains an invalid type, it should be a number, or an object

それとも、nodeサービスを立ち上げて、コンテナ内でアクセスするようなコマンドを打てばいいのでしょうか?

よかったらご教授いただきたいです。よろしくお願いします!

nabeyangnabeyang

portsは書かないですね。こういうのは、自分で調べるのがおすすめです。色々な要素が関わっていて、わかりにくければ、自分の確認したいことに絞って簡単なケースで実験出来るようになる必要があります。

お互いに信頼関係があれば、「自分で調べて下さい」で終わりでも良いと思いますが、そうではないので、ここで今言ったことを実践してみます。
まずdocker-compose.yml

docker-compose.yml
version: '3'
services: 
  node:
    image: node:14.16.0-buster
    command: /bin/bash -c "while sleep 1000; do :; done"
    volumes: 
      - ./node:/src
    working_dir: /src
    depends_on: 
      - mysql
  mysql:
    image: mysql:5.7.33
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    environment:
      MYSQL_DATABASE: db_name
      MYSQL_ALLOW_EMPTY_PASSWORD: "yes"

このように変えます(使用するdockerイメージはlatestだと常に変わるので、できればバージョンを指定した方が良いと思います。このあたりは簡単な実験でしかないので好みです)。nodeプロジェクトのルートパスは'./node'とします。この状態で、まずdocker-compose upを実行して、起動したら

docker exec -i   mysql_test_mysql_1 sh -c 'exec mysql -D db_name' < db.sql

で、db_nameにテーブルを追加します。db.sqlの中身は次の通りです。

db.sql
DROP TABLE IF EXISTS `person`;
CREATE TABLE `person` (
  `name` varchar(20) NOT NULL,
  `email` varchar(20) NOT NULL,
  PRIMARY KEY (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

LOCK TABLES `person` WRITE;
INSERT INTO `person` VALUES ('Tom','tom@example.com');
UNLOCK TABLES;

とりあえずDBの中身を確認します。docker-compose exec mysql mysqlでmysqlにログインしたら

SELECT * FROM person;

を入力して、レコードが1行表示されることを確認します。もし、mysqlに繋がらない場合はvolumeの状態がおかしくなっている可能性があるのでdocker-compose down --volumesで初期化します。

次にdocker-compose exec nodeでnodeサービスに入ります。次のようにして、プロジェクトを作成します。

cd /src
touch client.js
npm init

全てデフォルトのまま連打してプロジェクトを作成したあと、npm install mysqlをインストールし、client.jsを編集します。

client.js
const mysql = require('mysql');
const connection = mysql.createConnection({
	host : 'mysql',
	user : 'root',
	database: 'db_name'
});

connection.connect();
connection.query('SELECT name, email from person;', function (err, rows, fields) {
	if (err) { console.log('err: ' + err); } 
	console.log('name: ' + rows[0].name);
	console.log('email: ' + rows[0].email);
});
connection.end();

この状態でnpx node client.jsでレコードが表示されればOK。これでコンテナ同士は<サービス名>:<ポート番号>で繋がることが確認できました。

kobaryokobaryo

記載していただいたのを参考にしつつ進めていったら、下記のように

# npx node client.js
name: Tom
email: tom@example.com

と表示されました。

本当にありがとうございます🙇‍♂️

kobaryokobaryo

npxコマンドで試してみる

/usr/src/app # npx mysql -u root -p
npm ERR! could not determine executable to run

npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2021-02-24T09_22_47_997Z-debug.log

ログを確認

0 verbose cli [                                                 
0 verbose cli   '/usr/local/bin/node',                        
0 verbose cli   '/usr/local/lib/node_modules/npm/bin/npm-cli.js',        
0 verbose cli   'exec',                                 
0 verbose cli   '--',                                                    
0 verbose cli   'mysql',                                                                       
0 verbose cli   '-u',                                                            
0 verbose cli   'root',                                                                        
0 verbose cli   '-p'                                                             
0 verbose cli ] 
1 info using npm@7.5.1                                          
2 info using node@v15.8.0                                        
3 timing config:load:defaults Completed in 4ms                           
4 timing config:load:file:/usr/local/lib/node_modules/npm/npmrc Completed in 2ms
5 timing config:load:builtin Completed in 2ms                            
6 timing config:load:cli Completed in 3ms                                                      
7 timing config:load:env Completed in 0ms                                        
8 timing config:load:file:/usr/src/app/.npmrc Completed in 3ms                                 
9 timing config:load:project Completed in 5ms                                    
10 timing config:load:file:/root/.npmrc Completed in 1ms                                          
11 timing config:load:user Completed in 1ms                                                    
12 timing config:load:file:/usr/local/etc/npmrc Completed in 0ms                                  
13 timing config:load:global Completed in 1ms                                                  
14 timing config:load:cafile Completed in 1ms                                                     
15 timing config:load:validate Completed in 0ms                                                   
16 timing config:load:setUserAgent Completed in 1ms
17 timing config:load:setEnvs Completed in 2ms                   
18 timing config:load Completed in 21ms                                         
19 verbose npm-session b60d3143ec60cc6a                                         
20 timing npm:load Completed in 47ms                                     
21 http fetch GET 304 https://registry.npmjs.org/mysql 281ms (from cache)                      
22 timing command:exec Completed in 311ms                                        
23 verbose stack Error: could not determine executable to run                                  
23 verbose stack     at getBinFromManifest (/usr/local/lib/node_modules/npm/lib/exec.js:264:23)
23 verbose stack     at exec (/usr/local/lib/node_modules/npm/lib/exec.js:178:15)                 
24 verbose cwd /usr/src/app                                                                    
25 verbose Linux 4.19.121-linuxkit                                                                
26 verbose argv "/usr/local/bin/node" "/usr/local/lib/node_modules/npm/bin/npm-cli.js" "exec" "--"
27 verbose node v15.8.0                                                                           
28 verbose npm  v7.5.1                                                                            
29 error could not determine executable to run 
30 verbose exit 1 

よくわからない。。

npm install -g mysqlしなおしてもエラーは変わらず。。

このスクラップは2021/02/25にクローズされました