參考文章
💓Docker常用指令介紹
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 .
把node.js給run起來
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,將本地程式碼目錄掛載到容器內。
services:
my-node-app:
volumes:
- .:/usr/src/app # 將本地程式碼目錄掛載到容器內
mysql-container:
volumes:
- ./mysql-data:/var/lib/mysql
如果你沒有用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進去了!!
{
"dependencies": {
"express": "^4.17.1",
"mysql": "^2.18.1",
"mysql2": "^3.6.5"
},
"scripts": {
"start": "node server_wei.js"
}
}
🙆尚未建立網路,可以使用以下命令建立一個自定義的 Docker 網路:
docker network create mynetwork
🙆可以使用以下命令來列出 Docker 中目前存在的網絡
如果您的 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 中啟動名為 mysql-container 的 MySQL 容器,並將其連接到名為 mynetwork 的自定義網路中。該容器使用了 mysql:8.2-oraclelinux8 這個映像。已經正確設置了 root 用戶的密碼為 root。
fdf11af7e81d3d50d4846ebe8dde3a76e83d52ea8113704711bac098db28bffd是所建立的 MySQL 容器的 ID。這個 ID 是容器的唯一標識符。
該容器已以後台(detached)模式運行,MySQL 容器的名稱為 mysql-container,並已加入了名為 mynetwork 的自定義網路。這表示其他容器也可以透過該網路與該 MySQL 容器進行通訊。
🙆列出所有的 Docker 容器,包括運作中的和已經停止的。
🙆用於在運行中的 MySQL 容器中啟動一個互動式的 Bash 終端。它允許您在容器內部執行命令或進行操作
docker exec -it mysql-container bash
bash-4.4#
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
Query OK, 1 row affected (0.01 sec)
🙆使用DB
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!');
Query OK, 1 row affected (0.01 sec)
🙆Select裡面的資料
+------+-----------+
| 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版本~
D:\mysql>npm show mysql version
2.18.1
D:\mysql>npm install mysql@latest
up to date, audited 86 packages in 4s
11 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
D:\mysql>
D:\mysql>npm show mysql version
2.18.1
因此還是必須要使用mysql2才能成功使用。
👿遇到問題!!
docker failed to solve: Canceled: context canceled
PS D:\mysql_DockerCopmpose> docker-compose up
[+] Building 3.2s (5/9) docker:default
=> [my-node-app internal] load .dockerignore 0.0s
=> => transferring context: 81B 0.0s
=> [my-node-app internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 443B 0.0s
=> [my-node-app internal] load metadata for docker.io/library/node:14 3.0s
=> [my-node-app 1/5] FROM docker.io/library/node:14@sha256:a158d3b9b4e3fa813fa6c8c590b8f0a860e015ad4e59bbce5744d2f6fd8461aa 0.0s
=> CANCELED [my-node-app internal] load build context 0.2s
=> => transferring context: 6.27MB 0.2s
failed to solve: Canceled: context canceled
我把mysql 的volume裡面內容刪除就可以跑了,
總之出現這個訊息可以試著清空/mysql-data~
(mysql-data~刪除後,需要再次創DB、table等內容)
mysql-container:
volumes:
- ./mysql-data:/var/lib/mysql
🙆.gitignore
.gitignore 是一個用來指示 Git 忽略哪些檔案或目錄的配置文件。它通常用於排除不應該被版本控制的檔案或目錄,例如暫存檔案、編譯生成的檔案、臨時檔案、敏感資訊等。
👉暫存檔案:通常由編輯器或 IDE 產生的暫存檔案,如 .DS_Store(Mac 系統的暫存檔)、Thumbs.db(Windows 系統的暫存檔)等。
👉編譯生成的檔案:例如編譯後的程式碼、執行檔、程式庫檔案、log 檔案等,這些通常是由編譯器、建置工具或執行程式生成的。
👉臨時檔案:臨時性的檔案或目錄,例如暫時性的下載檔案、快取檔案等。
👉資料夾:排除整個資料夾的路徑,特別是包含大量檔案或敏感資訊的資料夾。
👉敏感資訊:如密碼、私鑰、API 金鑰等應該保密的資訊檔案。
👉自動生成的檔案:由程式自動生成的檔案,如日誌檔案、測試報告等。
👉特定程式語言或框架生成的檔案:某些程式語言或框架會生成特定的檔案或資料夾,可能需要被忽略。
# 忽略暫存檔案
.DS_Store
Thumbs.db
# 忽略編譯生成的檔案
/dist
/build
*.log
# 忽略臨時檔案
.temp/
.tmp/