Skip to content

项目写完了,本地跑没啥问题,我们最终是要把它部署到服务器上,跑起来。

我们会用到 mysql、redis、nginx,它们是这样的关系:

前端代码由 nginx 托管,处理静态请求。

并且后端服务也会经过 nginx 做反向代理,这样可以做多个 Nest 服务的负载均衡。

Nginx、Mysql、Redis、Nest 服务等都是通过 docker 来跑。

当然,不用一个个的跑,可以通过 Docker Compose 把它们组合成一个整体,一起跑。

开发完之后,本地把代码 push 到 github、gitlab 等代码仓库。

之后服务器上把代码 pull 下来,然后用 docker compose 跑就行。

有了 docker,根本不用考虑 mysql、redis、node 等在 linux 下怎么装,直接跑 docker 镜像就行。

是不是再次感受到了 docker 的好处?

此外,还有一点要注意,线上不能开启 typeorm 的 synchronize,这样代码一改就同步修改了表结构,容易导致数据丢失。

线上会用 migration 迁移来做。

详细的 migration 介绍看这节

我们一步步来做,首先,在本地用 docker compose 跑一下:

在后端项目的根目录添加 docker-compose.yml 文件:

yml
version: '3.8'
services:
  nest-app:
    build:
      context: ./
      dockerfile: ./Dockerfile
    depends_on:
      - mysql-container
      - redis-container
    ports:
      - 3005:3005
    networks:
      - common-network
  mysql-container:
    image: mysql
    volumes:
      - /Users/guang/mysql-data:/var/lib/mysql
    environment:
      MYSQL_DATABASE: meeting_room_booking_system
      MYSQL_ROOT_PASSWORD: guang
    networks:
      - common-network
  redis-container:
    image: redis
    volumes:
      - /Users/guang/redis-data:/data
    networks:
      - common-network
networks:
  common-network:
    driver: bridge

有 3 个 docker 容器,nest-app、mysql-container、redis-container

nest-app 是通过 Dockerfile 构建出来的,暴露 3005 端口。

nest-app 依赖 redis-container 和 mysql-container

redis-container 指定挂载的 volume 数据卷,以及 MYSQL_DATABASE(自动创建的 database) 和 MYSQL_ROOT_PASSWORD(root 用户密码) 的环境变量

mysql-container 指定挂载的 volume 数据卷

然后这是三个容器放到同一个桥接网络里。

在根目录添加 Dockerfile:

docker
FROM node:18.0-alpine3.14 as build-stage

WORKDIR /app

COPY package.json .

RUN npm config set registry https://registry.npmmirror.com/

RUN npm install

COPY . .

RUN npm run build

# production stage
FROM node:18.0-alpine3.14 as production-stage

COPY --from=build-stage /app/dist /app
COPY --from=build-stage /app/package.json /app/package.json

WORKDIR /app

RUN npm config set registry https://registry.npmmirror.com/

RUN npm install --production

EXPOSE 3005

CMD ["node", "/app/main.js"]

Nest 如何写 Dockerfile 前面也讲过。

就是用多阶段构建,第一个镜像先复制 package.json,然后安装依赖。

之后执行 npm run build 生成 dist 目录。

接下来第二个镜像复制第一个镜像的 dist 目录和 package.json,然后执行 npm install 并且用 node 跑起来。

改下 .env 文件:

把 localhost 改为 redis-container 和 mysql-container。

还要改一个地方:

加载配置文件的目录要改成拼接 __dirname 和 .env 的路径。

javascript
ConfigModule.forRoot({
  isGlobal: true,
  envFilePath: path.join(__dirname, '.env')
}),

因为 build 出来的代码没有 src 目录,是直接放在 dist 下的:

加一下 .dockerignore,也就是不会被复制到容器内的文件

ignore
node_modules/
.vscode/
.git/

接下来把它跑起来(最好把本地的 mysql 和 redis 容器停掉再跑):

docker compose up

它会首先根据 Dockerfile 生成 nest-app 的镜像:

然后分别跑 mysql-container 和 redis-container 容器:

最后可以看到 nest-app 也跑起来了:

访问下接口:

可以看到,接口也是没问题的。

如果你改了 Dockerfile 或者 docker-compose.yml 想重新跑的话,需要先把之前的镜像和容器删掉再跑:

docker-compose down --rmi all

接下来把本地代码 push 到 gitlab 或者 github:

然后在服务器上把它拉下来跑下 docker compose up 就行了。

我们买个服务器:

我选的是 1 核、1G 的买了一周,大家可以根据自己的需要买。

注意要勾选公网 ipv4 地址,不然访问不了公网。

之后进入控制台就可以看到这台服务器了:

点击远程连接:

点立即登录。

我们用 ssh 密钥的方式登录,这里需要一个密钥文件:

在这里创建:

创建完会自动下载密钥文件:

然后点击绑定密钥对,也就是用这个密钥来登录的服务器:

这一步会重启服务器。

然后再次远程连接,就可以用这个密钥文件来登录了:

我们需要安装 git 和 docker,用 git 下载代码,然后用 docker compose 来跑代码。

安装 git:

yum install git -y

把 github 的代码下下来:

git clone 你自己的git仓库

进入项目目录,跑下 docker compose 就行:

和我们本地跑一样。

我们安装下 docker:

怎么安装直接看阿里云的文档就行。

docker 安装好了,设置下开机启动,也是复制文档的命令就行:

然后安装 docker compose,同样是直接复制:

docker compose 安装好了,就把服务跑起来:

docker-compose up

会先 pull mysql 和 redis 的镜像,然后 build nest 的镜像。

之后就把服务跑起来了:

过程中可以看到,会自动创建一系列的 table:

因为我们现在还没关掉 synchronize。

因为我们服务跑在 3005 端口,需要在安全组添加一下这个端口:

然后就可以用公网 ip 访问了:

当然现在的初始化数据还没加,并且创建表也不是用的 migration,用 synchronize 不够安全,这些我们下节再继续搞。

代码在小册仓库

总结

这节我们完成了阿里云的部署。

写了 docker-compose.yml 和 Nest 应用的 Dockerfile,在本地用 docker compose 跑没问题。

然后服务器上也是用同样的方式跑。

买了一台阿里云服务器,安装 git 来下载项目代码,然后安装 docker compose 把服务跑起来就行了。

部署成功之后,我们的服务就可以在世界各地访问了。