參考文章
Q:我的node.js在本地安裝跑,可是我的mysql想用docker來裝,有辦法讓這兩個東西連接在一起嗎?
A:可以,但你要讓node.js和mysql連結在同一個網路之中(--network),要在同個網路下面才可以進行通訊。
方法1: mysql和node.js個別run起來
把mysql給run起來
docker run --network=mynetwork --name=mysql-container -e MYSQL_ROOT_PASSWORD=root -d mysql:8.2-oraclelinux8
把node.js的Dockerfile給build起來
docker build -t my-express-app .
docker run --name my-node-app --rm -v D:/mysql:/app --network=mynetwork -p 3000:3000 -d node:14 node /app/server.js
方法1缺點>>
雖然您可以個別使用 docker run 命令來運行單個容器,但在開發和生產環境中,通常會涉及到多個容器相互協作的情況,例如應用程式需要與資料庫服務、消息佇列服務等進行通訊。
方法2: Docker Compose來run起來
這時使用 Docker Compose 可以帶來以下幾個優點:
1. 方便管理多個容器:透過一個配置檔案 (docker-compose.yml),您可以定義並管理多個容器,包括它們的屬性、依賴關係、網路設定等,這樣可以更有效地管理和運行整個應用程式的相關容器。
2. 簡化部署:使用 Docker Compose 可以使應用程式的部署變得更容易,只需在部署環境中運行一個指令 (docker-compose up),即可自動啟動並連接多個容器,而不需要手動運行多個 docker run 命令。
3. 提供環境一致性:使用 Docker Compose 可以確保開發、測試和生產環境之間的一致性,因為您可以在不同環境中使用相同的配置檔案來啟動和管理容器。
雖然可以個別運行容器,但使用 Docker Compose 通常是管理多個相互關聯的容器更簡便和方便的方式。這對於開發、測試和部署複雜的應用程式尤其有益。
👿困難點::
Q: 使用Dockerfile build成一個image後,是不是我的檔案就不能更改了QQ?
A: 需要使用volumes,將本地程式碼目錄掛載到容器內。
如果你沒有用volumes來掛載,當stop container後,你之後在start container時,就會發現你在裡面做的更動都不見囉~~
我之前mysql沒有掛載,我進去mysql container裡面創建了DB和Table,但只要我重啟了container後,我新增的東西就會不見。
如果有用volumes,你做的更動會存在本地的./mysql-data資料夾裡面,也就是說就算container重啟,你有進行掛載的資料都還會在唷!!
Q: 為什麼我的server.js跑不出來??? 一直卡住?
CMD ["npm", "start"]到底在幹嘛?
A: npm start 是 Node.js 中的一個預設 script,它用於啟動應用程式。當您在命令列執行 npm start 時,Node.js 會查找 package.json 檔案中的 "scripts" 部分,並找到名為 "start" 的指令。
"scripts": {
"start": "node server.js"
}
即使在 package.json 文件中沒有明確定義 "start" script,npm start 也能運行成功。這是因為 npm 有一個預設行為:如果沒有定義 "start" script,它會嘗試運行一個叫做 server.js 的文件。
當您運行 npm start 時,npm 會檢查當前目錄下是否有 server.js 文件,如果有的話,它會試圖使用 node server.js 來啟動應用程式。
所以如果你的server取很特別的名字,像是server_wei.js,你就需要加上scripts >> start進去了!!
🙆尚未建立網路,可以使用以下命令建立一個自定義的 Docker 網路:
docker network create mynetwork
docker network ls
如果您的 Docker Compose 專案名為 my_project,
my_project_default 是 Docker Compose 預設為專案建立的網路名稱。
本專案的project名稱為mysql_DockerCopmpose,因此網路名稱為mysql_dockercopmpose_default 。
574b5af1e1a8 mysql_dockercopmpose_default bridge local
🙆啟動 MySQL 容器時,使用 --network 參數將容器連接到您剛剛建立的網路中。
docker run --network=mynetwork --name=mysql-container -e MYSQL_ROOT_PASSWORD=root -d mysql:8.2-oraclelinux8
docker ps -a
🙆用於在運行中的 MySQL 容器中啟動一個互動式的 Bash 終端。它允許您在容器內部執行命令或進行操作
docker exec -it mysql-container bash
bash-4.4#
mysql -u root -p
Enter password: 輸入root
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8 ...
🙆或者可以直接把mysql -u root -p加在最後面,可以少打一行。
docker exec -it mysql-container mysql -u root -p
🙆創建DB
create database qq;
Query OK, 1 row affected (0.01 sec)
🙆使用DB
use qq;
Database changed
🙆創建Table
CREATE TABLE q_table (
id INT, -- 整数类型
text TEXT -- 文本类型
);
CREATE TABLE messages (
id INT AUTO_INCREMENT PRIMARY KEY,
text TEXT
);
Query OK, 0 rows affected (0.02 sec)
🙆插入內容
INSERT INTO q_table (id, text) VALUES (1, 'Some text');
INSERT INTO messages (text) VALUES ('Hello, this is a new message!');
🙆Select裡面的資料
SELECT * FROM q_table;
+------+-----------+
| id | text |
+------+-----------+
| 1 | Some text |
+------+-----------+
1 row in set (0.00 sec)
SELECT * FROM messages;
🙆Dockerfile
# 使用官方 Node.js 映像作為基礎映像
FROM node:14
# 設定工作目錄
WORKDIR /usr/src/app
# 複製 package.json 和 package-lock.json(如果有的話)
COPY package*.json ./
# 安裝相依套件
RUN npm install
# 複製應用程式代碼到容器中
COPY . .
# 開放應用程式使用的端口
EXPOSE 3000
# 定義啟動應用程式的指令
CMD ["npm", "start"]
👉FROM node:14:
FROM 指令指定了這個 Dockerfile 使用的基礎映像。在這裡,它使用官方的 Node.js 映像作為基礎,版本是 14。這表示您的應用程式將建立在 Node.js 14 的運行環境之上。
👉WORKDIR /usr/src/app:
WORKDIR 指令用於設定容器中的工作目錄。在這裡,它設置工作目錄為 /usr/src/app,這將是您應用程式代碼的主要位置。
👉COPY package*.json ./:
COPY 指令將主機中的 package.json 和 package-lock.json 檔案複製到容器中的工作目錄。這麼做是為了讓 Docker 在建構映像時安裝您應用程式所需的相依套件。
👉RUN npm install:
RUN 指令用於在容器內執行命令。在這裡,它執行 npm install 命令,安裝了在剛才複製進來的 package.json 中定義的相依套件。這個步驟將會在建立映像時執行。
👉COPY . .:
COPY 指令將目前目錄下的所有檔案複製到容器的工作目錄中。這個步驟將會把整個應用程式的代碼複製進容器中。
👉EXPOSE 3000:
EXPOSE 指令定義了容器執行的應用程式使用的端口號。在這裡,它設置容器內部使用的端口號為 3000,但這僅僅是一種宣告,並不會實際打開該端口。
👉CMD ["npm", "start"]:
CMD 指令定義了容器啟動時要運行的預設命令。在這裡,它設置容器啟動後要執行的指令是 npm start,這將啟動您的 Node.js 應用程式。
🙆是一個用於建構 Docker 映像的命令。
docker build -t my-express-app .
docker build: 這是 Docker 命令的一部分,用於建置 Docker 映像。
-t my-express-app: -t 參數用於為您建立的鏡像指定名稱(my-express-app)。
🙆運行名為 my-express-app 的鏡像作為一個容器,並且指定了一些參數:
docker run -d --name my-express-app --network mynetwork -p 3000:3000 my-express-app
-d: 表示以背景模式運行容器。
--name my-express-app: 為容器指定名稱為 my-express-app。
--network mynetwork: 將容器連接到指定的網路,網路名稱為 mynetwork。
-p 3000:3000: 將容器的 3000 端口映射到主機的 3000 端口,這樣您可以通過瀏覽器訪問主機的 3000 端口來訪問容器中運行的應用程式。
my-express-app: 這是要運行的 Docker 映像的名稱。
🙆運行 Docker 容器並執行 Node:14 的映像
docker run --name my-node-app -it --rm --network=mynetwork -v D:/mysql:/app node:14
docker run: 啟動一個新的容器
--name my-node-app: 為容器指定名稱為 my-node-app
-it: 分別代表使用互動式(interactive)的模式運行容器,通常用於在容器內部進行命令行操作
--rm: 當容器停止運行時自動刪除容器
--network=mynetwork: 將容器連接到名為 mynetwork 的網路
-v D:/mysql:/app: 將本機的 D:/mysql 掛載到容器的 /app 目錄,這樣容器內的 /app 目錄將與本機的 D:/mysql 目錄進行資料共享
node:14: 使用的 Docker 映像為 Node.js 的版本 14
🙆運行 Docker 容器並執行 Node:14 的映像+執行node.js伺服器
在這個指令中,-p 3000:3000 表示將容器的 3000 連接埠對應到宿主機器的 3000 連接埠。這樣,您可以在本機瀏覽器中透過 http://127.0.0.1:3000/ 或 http://localhost:3000/ 存取您的 Node.js 伺服器。
docker run --name my-node-app --rm -v D:/mysql:/app --network=mynetwork -p 3000:3000 -d node:14 node /app/server.js
docker run: 啟動一個新的容器
--name my-node-app: 為容器指定名稱為 my-node-app
--rm: 當容器停止運行時自動刪除容器
-v D:/mysql:/app: 將本機的 D:/mysql 掛載到容器的 /app 目錄,這樣容器內的 /app 目錄將與本機的 D:/mysql 目錄進行資料共享
--network=mynetwork: 將容器連接到名為 mynetwork 的網路
-p 3000:3000: 將容器的 3000 端口映射到主機的 3000 端口,使得可以通過訪問主機的 3000 端口來訪問容器中運行的應用程式
-d: 表示以背景模式運行容器
node:14: 使用的 Docker 映像為 Node.js 的版本 14
node /app/server.js: 在容器內運行指令 node /app/server.js,這會執行容器中的 /app/server.js 檔案,開啟一個 Node.js 伺服器。
docker-compose up
docker-compose down
/mysqld.sock' port: 3306 MySQL Community Server - GPL.
my-node-app | Server is running on port 3000
my-node-app | Error connecting to database: Error: ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client
my-node-app | at Handshake.Sequence._packetToError (/usr/src/app/node_modules/mysql/lib/protocol/sequences/Sequence.js:47:14)
my-node-app | at Handshake.ErrorPacket (/usr/src/app/node_modules/mysql/lib/protocol/sequences/Handshake.js:123:18)
my-node-app | at Protocol._parsePacket (/usr/src/app/node_modules/mysql/lib/protocol/Protocol.js:291:23)
my-node-app | at Parser._parsePacket (/usr/src/app/node_modules/mysql/lib/protocol/Parser.js:433:10)
my-node-app | at Parser.write (/usr/src/app/node_modules/mysql/lib/protocol/Parser.js:43:10)
my-node-app | at Protocol.write (/usr/src/app/node_modules/mysql/lib/protocol/Protocol.js:38:16)
my-node-app | at Socket.<anonymous> (/usr/src/app/node_modules/mysql/lib/Connection.js:88:28)
my-node-app | at Socket.<anonymous> (/usr/src/app/node_modules/mysql/lib/Connection.js:526:10)
my-node-app | at Socket.emit (events.js:400:28)
my-node-app | at addChunk (internal/streams/readable.js:293:12)
my-node-app | --------------------
my-node-app | at Protocol._enqueue (/usr/src/app/node_modules/mysql/lib/protocol/Protocol.js:144:48)
my-node-app | at Protocol.handshake (/usr/src/app/node_modules/mysql/lib/protocol/Protocol.js:51:23)
my-node-app | at Connection.connect (/usr/src/app/node_modules/mysql/lib/Connection.js:116:18)
my-node-app | at Object.<anonymous> (/usr/src/app/server.js:17:12)
my-node-app | at Module._compile (internal/modules/cjs/loader.js:1114:14)
my-node-app | at Object.Module._extensions..js (internal/modules/cjs/loader.js:1143:10)
my-node-app | at Module.load (internal/modules/cjs/loader.js:979:32)
my-node-app | at Function.Module._load (internal/modules/cjs/loader.js:819:12)
my-node-app | at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:75:12)
my-node-app | at internal/main/run_main_module.js:17:47 {
my-node-app | code: 'ER_NOT_SUPPORTED_AUTH_MODE',
my-node-app | errno: 1251,
my-node-app | sqlMessage: 'Client does not support authentication protocol requested by server; consider upgrading MySQL client',
my-node-app | sqlState: '08004',
my-node-app | fatal: true
my-node-app | }
這個錯誤表示 MySQL 用戶端不支援 MySQL 伺服器所要求的身份驗證協定。這通常是由於 MySQL 伺服器使用了新的身份驗證插件,而舊版的 MySQL 用戶端不支援這種插件造成的。
解決方法1: 使用mysql2,不要使用mysql
const mysql = require('mysql2');
改成使用mysql2,就成功了!!
解決方法2:使用 npm 命令更新 MySQL 模块
更新前和更新後版本都一樣,即使更新到最新的mysql,也只有2.18.1版本~
沒有留言:
張貼留言
喜歡我的文章嗎? 喜歡的話可以留言回應我喔! ^^