Skip to content

Commit

Permalink
feat: nestjs socket.io 集成
Browse files Browse the repository at this point in the history
fix #187

feat: nestjs socket.io 集成

fix #187

chore: docker部署调整

ci: nestjs-backend服务名修改

fix: nest端口调整
  • Loading branch information
cumt-robin committed Dec 17, 2024
1 parent 3b7d8b4 commit 3aab4d5
Show file tree
Hide file tree
Showing 21 changed files with 506 additions and 118 deletions.
6 changes: 6 additions & 0 deletions .changeset/chilly-readers-hang.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"nest-server": major
"vite-vue3": patch
---

feat: nestjs socket.io 集成
72 changes: 72 additions & 0 deletions .github/workflows/nest-server.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
name: nest_server_cicd

on:
push:
tags:
- 'nest-server@*'

env:
SSH_PRIVATE_KEY: ${{secrets.SSH_PRIVATE_KEY}}

jobs:
extract:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.extract_version.outputs.version }}
steps:
- id: extract_version
run: |
echo "version=$(echo ${{ github.ref_name }} | sed 's/nest-server@//')" >> $GITHUB_OUTPUT
build:
needs: extract
runs-on: ubuntu-latest
env:
IMAGE_VERSION: ${{ needs.extract.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Build & Push Image
run: |
echo "${{env.IMAGE_VERSION}}"
docker login --username=${{secrets.DOCKER_USERNAME}} --password=${{secrets.DOCKER_PASSWORD}} ${{secrets.DOCKER_REGISTRY}}
docker build --target nestjs-backend -t ${{secrets.DOCKER_REGISTRY}}/${{secrets.DOCKER_NAMESPACE}}/fullstack-blog-nest:${{env.IMAGE_VERSION}} .
docker push ${{secrets.DOCKER_REGISTRY}}/${{secrets.DOCKER_NAMESPACE}}/fullstack-blog-nest:${{env.IMAGE_VERSION}}
deploy:
needs: [extract, build]
runs-on: ubuntu-latest
env:
IMAGE_VERSION: ${{ needs.extract.outputs.version }}
steps:
- name: SSH Auth && Deploy Image
run: |
ssh -V
mkdir -p ~/.ssh
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
cat >>~/.ssh/config <<END
Host remote
HostName ${{secrets.SSH_HOST}}
Port 22
User ${{secrets.SSH_USERNAME}}
IdentityFile ~/.ssh/id_rsa
StrictHostKeyChecking no
END
cat >>~/remote.sh <<END
docker ps
docker login --username=${{secrets.DOCKER_USERNAME}} --password=${{secrets.DOCKER_PASSWORD}} ${{secrets.DOCKER_REGISTRY}}
docker pull ${{secrets.DOCKER_REGISTRY}}/${{secrets.DOCKER_NAMESPACE}}/fullstack-blog-nest:${{env.IMAGE_VERSION}}
cd ${{secrets.PROJECT_DIR}}
sed -i 's/^NEST_SERVER_VERSION=.*/NEST_SERVER_VERSION=${{env.IMAGE_VERSION}}/' .env.docker.local
docker compose --env-file .env.docker.local up -d
echo "Done"
END
ssh remote < ~/remote.sh
45 changes: 23 additions & 22 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ COPY . /usr/src/app
WORKDIR /usr/src/app
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
RUN pnpm deploy --filter=vite-vue3 /app/vite-vue3
RUN pnpm deploy --filter=webpack-vue3 /app/webpack-vue3
RUN pnpm deploy --filter=express-server /app/express-server
# RUN pnpm deploy --filter=webpack-vue3 /app/webpack-vue3
# RUN pnpm deploy --filter=webpack-vue3 /app/cra-react18
# RUN pnpm deploy --filter=express-server /app/express-server
RUN pnpm deploy --filter=nest-server /app/nest-server

FROM base AS vite-vue3-build
Expand All @@ -20,30 +21,30 @@ RUN pnpm build

FROM nginx:latest AS vite-vue3-frontend
COPY --from=vite-vue3-build /usr/src/fullstack-blog/app/vite-vue3/dist/ /usr/share/nginx/html
COPY nginx/default.conf.template /etc/nginx/conf.d/default.conf.template
EXPOSE 80

FROM base AS webpack-vue3-build
COPY --from=build /app/webpack-vue3 /usr/src/fullstack-blog/app/webpack-vue3
COPY tsconfig.base.json /usr/src/fullstack-blog/tsconfig.base.json
WORKDIR /usr/src/fullstack-blog/app/webpack-vue3
RUN pnpm build
# FROM base AS webpack-vue3-build
# COPY --from=build /app/webpack-vue3 /usr/src/fullstack-blog/app/webpack-vue3
# COPY tsconfig.base.json /usr/src/fullstack-blog/tsconfig.base.json
# WORKDIR /usr/src/fullstack-blog/app/webpack-vue3
# RUN pnpm build

FROM nginx:latest AS webpack-vue3-frontend
COPY --from=webpack-vue3-build /usr/src/fullstack-blog/app/webpack-vue3/dist/ /usr/share/nginx/html
COPY nginx/default.conf.template /etc/nginx/conf.d/default.conf.template
EXPOSE 80
# FROM nginx:latest AS webpack-vue3-frontend
# COPY --from=webpack-vue3-build /usr/src/fullstack-blog/app/webpack-vue3/dist/ /usr/share/nginx/html
# EXPOSE 80

FROM base AS express-backend
RUN npm i -g pm2-runtime
COPY --from=build /app/express-server /usr/src/fullstack-blog/app/express-server
WORKDIR /usr/src/fullstack-blog/app/express-server
EXPOSE 8002
CMD ["pnpm", "start-docker-prod"]
# FROM base AS express-backend
# RUN npm i -g pm2-runtime
# COPY --from=build /app/express-server /usr/src/fullstack-blog/app/express-server

FROM base AS nestjs-backend
RUN npm i -g pm2-runtime
FROM base AS nest-server-build
COPY --from=build /app/nest-server /usr/src/fullstack-blog/app/nest-server
WORKDIR /usr/src/fullstack-blog/app/nest-server
EXPOSE 8003
CMD ["pnpm", "start-docker-prod"]
RUN pnpm build

FROM base AS nestjs-backend
RUN npm i -g pm2-runtime
COPY --from=nest-server-build /usr/src/fullstack-blog/app/nest-server/dist /usr/src/fullstack-blog/app/nest-server/dist
COPY --from=nest-server-build /usr/src/fullstack-blog/app/nest-server/node_modules /usr/src/fullstack-blog/app/nest-server/node_modules
COPY --from=nest-server-build /usr/src/fullstack-blog/app/nest-server/package.json /usr/src/fullstack-blog/app/nest-server/package.json
COPY --from=nest-server-build /usr/src/fullstack-blog/app/nest-server/process-docker-prod.json /usr/src/fullstack-blog/app/nest-server/process-docker-prod.json
10 changes: 6 additions & 4 deletions app/nest-server/ENV.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,19 @@
开发环境可以准备一个`.env.development.local`文件,内容如下:

```
PORT=8003
PORT=8012
MYSQL_HOST=127.0.0.1
MYSQL_PORT=3306
MYSQL_USER=root
MYSQL_PASSWORD=xxx
MYSQL_DATABASE_NAME=blog_db
MYSQL_ROOT_PASSWORD=xxx
MYSQL_DATABASE=blog_db
JWT_SECRET=xxx
EMAIL_USER=xxx@163.com
EMAIL_PASS=xxx
BLOG_NAME=Tusi博客
AUTHOR_EMAIL=xxx
SITE_URL=https://blog.wbjiang.cn
OPENAI_API_KEY=xxx
WEB_SOCKET_WHITE_LIST=http://localhost:3000,http://127.0.0.1:3000
```

## 生产环境见 docker-ops.md
8 changes: 5 additions & 3 deletions app/nest-server/package.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
{
"name": "nest-server",
"version": "0.8.0",
"description": "",
"author": "",
"description": "nestjs backend",
"private": true,
"license": "UNLICENSED",
"scripts": {
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start",
"dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"start-docker-prod": "pm2-runtime start process-docker-prod.json",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest",
"test:watch": "jest --watch",
Expand All @@ -26,7 +25,9 @@
"@nestjs/jwt": "^10.2.0",
"@nestjs/mapped-types": "*",
"@nestjs/platform-express": "^10.0.0",
"@nestjs/platform-socket.io": "^10.4.15",
"@nestjs/typeorm": "^10.0.2",
"@nestjs/websockets": "^10.4.15",
"@types/lodash": "^4.17.13",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
Expand All @@ -37,6 +38,7 @@
"openai": "^3.1.0",
"reflect-metadata": "^0.2.0",
"rxjs": "^7.8.1",
"socket.io": "^4.8.1",
"svg-captcha": "^1.3.12",
"typeorm": "^0.3.20",
"xss": "^1.0.9"
Expand Down
8 changes: 8 additions & 0 deletions app/nest-server/process-docker-prod.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"apps": [
{
"name": "blog-nest-server",
"script": "dist/main.js"
}
]
}
11 changes: 7 additions & 4 deletions app/nest-server/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,23 @@ import { ReplyModule } from "./modules/reply/reply.module";
import { CommonModule } from "./modules/common/common.module";
import { BannerModule } from "./modules/banner/banner.module";
import { ChatgptModule } from "./modules/chatgpt/chatgpt.module";
import { ChatModule } from "./modules/chat/chat.module";

@Module({
imports: [
CommonModule,
ConfigModule.forRoot({
isGlobal: true,
envFilePath: [".env.development.local", ".env"],
// 数组中的第一个文件路径具有最高优先级,依次类推。运行时环境变量优先级更高。
envFilePath: [".env.development.local", ".env.production.local", ".env"],
}),
TypeOrmModule.forRoot({
type: "mysql",
host: process.env.MYSQL_HOST,
port: parseInt(process.env.MYSQL_PORT),
username: process.env.MYSQL_USER,
password: process.env.MYSQL_PASSWORD,
database: process.env.MYSQL_DATABASE_NAME,
username: "root",
password: process.env.MYSQL_ROOT_PASSWORD,
database: process.env.MYSQL_DATABASE,
autoLoadEntities: true,
// entities: [__dirname + "/entities/*.ts"],
}),
Expand All @@ -40,6 +42,7 @@ import { ChatgptModule } from "./modules/chatgpt/chatgpt.module";
ReplyModule,
BannerModule,
ChatgptModule,
ChatModule,
],
controllers: [],
providers: [
Expand Down
2 changes: 1 addition & 1 deletion app/nest-server/src/guards/auth.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export class AuthGuard implements CanActivate {
if (error instanceof TokenExpiredError) {
throw new InnerException("000002", "授权已过期");
}
throw new InnerException("000001", "对不起,您还未获得授权");
throw new InnerException("000004", "授权验证失败");
}

return true;
Expand Down
2 changes: 1 addition & 1 deletion app/nest-server/src/modules/article/article.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export class ArticleController {
return this.articleService.getPage(query);
}

@Get("/admin/page")
@Get("/page_admin")
adminPage(@Query() query: GetPageDto) {
return this.articleService.getAdminPage(query);
}
Expand Down
71 changes: 71 additions & 0 deletions app/nest-server/src/modules/chat/chat.gateway.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import {
WebSocketGateway,
SubscribeMessage,
MessageBody,
WebSocketServer,
OnGatewayConnection,
OnGatewayDisconnect,
ConnectedSocket,
} from "@nestjs/websockets";
import { Server, Socket } from "socket.io";

@WebSocketGateway({
path: "/socket.io",
namespace: "/chatroom",
allowEIO3: true,
cors: {
origin: (origin, callback) => {
const list = process.env.WEB_SOCKET_WHITE_LIST.split(",");
if (list.includes(origin)) {
callback(null, true);
} else {
callback(new Error("Not allowed by CORS"));
}
},
// origin: "http://localhost:3000",
credentials: true,
},
})
export class ChatGateway implements OnGatewayConnection, OnGatewayDisconnect {
@WebSocketServer()
server: Server;

private getId(client: Socket) {
return client.id.replace("/chatroom#", "");
}

handleConnection(client: Socket) {
client.emit("singleMsg", {
event: "greet_from_server",
data: {
content: "hello,欢迎您加入在线聊天室!",
},
});
client.broadcast.emit("broadcast", {
event: "new_user_join",
data: {
user: this.getId(client),
},
});
}

handleDisconnect(client: Socket) {
client.broadcast.emit("broadcast", {
event: "someone_exit",
data: {
user: this.getId(client),
},
});
}

@SubscribeMessage("chat")
onChat(@MessageBody() data: Record<string, any>, @ConnectedSocket() client: Socket) {
client.broadcast.emit("broadcast", {
event: "new_chat_content",
data: {
user: this.getId(client),
content: data,
},
});
}
}
7 changes: 7 additions & 0 deletions app/nest-server/src/modules/chat/chat.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Module } from "@nestjs/common";
import { ChatGateway } from "./chat.gateway";

@Module({
providers: [ChatGateway],
})
export class ChatModule {}
2 changes: 1 addition & 1 deletion app/vite-vue3/.env.development
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# 开发环境变量
VITE_APP_SOCKET_SERVER=http://localhost:8002
VITE_APP_SOCKET_SERVER=http://localhost:8012
2 changes: 1 addition & 1 deletion app/vite-vue3/.env.production
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# 生产环境变量
VITE_APP_SOCKET_SERVER=https://blog.wbjiang.cn
VITE_APP_SOCKET_SERVER=https://blog.wbjiang.cn
2 changes: 1 addition & 1 deletion app/vite-vue3/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default defineConfig({
port: 3000,
proxy: {
"/api": {
target: "http://express-server:8002",
target: "http://127.0.0.1:8012",
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ""),
},
Expand Down
2 changes: 1 addition & 1 deletion build-dev-images.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
# docker build . -f Dockerfile.dev --target vite-vue3-frontend --tag fullstack-blog-vite-vue3:dev
# docker build . -f Dockerfile.dev --target cra-react18-frontend --tag fullstack-blog-cra-react18:dev
# docker build . -f Dockerfile.dev --target express-backend --tag fullstack-blog-express:dev
docker build . -f Dockerfile.dev --target nestjs-backend --tag fullstack-blog-nestjs:dev
# docker build . -f Dockerfile.dev --target nestjs-backend --tag fullstack-blog-nestjs:dev

echo "build dev images successfully."
Loading

0 comments on commit 3aab4d5

Please sign in to comment.