- Docker 教程
- Docker - 首頁
- Docker - 概述
- Docker - 在 Linux 上安裝
- Docker - 安裝
- Docker - Hub
- Docker - 映象
- Docker - 容器
- Docker - 倉庫
- Docker - Compose
- Docker - 使用容器
- Docker - 架構
- Docker - 層
- Docker - 容器和主機
- Docker - 配置
- Docker - 容器和 Shell
- Docker - Dockerfile
- Docker - 構建檔案
- Docker - 公共倉庫
- Docker - 管理埠
- Docker - Web 伺服器
- Docker - 命令
- Docker - 容器連結
- Docker - 資料儲存
- Docker - 卷
- Docker - 網路
- Docker - 安全
- Docker - 工具箱
- Docker - 雲
- Docker - 構建雲
- Docker - 日誌記錄
- Docker - 持續整合
- Docker - Kubernetes 架構
- Docker - Kubernetes 的工作原理
- Docker - 生成式 AI
- Docker - 託管
- Docker - 最佳實踐
- Docker 設定服務
- Docker - 設定 Node.js
- Docker - 設定 MongoDB
- Docker - 設定 NGINX
- Docker - 設定 ASP.Net
- Docker - 設定 MySQL
- Docker - 設定 Go
- Docker - 設定 Rust
- Docker - 設定 Apache
- Docker - 設定 MariaDB
- Docker - 設定 Jupyter
- Docker - 設定 Portainer
- Docker - 設定 Rstudio
- Docker - 設定 Plex
- Docker 設定 - Flame
- Docker 設定 - PostgreSql
- Docker 設定 - Mosquitto
- Docker 設定 - Grafana
- Docker 設定 - Nextcloud
- Docker 設定 - Pawns
- Docker 設定 - Ubuntu
- Docker 設定 - RabbitMQ
- Docker - 設定 Python
- Docker - 設定 Java
- Docker - 設定 Redis
- Docker - 設定 Alpine
- Docker - 設定 BusyBox
- Docker 設定 - Traefik
- Docker 設定 - WordPress
- Docker 有用資源
- Docker - 快速指南
- Docker - 有用資源
- Docker - 討論
Docker - 設定 Node.js
將 Node.js 應用程式 Docker 化是一種將應用程式及其依賴項打包到一個包含且可重現的單元中的可靠方法。這確保了跨不同環境的部署的一致性,並簡化了開發到生產的工作流程。
在本章中,我們將帶您從設定 NodeJs 專案到在 Docker 容器內執行應用程式的旅程。我們將涵蓋重要的主題,例如組織專案、建立 Dockerfile 和管理容器。在本章結束時,您將完全理解如何將 Node.js 應用程式 Docker 化,但更重要的是,能夠將這些概念應用到您的專案中。
先決條件
在將我們的 Node.js 應用程式 Docker 化之前,您應該瞭解以下一些先決條件:
- 已安裝 Node.js 和 npm(或 yarn) - 這些對於開發 Node.js 應用程式至關重要。
- 對 Node.js 和 Express.js 的基本瞭解 - 熟悉這些框架將有所幫助。
- 程式碼編輯器或 IDE - 用於編寫和管理程式碼。
- 版本控制系統(可選) - 用於管理專案的程式碼(例如,Git)。
建立倉庫
要組織您的專案,請建立一個新的 Git 倉庫:
選擇一個倉庫名稱 - 為您的專案選擇一個描述性的名稱,例如node-blog。
初始化 Git 倉庫
git init
建立遠端倉庫(可選) - 如果您想協作或備份您的程式碼,請在 GitHub、GitLab 或 Bitbucket 等平臺上建立一個遠端倉庫。
目錄結構
我們將建立一個簡單的部落格應用程式。以以下方式為您的專案建立目錄結構:
node-blog/ ├── package.json ├── index.js ├── routes/ │ ├── posts.js │ └── users.js ├── models/ │ ├── posts.js │ └── users.js ├── controllers/ │ ├── postsController.js │ └── usersController.js ├── public/ │ └── index.html ├── Dockerfile └── .gitignore
- package.json - 儲存專案依賴項和元資料。
- index.js - 主要的應用程式入口點。
- routes - 包含不同 API 端點的路由定義。
- models - 定義應用程式的資料模型。
- controllers - 處理業務邏輯並與模型互動。
- public - 儲存靜態檔案,例如 html、css 等。
- Dockerfile - 定義 Docker 映象構建指令。
- .gitignore - 指定要從 Git 版本控制中排除的檔案和目錄。
此結構將為您的部落格應用程式提供堅實的基礎。您可以根據專案的具體需求對其進行調整。
讓我們繼續下一節:新增路由。
新增路由
讓我們建立一個基本的路由來處理我們部落格主頁的 GET 請求。
步驟 1. 安裝 Express.js
$ npm install express
步驟 2. 安裝 Bootstrap
$ npm install bootstrap
步驟 3. 建立 index.js 檔案
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello from your blog!');
});
app.listen(3000, () => {
console.log('Server listening on port 3000');
});
步驟 4. 執行應用程式
node index.js
解釋
- 首先,我們匯入 Express 庫並建立一個 Express 應用程式例項。
- 然後,我們使用app.get()方法定義了一個路由來處理對根路徑('/')的 GET 請求。
- 路由處理程式傳送一個簡單的“Hello from your blog!”訊息作為響應。
- 最後,我們在埠 3000 上啟動伺服器。
完成程式碼
在深入研究程式碼之前,讓我們建立專案結構:
project-directory/
models/
posts.js
users.js
controllers/
postsController.js
usersController.js
routes/
posts.js
users.js
public/
index.html
index.js
models/posts.js
let posts = [];
let nextId = 1;
const createPost = (title, content, authorId) => {
const post = { id: nextId++, title, content, authorId };
posts.push(post);
return post;
};
const getPosts = () => {
return posts;
};
const getPostById = (id) => {
return posts.find(post => post.id === parseInt(id));
};
const updatePost = (id, title, content) => {
const postIndex = posts.findIndex(post => post.id === parseInt(id));
if (postIndex !== -1) {
posts[postIndex] = { ...posts[postIndex], title, content };
return posts[postIndex];
}
return null;
};
const deletePost = (id) => {
const postIndex = posts.findIndex(post => post.id === parseInt(id));
if (postIndex !== -1) {
return posts.splice(postIndex, 1)[0];
}
return null;
};
module.exports = {
createPost,
getPosts,
getPostById,
updatePost,
deletePost,
};
models/users.js
let users = [];
let nextUserId = 1;
const createUser = (username, email, password) => {
const user = { id: nextUserId++, username, email, password };
users.push(user);
return user;
};
const getUserByUsername = (username) => {
return users.find(user => user.username === username);
};
module.exports = {
createUser,
getUserByUsername,
};
controllers/postsController.js
const postsModel = require('../models/posts');
const getPosts = (req, res) => {
const posts = postsModel.getPosts();
res.json(posts);
};
const createPost = (req, res) => {
const { title, content, authorId } = req.body;
const post = postsModel.createPost(title, content, authorId);
res.status(201).json(post);
};
const getPostById = (req, res) => {
const { id } = req.params;
const post = postsModel.getPostById(id);
if (post) {
res.json(post);
} else {
res.status(404).json({ message: 'Post not found' });
}
};
const updatePost = (req, res) => {
const { id } = req.params;
const { title, content } = req.body;
const updatedPost = postsModel.updatePost(id, title, content);
if (updatedPost) {
res.json(updatedPost);
} else {
res.status(404).json({ message: 'Post not found' });
}
};
const deletePost = (req, res) => {
const { id } = req.params;
const deletedPost = postsModel.deletePost(id);
if (deletedPost) {
res.json({ message: 'Post deleted' });
} else {
res.status(404).json({ message: 'Post not found' });
}
};
module.exports = {
getPosts,
createPost,
getPostById,
updatePost,
deletePost,
};
controllers/usersController.js
const usersModel = require('../models/users');
const createUser = (req, res) => {
const { username, email, password } = req.body;
const user = usersModel.createUser(username, email, password);
res.status(201).json(user);
};
const getUserByUsername = (req, res) => {
const { username } = req.params;
const user = usersModel.getUserByUsername(username);
if (user) {
res.json(user);
} else {
res.status(404).json({ message: 'User not found' });
}
};
module.exports = {
createUser,
getUserByUsername,
};
routes/posts.js
const express = require('express');
const router = express.Router();
const postsController = require('../controllers/postsController');
router.get('/', postsController.getPosts);
router.post('/', postsController.createPost);
router.get('/:id', postsController.getPostById);
router.put('/:id', postsController.updatePost);
router.delete('/:id', postsController.deletePost);
module.exports = router;
routes/users.js
const express = require('express');
const router = express.Router();
const usersController = require('../controllers/usersController');
router.post('/', usersController.createUser);
router.get('/:username', usersController.getUserByUsername);
module.exports = router;
index.js
const express = require('express');
const path = require('path');
const posts = require('./routes/posts');
const users = require('./routes/users');
const app = express();
app.use(express.json());
// Import Bootstrap CSS
app.use('/css', express.static(path.join(__dirname, 'node_modules/bootstrap/dist/css')));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/posts', posts);
app.use('/users', users);
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'index.html'));
});
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Blog</title>
<link rel="stylesheet" href="/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6">
<form action="/users" method="POST">
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" class="form-control" id="username" name="username" placeholder="Username">
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control" id="email" name="email" placeholder="Email">
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" name="password" placeholder="Password">
</div>
<button type="submit" class="btn btn-primary">Create User</button>
</form>
</div>
<div class="col-md-6">
<form action="/posts" method="POST">
<div class="mb-3">
<label for="title" class="form-label">Title</label>
<input type="text" class="form-control" id="title" name="title" placeholder="Title">
</div>
<div class="mb-3">
<label for="content" class="form-label">Content</label>
<textarea class="form-control" id="content" name="content" rows="3"></textarea>
</div>
<button type="submit" class="btn btn-primary">Create Post</button>
</form>
</div>
</div>
</div>
<script src="/js/bootstrap.bundle.min.js"></script>
</body>
</html>
程式碼解釋
模型
- posts.js - 定義帖子的記憶體儲存,包括 CRUD 操作(建立、讀取、更新、刪除)。
- users.js - 定義使用者的記憶體儲存,包括使用者建立和按使用者名稱檢索。
控制器
- postsController.js - 處理與帖子相關的 HTTP 請求,與posts模型互動。
- usersController.js - 處理與使用者相關的 HTTP 請求,與users模型互動。
路由
- posts.js - 定義帖子的 API 端點(GET、POST、PUT、DELETE)。
- users.js - 定義使用者的 API 端點(POST、GET)。
index.js
- 設定 Express 伺服器。
- 定義 API 的基本 URL。
- 在指定埠上啟動伺服器。
Index.html
在這裡,我們使用了 Bootstrap 和基本的 HTML 建立了一個表單,允許您建立和檢視使用者和帖子。
在本地啟動應用程式
- 轉到專案目錄 - 開啟您的終端或命令提示符並轉到專案的根目錄。
- 安裝依賴項 - 執行npm install以安裝package.json檔案中列出的所需依賴項。
- 啟動開發伺服器 - 執行node index.js以啟動應用程式。
解釋
- npm install命令將獲取並安裝應用程式正常執行所需的所有必要包。
- 執行node index.js將執行 JavaScript 檔案index.js,它是應用程式的入口點。這將啟動 Node.js 伺服器。
測試您的應用程式
伺服器執行後,開啟 Web 瀏覽器並導航到https://:3000。您應該會看到一個指示應用程式正在執行的響應。
注意
- 預設埠是 3000,但您可以透過修改index.js檔案中的埠號來更改它。
- 您可以使用nodemon等工具在程式碼更改時自動重啟。
您現在可以在這裡建立使用者和帖子。
將 NodeJs 應用程式 Docker 化
讓我們在專案的根目錄中建立一個名為Dockerfile的檔案,內容如下
# Use a Node.js image as the base FROM node:18-alpine # Set the working directory WORKDIR /app # Copy package.json and package-lock.json to install dependencies COPY package*.json ./ # Install dependencies RUN npm install # Copy the rest of the application code COPY . . # Expose the port your app will listen on EXPOSE 3000 # Start the app CMD ["node", "index.js"]
Dockerfile 的解釋
- FROM node:18-alpine - 我們將使用 Node.js 18 映象作為 Docker 映象的基礎映象。
- WORKDIR /app - 它將容器內的工作目錄設定為 /app。
- COPY package*.json ./ - 它將 package.json 和 package-lock.json 複製到工作目錄。
- RUN npm install - 安裝專案依賴項。
- COPY . . - 將整個專案複製到容器。
- EXPOSE 3000 - 為應用程式公開埠 3000。
- CMD ["node", "index.js"] - 指定容器啟動時要執行的命令。
構建 Docker 映象
要構建 Docker 映象,您可以在終端中執行以下命令:
$ docker build -t my-node-app .
此命令構建 Docker 映象並將其標記為my-node-app。
執行 Docker 容器
要執行 Docker 容器,請使用以下命令:
$ docker run -p 3000:3000 my-node-app
此命令從my-node-app映象建立一個容器,然後將容器的埠 3000 對映到主機的埠 3000,並啟動容器。
現在,您可以透過https://:3000訪問您的應用程式。
結論
在本章中,我們介紹了開發 Node.js 部落格應用程式並使用 Docker將其容器化的所有步驟。您現在知道如何組織您的專案、處理使用者互動、有效地打包應用程式以進行部署以及建立其他 Docker 可以從中構建的基礎映象。
儘管本教程非常基礎,但如果您計劃使此應用程式投入生產,則應新增功能、安全措施、資料庫整合等。Docker 化將使您能夠簡化所有開發、測試和部署流程,以確保您的應用程式在所有環境中的行為相同。
在 Docker 中設定 Node.js 的常見問題解答
1. 最佳化 Node.js 應用程式的 Docker 映象的最佳實踐是什麼?
Docker 映象最佳化的最佳實踐是使用最小基礎映象大小和精簡的 Node.js 執行時,僅安裝應用程式所需的依賴項,並利用構建快取。您可以使用生產就緒的 Node.js 映象並透過更好的包管理方法進一步最佳化它。
2. 如何在 Docker 化的 Node.js 應用程式中處理環境變數?
您可以使用 ENV 指令在 Dockerfile 中設定環境變數,但最佳實踐是在執行時透過 -e 標誌傳遞它。您可以使用環境變數進行配置以增強靈活性和安全性。
3. 如何除錯在 Docker 容器中執行的 Node.js 應用程式?
您可以使用 Node.js 本身、帶有遠端除錯擴充套件的 Visual Studio Code 或其他第三方工具等遠端除錯工具來除錯在 Docker 容器內執行的 Node.js 應用程式。在您的 Dockerfile 中公開除錯埠並相應地配置您的 IDE。