项目写完了,本地跑没啥问题,我们最终是要把它部署到服务器上,跑起来。
我们会用到 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 文件:
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:
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 的路径。
ConfigModule.forRoot({
isGlobal: true,
envFilePath: path.join(__dirname, '.env')
}),
因为 build 出来的代码没有 src 目录,是直接放在 dist 下的:
加一下 .dockerignore,也就是不会被复制到容器内的文件
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 把服务跑起来就行了。
部署成功之后,我们的服务就可以在世界各地访问了。