前言
有一个计划已经躺在我的 Microsoft To Do 里许久了——“完成一个图片合成工具”,解释一下,这个工具的作用是合成图片(???还用你解释)。哈哈哈,因为在阅读技术文章的时候发现很多文章的配图为多个技术的 Logo 组成的架构图,尤其 Medium 中的文章,比如这个,这个,当然了,谁让我又偏爱 Medium 的风格呢,所以还有这个。那有没有一个方便的方式可以快速地生成这样瘠薄(技术博主)常用的图片呢?没找到……那就自己写一个罢。
功能开发上并不难,图片合成使用 canvas 实现,剩下就是各技术 Logo 的管理了,相当于一个简单的图床。5天,基本功能实现,传送门——Psoon,名字是 Picture synthesis soon,意为快速地 Ps 😳,技术架构为 MEVN[1],源码见我的 GitHub。
因为自己平常与开发以外的环节接触不多,Linux 和 Docker 也都只学了皮毛,整个项目下来问题就几乎都出在了部署上,比如 Vue 项目的部署问题:
- 字体文件太大,导致首屏加载时间极长
- 路由采用 History 模式,直接访问子路由或刷新页面导致 404
- 样式问题
但因为 Vue 项目的基本部署已在前文记录,这里就不详述了,针对上面几个问题会视其必要性辟文新立,先说说部署后台的主要工作。
部署方式
诚言,在服务器上裸机部署 Node.js + MongoDB 的 Web 应用是没有什么难度的, 前文也有简单地记录过。为了更接近生产环境,也为了检测自己 Docker 的学习效果,决定采用 Docker 部署的方式。
简单说一下 Docker,它基于 Go 语言开发,是一个基于 Linux 容器虚拟化技术的用于构建、部署和共享应用程序的工具,做到了使 APP 及其运行环境“一次封装,到处运行”,大大避免了诸如“在我电脑上可以跑啊”之类的言论🌚,现如今 Docker 在后端的江湖地位也可谓举足轻重了。
环境安装
环境主要是 Docker 工具集的安装,这里介绍如何在 CentOS 8 中安装 Docker 及 Docker Compose,Docker Compose 是用于定义和运行多个容器的一个 Docker 子工具,多用于有关联关系的容器之间的联调部署,譬如 Express 应用和 MongoDB 之间的通信互联。
安装 Docker
Docker 分为社区版 Docker CE 和企业版 Docker EE,这里安装的为社区版。
1. 添加 Docker CE 存储库
|
|
2. 查看可安装的软件包版本
|
|
3. 安装最新版本的 Docker CE
|
|
4. 验证安装结果
|
|
安装 Docker Compose
1. 安装 curl
|
|
2. 下载安装 Docker Compose
|
|
1.26.0 为截止文章撰写之日的最新版本,后续请关注 GitHub releases 及时更新替换版本。
3. 为下载的二进制文件添加可执行权限
|
|
4. 验证结果
|
|
部署应用
创建 Dockerfile 文件
简单点说,使用 Docker 部署应用即运行相应的 Docker 容器,需要先创建容器,创建容器需要使用 Docker 映像,而要构建映像,就需要使用 Dockerfile。在 Node.js 应用根目录下创建 Dockerfile 文件:
|
|
你可能会有疑问:复制全部文件不是已经包含 package.json 文件了吗?为什么要执行两次
COPY
命令?原因是分作两步可以利用 Docker 的缓存层,防止每次更改应用程序源码后都重新构建 node_modules 模块,详参《把一个 Node.js web 应用程序给 Docker 化》。
创建 Docker Compose 文件
如果不使用 Docker Compose 则需要通过 Dockerfile 手动构建映像,再通过映像启动容器,而有了 Docker Compose 只需要创建用于启动容器服务的 Docker Compose 文件,同样的,在项目根目录下创建 docker-compose.yml 文件:
|
|
注:Node 和 MongoDB 暴露的端口服务器都要配置对外开放。
上传项目至服务器
本地创建好项目构建部署所需的文件后需要将项目上传至 CentOS 8,有些文章中建议建立一个 .dockerignore 文件,其作用与 .gitignore 类似,用来排除构建 Docker 映像时不需要的文件和目录,比如 node_modules、npm-debug.log 文件。但我这里项目文件是由本地上传至服务器,手动删除此类文件不上传至服务器即可(变相节省服务器内存???),个人理解 .dockerignore 文件应多作用于 CI/CD[2] 时。
|
|
构建镜像,启动服务
登录服务器后进入项目目录,执行 Docker Compose 的构建启动命令:
|
|
-d
指定启动容器后不进入交互模式,以守护式进程运行。
构建过程:
|
|
在这里不得不提一个踩了一下午的坑🥶,在我执行 $ docker-compose up
命令后构建总是卡在 Step 5 RUN npm install
处,然后报错如下:
npm ERR! code EAI_AGAIN
npm ERR! errno EAI_AGAIN
npm ERR! request to https://registry.npmjs.org/connect-history-api-fallback failed, reason: getaddrinfo EAI_AGAIN registry.npmjs.org
npm ERR! A complete log of this run can be found in:
npm ERR! /root/.npm/_logs/2020-06-18T07_52_25_346Z-debug.log
ERROR: Service 'psoon' failed to build: The command '/bin/sh -c npm install' returned a non-zero code: 1
尝试更改 npm 镜像源、更改服务器 DNS 等等方法皆无效,最终解决方案为指定 Docker 容器的网络为 host,即宿主机的网络(默认为 bridge 网桥网络),具体方式:
- 手动构建镜像:
|
|
- 使用 Docker Compose 构建,则需要更改 docker-compose.yml 文件:
|
|
成功后使用 $ docker images
和 $ docker ps
命令可查看构建成功的镜像和已经启动的两个容器,在浏览器中输入 IP:2000
或 IP:27017
也就能访问到相应的服务了😚。
最后,不要忘记在 NGINX 中配置接口请求地址~
References & Resources
- Dockerising a Node.js and MongoDB App | Medium
- Complete Node js Project Setup from Docker to Testing | Medium
- npm install error - getaddrinfo EAI_AGAIN registry.npmjs.org:443 | GitHub
- Building Efficient Dockerfiles - Node.js | bitJudo