夜猫子的知识栈 夜猫子的知识栈
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《Web Api》
    • 《ES6教程》
    • 《Vue》
    • 《React》
    • 《TypeScript》
    • 《Git》
    • 《Uniapp》
    • 小程序笔记
    • 《Electron》
    • JS设计模式总结
  • 《前端架构》

    • 《微前端》
    • 《权限控制》
    • monorepo
  • 全栈项目

    • 任务管理日历
    • 无代码平台
    • 图书管理系统
  • HTML
  • CSS
  • Nodejs
  • Midway
  • Nest
  • MySql
  • 其他
  • 技术文档
  • GitHub技巧
  • 博客搭建
  • Ajax
  • Vite
  • Vitest
  • Nuxt
  • UI库文章
  • Docker
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

夜猫子

前端练习生
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《Web Api》
    • 《ES6教程》
    • 《Vue》
    • 《React》
    • 《TypeScript》
    • 《Git》
    • 《Uniapp》
    • 小程序笔记
    • 《Electron》
    • JS设计模式总结
  • 《前端架构》

    • 《微前端》
    • 《权限控制》
    • monorepo
  • 全栈项目

    • 任务管理日历
    • 无代码平台
    • 图书管理系统
  • HTML
  • CSS
  • Nodejs
  • Midway
  • Nest
  • MySql
  • 其他
  • 技术文档
  • GitHub技巧
  • 博客搭建
  • Ajax
  • Vite
  • Vitest
  • Nuxt
  • UI库文章
  • Docker
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 任务管理日历

    • 前言
    • 前端搭建

    • 后端搭建

    • 部署前置篇
    • 前端部署

    • 后端部署

      • 单机部署
        • 技术方案
        • 项目依赖的第三方容器
        • 编写 Dockerfile
          • docker 体积优化策略
        • 编写docker-compose.yml
          • 命令说明
          • image
          • restart
          • volumes
          • expose
          • environment
          • env_file
          • build
          • ports
          • container_name
          • links
          • depends_on
        • 配置项目
          • 创建 .dockerignore文件
          • 更改项目配置文件
          • config.default.ts
        • 服务器部署
          • 安装 node、npm、git
          • 下载代码到服务器
          • 运行项目
          • 查看运行状态,是否是 running 状态
          • 修改服务器防火墙
          • 测试是否能访问
          • 更改服务器 nginx 配置
          • 代码更新,重新部署
      • GitLab CICD
      • Serverless部署
  • 无代码平台

  • 图书管理系统

  • 《全栈项目》
  • 任务管理日历
  • 后端部署
夜猫子
2023-07-11
目录

单机部署

# 技术方案

通过 docker compose进行部署

# 项目依赖的第三方容器

  1. redis7
  2. mysql8

# 编写 Dockerfile

由于后端我们使用的 Midway 框架,它是由 ts 编写的,部署时需要将 ts 文件构建成 js 文件,所以这里会走一个 npm run build 构建命令;

如果你用的是其它 node.js 框架,比如 express 可能并不需要 build 这一阶段

FROM node:12 AS build

WORKDIR /app

COPY . .

RUN npm install --registry=https://registry.npmmirror.com

RUN npm run build

FROM node:12-alpine

WORKDIR /app

COPY --from=build /app/dist ./dist
COPY --from=build /app/bootstrap.js ./
COPY --from=build /app/package.json ./

# 在docker container 中不能自动识别宿主机的时区,可通过安装tzdata软件包,配置TZ环境变量识别正确时区.
RUN apk add --no-cache tzdata
ENV TZ="Asia/Shanghai"

# 移除开发依赖,构建正式包的时候只安装 dependencies 的依赖
RUN npm install --production --registry=https://registry.npmmirror.com

# 如果端口更换,这边可以更新一下
EXPOSE 7001

CMD ["npm", "run", "start"]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# docker 体积优化策略

  1. 合理使用 COPY 命令,COPY命令是会对文件进行差异化对比的,只要文件没有发生变化,那么就会使用上一层的镜像缓存

    1. 当然 ADD 也可以,但是 COPY 和 ADD 还是有本质区别的, docker 文档 (opens new window)有对这两个命令有所解释
  2. 多阶段构建

    1. 通过多阶段构建,减少构建体积
    2. 多阶段构建最明显的好处是,最终打出的镜像只包含编译产物而不包含编译过程中的依赖等冗余文件,可大大减小最终镜像的体积

# 编写docker-compose.yml

version: '3'
services:
  redis:
    image: redis:7-alpine
    restart: always
    volumes:
      - ./home/redis/data:/data
    environment:
      TZ: Asia/Shanghai
    expose:
      - 6379

  mysql:
    image: mysql:8
    restart: always
    volumes:
      - ./home/mysql/data:/var/lib/mysql
    expose:
      - 3306
    command: --default-authentication-plugin=mysql_native_password
      --character-set-server=utf8mb4
      --collation-server=utf8mb4_general_ci
    env_file:
      - ./.env
    environment:
      - TZ=Asia/Shanghai
      - MYSQL_DATABASE=tutulist_admin
      - MYSQL_ROOT_USER=root
      - MYSQL_ROOT_PASSWORD=tutulist

  app:
    container_name: app_server
    build: .
    ports:
      - '7001:7001'
    env_file:
      - ./.env
    restart: always
    depends_on:
      - mysql
      - redis
    links:
      - redis
      - mysql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

# 命令说明

文档上啥都有 文档地址 (opens new window)

# image

指定使用的镜像名称,redis 我们使用的是 alpine 版本,大小只有 28.4 MB

# restart

指定容器退出后的重启策略为始终重启

# volumes

数据卷所挂载路径设置,可以持久化的保存数据;

拿 mysql 为例,我们并不希望 mysql 容器关闭后,存储在 mysql 中存储的数据就丢了,这时我们可以将映射一个宿主机的目录,将数据存储在宿主机上

# expose

暴露端口,但不映射到宿主机,只被连接的服务访问;

不映射到宿主机也有缺点

  1. 就是调试不方便,拿 MySQL 为例,不映射端口到宿主机,我们就无法在宿主机使用 navicat 连接这个数据库查看数据

# environment

设置环境变量

# env_file

从文件中获取环境变量,就是我们的那个 .env

# build

指定 Dockerfile 所在文件夹的路径

# ports

暴露端口信息

格式

  1. 宿主机端口:容器端口

# container_name

指定容器名称

# links

默认情况下,服务之间可使用服务名称相互访问, links允许我们定义一个别名,从而使用该别名访问其他服务

比如,之前我们在 config.dev.ts 中需要制定具体的 host 名称,现在我们就可以直接使用别名访问

img

# depends_on

解决容器的依赖、启动先后的问题

比如我们的 app 容器,它依赖于 mysql 和 redis两个容器 ,只有它们先启动了,我们 app 业务容器才能对外提供服务

# 启动并不代表就能提供服务
  1. 拿我们的电脑的日常开机来讲,启动 -> 加载进度条 -> 展示界面,从启动到展示界面这段过程中,我们的电脑是不能给我们提供服务的
  2. 为了解决 这个问题 (opens new window),我们就需要用到另一个工具 wait-for-it (opens new window)
# 使用 restart: always 解决此问题

在这里我没有使用 wait-for-it 这个脚本,而是配置了 restart:always

我们的 app 业务容器连接不上 mysql是会报错的,并且 app 业务容器也会停止运行,而我们配置 restart:always 后,每次报错停止运行后,都会重启容器,直至mysql 容器能给 app 容器提供服务。

# 其它方案

condition: service_completed_successfully (opens new window)

# 配置项目

# 创建 .dockerignore文件

它的作用和 git 的 .gitignore 类似,我们直接将 .gitignore内容复制进去即可

# 更改项目配置文件

根据环境的不同,midway 会加载不同的配置文件,在这里我们以 build 为例, 它会将 config.default.ts 和 config.prod.ts 配置进行合并,详情见 midway 文档 (opens new window)

img

# config.default.ts

所有的环境都会走这个文件,一般也会作为 开发环境 的默认配置文件。

如果在生产环境中走另一套配置,只需要在 config.prod.ts 中再添加一份配置即可,如果配置相同,它会将 config.default 的配置进行覆盖

import { MidwayConfig } from '@midwayjs/core';
export default {
  keys: '1659760140542_6750',
  koa: {
    globalPrefix: '/api',
    port: 7001,
  },
  jwt: {
    secret: 'xxxxxxxxxxxxxxxxx', // fs.readFileSync('xxxxx.key')
    expiresIn: '2d', // https://github.com/vercel/ms
    refreshExpiresIn: '4d',
  },
  typeorm: {
    dataSource: {
      default: {
        type: 'mysql',
        host: 'mysql',
        port: 3306,
        synchronize: true,
        database: process.env.DATABASE_NAME,
        username: process.env.DATABASE_USERNAME,
        password: process.env.DATABASE_PASSWORD,
        entities: ['/entity'],
      },
    },
  },
  redis: {
    client: {
      port: 6379,
      host: 'redis', // Redis host
      db: 0,
    },
  },
} as MidwayConfig;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

# 服务器部署

# 安装 node、npm、git

sudo yum install –y nodejs
sudo yum install -y npm
sudo yum install -y git
1
2
3

# 下载代码到服务器

git clone 拉取代码。

ls-a查看是否存在 .env 文件,可能会被 .gitignore 给忽略掉了,没有就 touch .env 创建一个,将项目中的环境变量 copy 进去

img

# 运行项目

关于 docker compose 更多命令 (opens new window)

docker compose up -d
1

# 查看运行状态,是否是 running 状态

docker compose ps
1

img

# 修改服务器防火墙

将 7001 端口暴露出来

img

# 测试是否能访问

img

# 更改服务器 nginx 配置

添加 /api/ 开头的配置并配置代理,让前端可以通过 api 进行访问

location /api/ {
  proxy_pass http://43.138.82.165:7001;
}
1
2
3

重启 nginx 容器

docker restart nginx
1

# 代码更新,重新部署

当我们的业务代码发生变更时,需要重新构建

git pull
1
  • 拉取最新代码
docker compose up -d --build app --no-deps
1
  • --build:构建(重新构建)项目中的服务容器。
  • [service name]:在 docker-compose.yml 文件中为我们的业务容器定义的服务名称 app
  • --no-deps:不启动与该 service 关联的其它容器。

以上的方式还是要登录服务器,并在服务器上手敲命令。

在下一篇中,我们会借助 gitlab ci/cd 和 gitlab webhooks 最终将这一流程实现自动化

编辑 (opens new window)
上次更新: 2024/6/18 13:14:59
Gitlab CICD
GitLab CICD

← Gitlab CICD GitLab CICD→

最近更新
01
IoC 解决了什么痛点问题?
03-10
02
如何调试 Nest 项目
03-10
03
Provider注入对象
03-10
更多文章>
Copyright © 2019-2025 Study | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式