Docker部署Node+Koa+TS+Mongo项目

ops/2024/10/18 23:23:24/

在这里插入图片描述

Docker 简介

简而言之,Docker 容器轻量级、启动快、可移植,适合微服务架构。主要组件包括 Docker Engine、Docker 镜像、Docker 容器和 Docker Hub,它通过容器打包应用程序及其依赖项,使得应用在任何环境中都能一致运行。

这里不详细介绍 docker,想了解更多相关知识可以去官网查看docker 官网

docker_mac__8">安装 docker (mac 系统)

1.通过官网下载小鲸鱼(Docker Desktop),查看 About Dokcer Desktop,可以看到 docker 的信息
在这里插入图片描述

2.打开终端,输入docker -v查看当前的版本,或者查看 docker 服务状态docker info

docker -v 或者 docker info

➜  ~ docker -v
Docker version 27.0.3, build 7d4bcd8

3.如果zsh: command not found: docker,按照以下步骤处理:

  • 在.bash_profile 写入:export PATH=$PATH:/Applications/Docker.app/Contents/Resources/bin/
  • 在.zshrc 中写入:source ~/.bash_profile
  • 运行source .zshrc
  • 运行docker -v

docker_28">测试 docker

终端运行docker run hello-world, 会得到以下结果:

➜  ~ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
c1ec31eb5944: Pull complete
Digest: sha256:1408fec50309afee38f3535383f5b09419e6dc0925bc69891e79d84cc4cdcec6
Status: Downloaded newer image for hello-world:latestHello from Docker!
This message shows that your installation appears to be working correctly.
....(忽略其他的)

hello-world 是 docker 上面发布的镜像,在 Docker Desktop 中也能看到这个 Image 和 Container,说明 docker 已经可以正常使用了。

docker__48">docker 镜像和容器

这里来说下 docker 镜像和容器的关系:

  • 想象一下,你要做一个蛋糕。蛋糕的配方就像是 Docker 镜像。
  • 这个配方详细列出了制作蛋糕所需的所有材料和步骤。同样,Docker 镜像包含了一个应用程序运行所需的所有文件、依赖项和设置(可以理解为一个完整的项目)。
  • 当你有了配方(Docker 镜像)之后,你可以根据这个配方反复制作蛋糕(启动容器)。
  • 每次制作出来的蛋糕(容器)都是一样的,因为它们都是根据同一个配方(镜像)做出来的。

镜像的拉取和创建

  1. docker pull 从 Docker Hub 或者其他注册表中拉取镜像
# 拉取 node 镜像最新版本或者指定版本
docker pull node:latest 或 docker pull node:20.10.0
  1. docker image build 从 Dockerfile 构建一个镜像(下面会讲)
docker build -t <镜像名>:<标签> <Dockerfile所在目录>

容器的启动

  1. 使用该镜像运行一个容器 docker run [选项] <镜像名>:[标签]

docker run -d -p 8000:3000 --name my-node-app node:20.10.0

常用选项:

  • -d: 后台运行
  • -p: 端口映射(如 -p 8000:3000, 访问 localhost:8000 代替 localhost:3000)
  • --name: 为容器指定一个名称
  1. 查看所有容器(包括停止的容器)

docker ps -a

  1. 停止和开启容器

docker stop <容器 ID 或名称> / docker start <容器 ID 或名称>

  1. 删除容器

docker rm <容器 ID 或名称>


以上介绍和示例跑通说明我们已经可以开始使用 docker 来部署我们的项目了(其他更多的 docker 语法可以在网上自行查阅,这里不进行详细讲解)

Dockerfile

# 选择基础镜像
FROM node:latest# 设置维护者信息
LABEL maintainer="edon"# 防止中文打印信息显示乱码
ENV LANG="C.UTF-8"# WORKDIR:设置工作目录,所有后续指令(如RUN、COPY、ADD)都会在这个目录下执行。如果目录不存在,会自动创建。
WORKDIR /app# COPY <源路径> <目标路径> 将文件或目录从构建上下文复制到镜像中。(如有忽略文件配置在.dockerignore中)
COPY ./package.json /app
COPY . /app# RUN: 在镜像内执行命令。常用于安装软件包或配置环境。
RUN npm install
RUN npm run build
或
RUN npm install && npm run build# EXPOSE: 声明镜像要监听的端口,这只是一个文档化的指令,实际上并不会开放端口。
EXPOSE 3000# CMD:指定容器启动时要执行的命令,Dockerfile中只能有一个CMD指令,后面的会覆盖前面的
CMD ["node", "app.js"]

还有其他的配置如,ADDENTRYPOINTVOLUMEUSERARG等等,在这里不详细列出。

以上是 Dockerfile 最基础的结构,将 Dockerfile 放置在根目录下,执行docker image build -t [image:name]:[tag] .即可创建镜像,创建完就可以docker run来运行了。

执行:docker image build -t my-node-app:0.1 .

在这里插入图片描述

在Docker Desktop的Images可以看到:
在这里插入图片描述

Docker Compose

Dockerfile 构建的是一个独立的镜像,但是像我们的后端项目,一般还会连接数据库,比如 mongodb,按照 Dockerfile 模块的介绍,我们还要创建 mongo 的镜像和开启 mongo 容器

# 拉取mongo镜像
docker pull mongo:latest
# 运行mongo容器
docker run -d --name mongo -p 27017:27017 -v mongo-data:/data/db mongo:latest

当我们有一个后端项目,连接着数据库,如 node+mongo,我们可以使用Docker Compose,在一个 docker-compose.yml 文件中定义 Node.js 应用和 MongoDB 的服务,并一次性启动它们。

version: "3.8"services:app:image: node:20.16.0container_name: node-koa-tempworking_dir: /app/servervolumes:- ./:/app/server- /app/server/node_modulesenvironment:- HOST_MONGO_URL=mongodb://mongo:27017- PORT=8000depends_on:- mongoports:- "8001:8000"command: sh -c "npm install -g pnpm@latest --registry=https://registry.npmmirror.com && pnpm install && npm run build && npm run start:build"mongo:image: mongo:latestcontainer_name: node-koa-mongodbports:- "27018:27017"volumes:- mongo-data:/data/dbvolumes:mongo-data:

以上的配置看着是不是很熟悉,跟 Dockerfile 的配置很相似,配置介绍可参考:Docker Compose


实战 node+koa+ts+mongo

1.先准备好一个 node 后端项目,这里我们会写一个 node+koa+ts+mongo 的项目(这里本地具备 node 和 mongo 环境)

仓库地址

demo仓库地址:github node+koa+ts+mongo

Demo项目介绍

node-koa-temp
│
├── src
│   ├── index.ts
│   ├── controllers
│   │   └── users.ts
│   ├── models
│   │   └── users.ts
│   ├── mongodb
│   │   └── index.ts
│   ├── routes
│   │   └── index.ts
│   ├── types
│   │   ├── common.ts
│   │   └── user.ts
├── .dockerignore
├── .npmrc
├── docker-compose.yml
├── Dcokerfile
├── nodemon.json
├── package.json
├── tsconfig.json
└── README.md

src/mongodb/index.ts

import mongoose from "mongoose"const uri = "mongodb://localhost:27017"export const connectToDatabase = async () => {try {await mongoose.connect(uri, { dbName: "local-mongodb" })console.log("Connected to MongoDB with Mongoose")} catch (error) {console.error("Failed to connect to the database", error)throw error}
}

src/index.ts

import cors from "@koa/cors"
import http from "http"
import Koa from "koa"
import bodyParser from "koa-bodyparser"
import router from "src/routes"
import { connectToDatabase } from "./mongodb"const app = new Koa()
app.use(cors({origin: "*",allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],allowHeaders: ["Content-Type", "Authorization", "Accept"],})
)
app.use(bodyParser())
app.use(router.routes()).use(router.allowedMethods())const server = http.createServer(app.callback())
connectToDatabase().then(() => {const PORT = 8000server.listen(PORT, () => {console.log(`Server is running http://localhost:${PORT}`)})}).catch((error) => {console.error("Failed to connect to the database", error)})

tyconfig.json

{"compilerOptions": {"target": "es6","module": "commonjs","outDir": "./dist","strict": true,"esModuleInterop": true,"baseUrl": "./","paths": {"src/*": ["./src/*"],"~/*": ["./*"]},"typeRoots": ["node_modules/@types", "typings"]},"include": ["src/**/*", "typings"],"exclude": ["node_modules"]
}

nodemon.json

{"ignore": ["./node_modules/**"],"watch": ["src"],"exec": "cross-env ts-node -r tsconfig-paths/register src/index.ts","ext": "ts,json"
}

package.json

  "scripts": {"dev": "cross-env MODE=stage nodemon --config nodemon.json","build": "rimraf dist && tsc && tsc-alias","start:build": "cross-env MODE=prod node dist/index.js"},

本地运行项目

npm run dev

运行成功,可以访问 localhost:8000

在这里插入图片描述

本地编译打包项目和启动

npm run build
npm run start:build

运行成功,可以访问 localhost:8000

docker-compose.yml

version: "3.8"services:app:image: node:20.16.0container_name: node-koa-tempworking_dir: /app/servervolumes:- ./:/app/server- /app/server/node_modulesenvironment:- HOST_MONGO_URL=mongodb://mongo:27017- PORT=8000depends_on:- mongoports:- "8001:8000"command: sh -c "npm install -g pnpm@latest --registry=https://registry.npmmirror.com && pnpm install && npm run build && npm run start:build"mongo:image: mongo:latestcontainer_name: node-koa-mongodbports:- "27018:27017"volumes:- mongo-data:/data/dbvolumes:mongo-data:

在根目录下执行docker-compse up --build,一次性启动两个容器

在这里插入图片描述

Docker Desktop 的 Container 可以看到:

在这里插入图片描述

这个时候访问 http://localhost:8001, 就可以访问到我们的服务了。

按照以上流程,使用 Dockerfile 可以直接部署 vue 或 React 前端项目,实现 docker 部署前后端项目项目。


http://www.ppmy.cn/ops/90134.html

相关文章

day_31

56. 合并区间 class Solution:def merge(self, intervals: List[List[int]]) -> List[List[int]]:res []if len(intervals) 0:return resintervals.sort(keylambda x:x[0])res.append(intervals[0])for intervali in intervals:if res[-1][1] > intervali[0]:res[-1][…

末日期权暴涨的条件是什么?

末日期权一般是指期权合约快到期的一周或者最后三天&#xff0c;当然最后一天就是末日期权的疯狂。我们可能经常听到期权市场某一天突然合约可能暴涨几百倍甚至上千倍&#xff0c;或暴跌几百&#xff0c;这就是期权的末日轮效应&#xff0c;今天我们就来聊一下末日期权暴涨的条…

【矩阵对角线求和】求一个3*3矩阵对角线元素之和

求一个3*3矩阵对角线元素之和&#xff0c;使用C语言实现 具体代码&#xff1a; #include<stdio.h>int main(){float a[3][3],sum0;printf("请输入3x3矩阵的元素&#xff08;按行输入&#xff09;&#xff1a;\n");for(int i0;i<3;i){for(int j0;j<3;j)…

SQL进阶技巧:如何分析可能好有问题?

目录 0 问题描述 1 数据准备 2 数据分析 3 小结 0 问题描述 给定每个用户的好友列表,好友关系是互相对称的,返回每个用户的可能好友。如果两个用户不是好友关系,并且两者拥有至少一个(或者两个)共同好友,则两者互相是可能好友。 1 数据准备 --建表语句 create tab…

Java实习记录 7 ——使用 Callable 多线程优化接口开发

Java实习记录 7 ——使用 Callable 多线程优化接口开发 引言正文收获 引言 实习第四周&#xff0c;接触到一个新需求&#xff0c;要求查询用户添的系列课程历史记录&#xff0c;包含分页查询以及按创建时间排序。主要要求查询&#xff0c;课程的名称、课程适合的年龄段、包含单…

使用Adobe Photoshop CS5给图片加水印

使用Adobe Photoshop CS5给图片加水印 前言1.我这里使用的是Adobe Photoshop CS52.新建空白画布3.写入水印内容4.按 Ctrl T 将其倾斜5.右键图层选择“混合选项”6.选择描边&#xff0c;颜色选择灰色7.效果如下8.填充选择0&#xff0c;不透明度选择75%9.打开编辑&#xff0c;选…

如何判断IP地址属于住宅IP还是机房IP

在数字化时代,IP地址作为互联网通信的基础标识&#xff0c;扮演着重要的角色。无论是网络管理、数据分析还是安全监控&#xff0c;正确识别IP地址的类型——尤其是区分是住宅IP还是机房IP&#xff0c;对于确保网络安全、优化网络性能以及合法合规运营具有重要意义。IPIDEA代理I…

如何在不同设备上检查您的 IP 地址?

IP 地址&#xff08;Internet 协议地址&#xff09;是网络上设备的唯一标识符。了解如何查找 IP 地址对于解决网络问题、设置网络设备和维护网络安全非常重要。本文将详细介绍如何在不同设备上检查 IP 地址&#xff0c;包括 Windows 计算机、Mac 计算机、智能手机&#xff08;A…