编写Node.js应用代码,并确保它可以在本地运行。
在使用 npm 之前,需要先安装 Node.js。因为 npm 是随 Node.js 一起安装的。你可以通过以下命令检查它们是否已经安装以及查看版本信息:
zgq@docker01:~$ node -v
Command 'node' not found, but can be installed with:
sudo apt install nodejs
zgq@docker01:~$ npm -v
Command 'npm' not found, but can be installed with:
sudo apt install npm
我的机器没有安装npm、node ,以下执行安装操作,(先安装node)
先执行对系统的更新操作
root@docker01:/home/zgq# apt update
root@docker01:/home/zgq# apt upgrade
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Calculating upgrade... Done
The following upgrades have been deferred due to phasing:
libunwind8 python3-distupgrade ubuntu-release-upgrader-core
0 upgraded, 0 newly installed, 0 to remove and 3 not upgraded.
zgq@docker01:~$ sudo apt install nodejs
sudo: unable to resolve host docker01: Name or service not known
[sudo] password for zgq:
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
libcares2 libnode109 node-acorn node-busboy node-cjs-module-lexer node-undici node-xtend nodejs-doc
Suggested packages:
npm
The following NEW packages will be installed:
libcares2 libnode109 node-acorn node-busboy node-cjs-module-lexer node-undici node-xtend nodejs nodejs-doc
0 upgraded, 9 newly installed, 0 to remove and 143 not upgraded.
Need to get 16.1 MB of archives.
After this operation, 70.4 MB of additional disk space will be used.
Do you want to continue? [Y/n] y
再安装npm
root@docker01:/home/zgq# apt install npm
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
npm is already the newest version (9.2.0~ds1-2).
0 upgraded, 0 newly installed, 0 to remove and 3 not upgraded.
验证版本信息
zgq@docker01:~$ sudo node -v
v18.19.1
zgq@docker01:~$ sudo npm -v
9.2.0
如果显示出版本号,说明已经安装成功。
如果你还没有项目目录,可以创建一个新的目录,并在该目录下初始化一个新的 Node.js 项目。以下是具体操作:
# 创建一个新的项目目录
zgq@docker01:~$ mkdir my-express-app
# 进入项目目录
zgq@docker01:~$ cd my-express-app
# 初始化项目,会生成一个 package.json 文件
zgq@docker01:~/my-express-app$ npm init -y
Wrote to /home/zgq/my-express-app/package.json:
{
"name": "my-express-app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
npm init -y 中的 -y 选项表示使用默认配置快速初始化项目,这样会自动生成一个 package.json 文件,该文件用于记录项目的元数据和依赖信息。
zgq@docker01:~/my-express-app$ npm install express
added 69 packages, and audited 70 packages in 6s
14 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
zgq@docker01:~/my-express-app$ cat package.json
{
"name": "my-express-app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.21.2" // 此版本号可能会根据实际安装情况有所不同,执行npm install 命令后会添加Express作为项目的依赖项
}
}
const express = require('express');
const app = express();
const port = 3000;
app.get('/', (req, res) => {
res.send('Hello, World!');
});
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
可以使用nano编辑,例如:
zgq@docker01:~/my-express-app$ nano app.js
zgq@docker01:~/my-express-app$ node app.js
Server is running on port 3000
在项目根目录下创建一个 Dockerfile 文件,用于定义如何构建镜像。以下是一个简单的 Node.js 应用的 Dockerfile 示例:
# 使用官方 Node.js 镜像作为基础镜像
FROM node: current-slim
# 设置工作目录
WORKDIR /app
# 复制 package.json 和 package-lock.json
COPY package*.json ./
# 安装依赖
RUN npm install
# 复制项目文件
COPY . .
# 暴露端口(假设应用运行在 3000 端口)
EXPOSE 3000
# 启动应用
CMD ["npm", "start"]
注意:命令行最某尾的" . " : 表示 Dockerfile 和构建上下文位于当前目录。
ubuntu@ip-172-31-89-208:~/zgq-kube/App$ sudo docker build -t zhuguoqiang999/node-app:1.0 .
[+] Building 9.4s (11/11) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 223B 0.0s
=> [internal] load metadata for docker.io/library/node:current-slim 0.5s
=> [auth] library/node:pull token for registry-1.docker.io 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 170B 0.0s
=> [1/5] FROM docker.io/library/node:current-slim@sha256:278dc9616f605d5de4304fb19bf245ec1fd5569fddf2c7ea611f6e7262de98b5 3.4s
=> => resolve docker.io/library/node:current-slim@sha256:278dc9616f605d5de4304fb19bf245ec1fd5569fddf2c7ea611f6e7262de98b5 0.0s
=> => extracting sha256:60eeb4400e1d51b1953b4b40591ad79190856f512afd10df0dcb13d184cf49c7 0.0s
=> => sha256:278dc9616f605d5de4304fb19bf245ec1fd5569fddf2c7ea611f6e7262de98b5 6.49kB / 6.49kB 0.0s
=> => sha256:9673e806eca4f9b3d32a0b8259e68c766d062136e3ea8e98bcffc440010a37b1 1.93kB / 1.93kB 0.0s
=> => sha256:3632793bb481bbf2c572029478b0141d66cbdc590dd32d4a708aa04605f8529d 6.54kB / 6.54kB 0.0s
=> => sha256:60eeb4400e1d51b1953b4b40591ad79190856f512afd10df0dcb13d184cf49c7 3.31kB / 3.31kB 0.1s
=> => sha256:ce755d7cf7f5964170ef8f511ba3de78ca52a5e4871dc9f467d05d47ae846059 49.81MB / 49.81MB 0.8s
=> => sha256:dc6c34e52d5c07b4fa00771ccd49191e4f3d6685ad6ab5cb7b53370bbc18a4f0 1.71MB / 1.71MB 0.2s
=> => sha256:ed279290f28c8b2682ebe25022d1df670b7c3a1499ab10bf6a00439647154c06 448B / 448B 0.2s
=> => extracting sha256:ce755d7cf7f5964170ef8f511ba3de78ca52a5e4871dc9f467d05d47ae846059 2.2s
=> => extracting sha256:dc6c34e52d5c07b4fa00771ccd49191e4f3d6685ad6ab5cb7b53370bbc18a4f0 0.1s
=> => extracting sha256:ed279290f28c8b2682ebe25022d1df670b7c3a1499ab10bf6a00439647154c06 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 1.13kB 0.0s
=> [2/5] WORKDIR /src 0.1s
=> [3/5] COPY package*.json ./ 0.0s
=> [4/5] RUN npm install 4.9s
=> [5/5] COPY . . 0.0s
=> exporting to image 0.3s
=> => exporting layers 0.3s
=> => writing image sha256:02a5d7d363c3ab6e6d6b0a92cf9580d6ca1ac01b9cfb71e0ec2ac7f60086ee6c 0.0s
=> => naming to docker.io/zhuguoqiang999/node-app:1.0 0.0s
ubuntu@ip-172-31-89-208:~/zgq-kube/App$ sudo docker run -p 3000:3000 zhuguoqiang999/node-app:1.0
Server is running on port 3000
需要重新开启另外一个终端连接服务器。
ubuntu@ip-172-31-89-208:~$ curl http://localhost:3000
Hello, Kubernetes! @Zhuguoqiang 2025.2.4 2937425@qq.
ubuntu@ip-172-31-89-208:~$ sudo docker login
Authenticating with existing credentials...
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credential-stores
Login Succeeded
2.推送镜像:
ubuntu@ip-172-31-89-208:~$ sudo docker push zhuguoqiang999/node-app:1.0
The push refers to repository [docker.io/zhuguoqiang999/node-app]
922d2f65e7aa: Pushed
289c1592db1b: Pushed
324187b0ba8b: Pushed
6cd6185f60c1: Pushed
10608948e461: Mounted from library/node
a1789e7ed79e: Mounted from library/node
dd75864d0f98: Mounted from library/node
5b7299b84b0c: Mounted from library/node
f5fe472da253: Mounted from zhuguoqiang999/qsk-book
1.0: digest: sha256:548a79a5fea6b61180156f53f7d54846ab333d87edf7fed8b8c740ada9421fa1 size: 2198
注意事项:
Dockerfile 路径:确保 Dockerfile 文件位于当前目录(.),或者指定正确的路径。
镜像名称:zhuguoqiang999/node-app 中的 zhuguoqiang999 必须是你的 Docker Hub 用户名,否则推送时会失败。
标签管理:建议为镜像添加明确的标签(如 zhuguoqiang999/node-app:1.0),而不是默认的 latest。
ubuntu@ip-172-31-89-208:~$ tree zgq-kube
zgq-kube
└── App
├── Dockerfile
├── app.js
└── package.json
2 directories, 3 files
将以下YAML 文件保存为 node-deployment.yaml,
# node-deployment.yaml
apiVersion: apps/v1
kind: Deployment # 表明这是 Kubernetes Deployment
metadata:
name: node-deployment # Deployment 的名称
spec:
replicas: 3 # 希望运行的 Pod 副本数量
selector:
matchLabels:
app: node-app # 选择具有这些标签的 Pod
template:
metadata:
labels:
app: node-app # 模板中创建的 Pod 的标签
spec:
containers:
- name: node-container # 容器的名称
image: zhuguoqiang999/node-app:1.0 # 使用的 Docker 镜像版本
ports:
- containerPort: 3000 # 容器内部监听的端口
运行以下命令创建和查看 Deployment、POD:
# 先测试node-deployment.yaml语法
zgq@k8s-node1:~/zgq-kube$ kubectl apply --dry-run='client' -f node-deployment.yaml
deployment.apps/node-deployment configured (dry run)
# 执行创建deployment
zgq@k8s-node1:~/zgq-kube$ kubectl apply -f node-deployment.yaml
deployment.apps/node-deployment created
# 查看创建的deployment
zgq@k8s-node1:~/zgq-kube$ kubectl get deployment |grep node-deployment
node-deployment 3/3 3 3 12m
# 查看创建的pods
zgq@k8s-node1:~/zgq-kube$ kubectl get pods |grep node-deployment
node-deployment-5c574c5cdb-6pwrq 1/1 Running 0 13m
node-deployment-5c574c5cdb-7hkm8 1/1 Running 0 13m
node-deployment-5c574c5cdb-qzm9v 1/1 Running 0 13m
为了让外部访问 Node.js 应用,需要创建一个 Service。创建一个 node-service.yaml 文件:
# node-service.yaml
apiVersion: v1
kind: Service # 表明这是 Kubernetes Service
metadata:
name: node-service # Service 的全局唯一名称
spec:
type: NodePort # 类型为 NodePort
ports:
- port: 80 # Service 提供服务的端口号
targetPort: 3000 # 目标 Pod 上容器监听的端口号
nodePort: 30008 # 暴露在节点上的端口号(可选,如果不指定会自动分配)
selector:
app: node-app # Service 对应的 Pod 拥有这里定义的标签
运行以下命令创建和查看 Deployment、POD:
# 先测试node-deployment.yaml语法
zgq@k8s-node1:~/zgq-kube$ kubectl apply --dry-run='client' -f node-deployment.yaml
deployment.apps/node-deployment configured (dry run)
# 执行创建deployment
zgq@k8s-node1:~/zgq-kube$ kubectl apply -f node-deployment.yaml
deployment.apps/node-deployment created
# 查看创建的deployment
zgq@k8s-node1:~/zgq-kube$ kubectl get deployment |grep node-deployment
node-deployment 3/3 3 3 12m
# 查看创建的pods
zgq@k8s-node1:~/zgq-kube$ kubectl get pods |grep node-deployment
node-deployment-5c574c5cdb-6pwrq 1/1 Running 0 13m
node-deployment-5c574c5cdb-7hkm8 1/1 Running 0 13m
node-deployment-5c574c5cdb-qzm9v 1/1 Running 0 13m
应用 Service 配置:
zgq@k8s-node1:~/zgq-kube$ kubectl apply --dry-run='client' -f node-service.yaml
service/node-service created (dry run)
zgq@k8s-node1:~/zgq-kube$ kubectl apply -f node-service.yaml
service/node-service created
zgq@k8s-node1:~/zgq-kube$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-node LoadBalancer 10.50.57.188 <pending> 8080:30856/TCP 7d17h
kubernetes ClusterIP 10.50.0.1 <none> 443/TCP 34d
kubernetes-bootcamp NodePort 10.50.28.53 <none> 8080:30707/TCP 7d16h
mysql ClusterIP 10.50.174.42 <none> 3306/TCP 45h
myweb NodePort 10.50.154.206 <none> 80:30001/TCP 42h
node-service NodePort 10.50.72.149 <none> 80:30008/TCP 10s
svc-local NodePort 10.50.187.62 <none> 8080:31111/TCP 3d1h
获取Service的NodePort端口:
zgq@k8s-node1:~/zgq-kube$ kubectl describe svc node-service
Name: node-service
Namespace: default
Labels: <none>
Annotations: <none>
Selector: app=node-app
Type: NodePort
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.50.72.149
IPs: 10.50.72.149
Port: <unset> 80/TCP
TargetPort: 3000/TCP
NodePort: <unset> 30008/TCP
Endpoints: 10.60.36.83:3000,10.60.169.147:3000,10.60.36.82:3000
Session Affinity: None
External Traffic Policy: Cluster
Internal Traffic Policy: Cluster
Events: <none>
使用Minikube或其他K8s集群,找到节点IP并访问:
minikube ip
然后在浏览器中访问:http://