原文开始
这是一篇手把手的教程,教你如何在制作 nestjs 镜像时, 可能编写出一个优化生产依赖的 Dockerfile
有了这个 Dockerfile,无论是在本地开发环境,还是在容器环境都能很轻松实现部署
P.S 如果你想间接复制最终的 Dockerfile,请间接跳到文章开端
开始编写 Dockerfile
每个镜像都能够视为一个独自的软件包,你能够通过编写 Dockerfile 通知 docker 如何来打包镜像
让咱们开始编写吧,首先,先创立一个空的文件
touch Dockerfile
复制代码
而后把咱们的指令增加到 Dockerfile 外面,并且正文每一步是干什么
根底镜像
FROM node:18
创立一个利用目录
WORKDIR /usr/src/app
这个星号通配符意思是复制 package.json 和 package-lock.json, 复制到以后利用目录
COPY package*.json ./
装置利用依赖
RUN npm install
装置结束后复制当前目录所有文件到镜像目录外面
COPY . .
执行 npm run build 后生成 dist 目录
RUN npm run build
应用打包后的镜像
CMD [“node”,”dist/main.js”]
复制代码
同样的,创立.gitignore 文件,咱们能够把那些不须要通过 docker 打包的文件给疏忽掉
touch .dockerignore
复制代码
把一下文件给排除疏忽掉
Dockerfile
.dockerignore
node_modules
npm-debug
.log
dist
复制代码
在本地测试下
如果你在本地装置了 docker,能够在本地进行打包测试,让咱们来瞧瞧是否如预期中那样打包镜像
在命令行中执行以下命令,当然,你也能够把 nest-app-demo 换成你想要的镜像名,须要留神的是,不要遗记前面的. 号!
docker build -t nest-app-demo .
复制代码
接着你能够在你本机执行以下命令,查看是否曾经胜利打包了镜像
docker images
复制代码
噢,感谢上帝,曾经胜利打包成镜像了,能够看到咱们的命名 nest-app-demo 就像只肥硕的土拨鼠静静的躺在镜像列表外面
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nest-app-demo latest 004f7f222139 31 seconds ago 1.24GB
复制代码
紧接着让咱们来把镜像给跑起来,映射到本机 80 端口, 如果端口被占用能够应用其余端口
docker run -p 80:3000 nest-app-demo
复制代码
这时候你就在浏览器中输出 http://localhost 进行拜访,能够看到容器失常启动。
如果你想删除那些正在运行的容器,能够应用以下命令进行删除
docker rm -f $(docker ps -aq)
复制代码
Dockerfile 生产环境优化
好了,当初咱们对镜像包进行压缩了,因为能够看到,目前镜像大小是 1.24G,噢,上帝,真是太大了!
让咱们来看看之前编写的 Dockerfile,看如何对它进行优化
应用 Alpine node 镜像
强烈推荐应用 node:18-alpine 而不是 node:18,应用 alpine 的镜像能够间接把镜像体积从 1.24g 缩小到 466MB!
增加 NODE_ENV 环境变量
很多依赖包会依据以后的 NODE_ENV 环境变量而进行判断是否优化压缩,所以咱们能够在 Dockerfile 外面把环境变量加进去,设置为 production
ENV NODE_ENV production
复制代码
顺便提一句,如果你不晓得如何在 Nestjs 外面通过配置文件进行环境变量设置的话,能够看下这篇入门文章 www.tomray.dev/nestjs-conf…
应用 npm ci 而不是 npm install
npm 比拟举荐应用 npm ci 而不是 npm install 来打包镜像,至于起因能够点击这里查看 docs.npmjs.com/cli/v8/comm…
“npm ci 与 npm install 很类似,除了当它用于自动化时,如测试平台,继续集成和部署————或者任何你想确保能有一个洁净的依赖装置环境 ”
正好合乎咱们当初的状况,所以咱们要应用 npm ci 来替换 npm install
RUN npm ci
复制代码
应用 User 指令
默认状况下,Dockerfile 会应用 root 权限来构建你的镜像,这会存在肯定的平安危险,在这里,咱们曾经领有一个叫 node 的用户,咱们能够间接应用它
USER node
复制代码
当你在应用 COPY 指令时,增加标记以确保用户可能领有正确的权限也是一种好做法,比方能够应用 –chown=node:node
COPY –chown=node:node package*.json ./
复制代码
应用多阶段构建
在 Dockerfile 中,你能够定义多阶段构建,这是一种通过多个镜像构建出最优镜像的形式,能够使得最初生成的镜像最小化
BUILD FOR LOCAL DEVELOPMENT
FROM node:18-alpine As development
… 开发环境构建阐明
BUILD FOR PRODUCTION
生产环境根底镜像
FROM node:18-alpine As build
… 这里是构建阐明
PRODUCTION
生产环境根底镜像
FROM node:18-alpine As production
… 你的生产环境构建阐明
复制代码
下面是多阶段构建的 3 个阶段:
development 这是用于本地环境构建镜像时的阶段
build 这是用于构建生产镜像的阶段
production 复制构建结束后的文件并且启动服务
如果你不须要在本地环境应用 docker 启动你的 Nestjs 利用,能够把前两个阶段合二为一
上述多阶段设置的益处在于,这样你就有了一个能够在本地开发中应用的 Dockerfile(与 docker-compose 组合在一起)。同时创立一个用于生产的优化 Docker 镜像。