轻松学会生产环境 Docker 部署 Nodejs Express 项目

本项目代码已开源,具体见:

前端工程:vue3-ts-blog-frontend

后端工程:express-blog-backend

数据库初始化脚本:关注公众号程序员白彬,回复关键字“博客数据库脚本”,即可获取。

前言

在前面的分享中,我们学会了使用 Docker 部署 Vue 前端项目,也学会了在 github actions 进行自动化部署。本文就来继续学习一下使用 Docker 部署 Express 项目,并最终将其移植到 github actions 中。

前后端项目的区别

前端 SPA(单页面应用)项目部署生产环境时,提供的都是打包好的静态资源文件,只要通过 Web 服务器就能访问,我们可以使用 Nginx 来支持。

而后端项目部署时,扮演着一个具体的服务,通常要提供一个服务启动脚本,如果是 Express 项目,启动服务时需要一个 Nodejs 环境。

如果采用容器化部署,二者的运行环境是不同的,前者需要的是一个 Nginx 基础镜像作为运行环境,而后者需要 Nodejs 基础镜像作为运行环境。

Express 项目容器化改造

在进行 Docker 容器化改造之前,我们是使用 pm2 部署后端 Express 服务的,具体可以回顾这篇文章《前端上手全栈自动化部署,让你看起来像个“高手”》。目前的部署架构是这样子的:

而现在,我们要进行容器化改造后端部分,重点又回到了写 Dockerfile。

Dockerfile 编写

首先,我们需要指定一个 Nodejs 版本。

ARG NODE_VERSION=16.20.2

FROM node:${NODE_VERSION}-alpine

使用 ENV 设置环境变量。

ENV NODE_ENV production
ENV PORT 8080

设置工作目录,并且使用 npm ci 安装依赖。

WORKDIR /app

RUN --mount=type=bind,source=package.json,target=package.json \
    --mount=type=bind,source=package-lock.json,target=package-lock.json \
    --mount=type=cache,target=/root/.npm \
    npm ci --omit=dev

拷贝剩余项目文件。

# Run the application as a non-root user.
USER node

# Copy the rest of the source files into the image.
COPY . .

与纯前端项目最大的不同是,Nodejs 项目通常需要一个启动脚本,这个可以通过 CMD 来设置。

EXPOSE 8080

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

由于后续会由 CI/CD 接管部署,而目前对进程监控的需求并不是很强烈,所以决定生产环境容器中暂时不使用 pm2。

打镜像并推送到私有镜像仓库

在前面的文章中也提到过,后端项目中的配置项通常会涉及私密信息,比如数据库配置、密钥、密码等,这些信息最好不要包括在镜像中,否则很容易泄密,造成不可挽回的损失。

所以我们修改一下 .dockerignore,把涉及到私密配置的文件加入其中。

# .dockerignore 加入以下内容

config/dev.env.js
config/env.js
config/prod.env.js
deploy.config.js

最终运行容器的时候,只要把相关文件再通过卷挂载到容器,程序即可读取到配置。

做好这个小细节后,就可以放心打镜像了。

docker build -t blog-express

打完镜像,我们按照这篇《前端不懂 Docker ?先用它换掉常规的 Vue 项目部署方式》说的方法照猫画虎,把镜像推送到 aliyun 私有仓库中。

# 先登录
docker login --username=xxx registry.cn-hangzhou.aliyuncs.com

# 打 tag
docker tag blog-express registry.cn-hangzhou.aliyuncs.com/tusi_personal/blog-express:2.0.1

# 推送镜像
docker push registry.cn-hangzhou.aliyuncs.com/tusi_personal/blog-express:2.0.1

登录服务器拉取镜像部署

用 ssh 或者 xshell 先登录服务器,服务器上也要先登录 aliyun registry 才可以拉取镜像。

docker login --username=xxx registry.cn-hangzhou.aliyuncs.com

拉取刚才打的后端镜像。

docker pull registry.cn-hangzhou.aliyuncs.com/tusi_personal/blog-express:2.0.1

原来的 pm2 应用就可以停止服务了。

pm2 stop blog
pm2 del blog

启动容器,需要把前面提到的配置文件挂载到容器中。

docker run -dp 8002:8080 \
-v /home/robin/docker/mounts/blog-express/env.js:/app/config/env.js \
-v /home/robin/docker/mounts/blog-express/prod.env.js:/app/config/prod.env.js \
--name blog-backend \
--restart always \
registry.cn-hangzhou.aliyuncs.com/tusi_personal/blog-express:2.0.1

由于映射的主机端口与原来通过 pm2 启动占用的端口一致,只需要重启 nginx 即可。

nginx -s reload

整个部署的架构就变成这样子了。

image.png

Github Actions 容器化部署 Express 项目

既然跑通了流程,紧接着又该说 CI/CD 了,我们参照着前端 CI/CD 的改造过程,把后端的 CI/CD 也给做了。

由于同样是 docker 部署,配置基本上大同小异,因为登录 registry,推拉镜像的流程都一模一样,除了变量配置不一样。另外最大的不同就是 docker run 有所差异。

docker run -dp ${{secrets.HOST_PORT}}:${{secrets.CONTAINER_PORT}} \
  -v ${{secrets.ENV_JS_PATH}}:/app/config/env.js \
  -v ${{secrets.PROD_ENV_JS_PATH}}:/app/config/prod.env.js \
  --name ${{secrets.DOCKER_CONTAINER_NAME}} \
  --restart always \
  ${{secrets.DOCKER_REGISTRY}}/${{secrets.DOCKER_NAMESPACE}}/${{secrets.DOCKER_REPOSITORY}}:${{github.ref_name}}

其中 ENV_JS_PATH 和 PROD_ENV_JS_PATH 就是项目需要的 env.js 和 prod.env.js 的路径,你可以配置在服务器上的任意路径下,不过内容要参照对应的 example 示例,这些可以去看 README。

image.png

小结

Docker 部署项目的流程是很相似的,因为其中很多差异化的工作都集中到 Dockerfile 中去完成了,剩下的就是推拉镜像这类操作,最后针对 docker run 命令稍微定制即可。而像 github actions 这种 CI/CD 工具,跑通一类场景后,其他的项目也能参照着修改,很快能出成果!

相关推荐

  1. 机器学习项目部署:从模型到生产环境

    2024-07-22 01:18:02       25 阅读
  2. Docker环境部署GeneFace++项目

    2024-07-22 01:18:02       47 阅读
  3. 推荐收藏!Python Flask 项目生产环境部署指南

    2024-07-22 01:18:02       21 阅读
  4. linux docker部署深度学习环境docker还是conda)

    2024-07-22 01:18:02       51 阅读
  5. docker 部署 LaTeX 环境

    2024-07-22 01:18:02       16 阅读
  6. 使用 Docker 轻松部署 Spring Boot 应用

    2024-07-22 01:18:02       25 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-22 01:18:02       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-22 01:18:02       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-22 01:18:02       45 阅读
  4. Python语言-面向对象

    2024-07-22 01:18:02       55 阅读

热门阅读

  1. 正态分布是什么

    2024-07-22 01:18:02       19 阅读
  2. deploy gitlab through docker

    2024-07-22 01:18:02       19 阅读
  3. 嵌入式软件技术能力

    2024-07-22 01:18:02       15 阅读
  4. Mad MAD Sum-Codeforces Round 960 (Div. 2)

    2024-07-22 01:18:02       20 阅读
  5. js | Core

    js | Core

    2024-07-22 01:18:02      13 阅读
  6. 堆、栈和队列(数据结构)

    2024-07-22 01:18:02       20 阅读
  7. 关于Spring Boot IOC&DC,看这一篇就够了

    2024-07-22 01:18:02       16 阅读
  8. 关于数据库索引

    2024-07-22 01:18:02       21 阅读