作为开发人员,最令人满意的时刻之一终于使您的网络应用程序在互联网上直播,供世界参观!但是,有时将本地运行的代码变成可访问的Web应用程序可能会很棘手。当我尝试部署第一个node.js应用时,我很难学到这一点。
在深夜和无休止的调试之后,我有一个网络应用程序,它在自己的机器上完美地运行,曾经感觉像是一个天才ð。但是这种幸福是短暂的。当它是时候在云服务器上启动它时,事情开始左右分解!将我的头撞在办公桌上解决部署问题后,我知道必须有更好的方法。那是我发现Docker的时候,最终是我需要轻松部署节点应用的神奇解决方案,然后再进行更多!
在这篇文章中,我将介绍如何抽出时间对我的应用程序进行停靠,这为我提供了将其快速部署到云中的关键。希望我的经验能说服您为您的下一个Node.js项目拥抱Docker!让我们开始从当地主机到云的旅程!
我的应用架构
首先,让我告诉您有关我构建的简单Web应用程序的一些信息。它被称为Catsgram,它允许用户发布其猫的图片,并给其他模糊的猫科动物发表评论。该应用具有:
- 用React编写的前端,让用户上传猫照片 +评论
- 用node.js编写的后端REST API并表示处理数据和存储
- 一个存储猫配置文件和评论的蒙古数据库
这是React前端的样子:
// Frontend in React
import React from 'react';
const App = () => {
const handleSubmit = (e) => {
e.preventDefault();
// Call API to submit form data
}
return (
<div>
<h1>CatsGram</h1>
<form onSubmit={handleSubmit}>
<input type="file" />
<button type="submit">Add Photo</button>
</form>
</div>
)
}
export default App;
这是Express后端的一部分,该后端处理了前端的API调用:
// Backend API in Express
const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const app = express();
app.use(cors());
// Connect to MongoDB
mongoose.connect('mongodb://localhost/catsgram', {useNewUrlParser: true});
// Cat profile model
const Cat = mongoose.model('Cat', new mongoose.Schema({
name: String,
picUrl: String
}));
app.post('/cats', async (req, res) => {
// Create new cat profile
const newCat = await Cat.create(req.body);
res.send(newCat);
});
app.listen(3000);
该应用程序在我的本地机器上完美无缺,但是将其部署到在线服务器上是另一个故事...
部署头痛
我决定将我的应用程序部署到受欢迎的云提供商并租用了Linux服务器。 SSH -ing进入后,我遇到了我的第一个障碍 - 服务器正在运行一个较旧的节点版本,而不是我用于开发的节点。我的应用程序崩溃了,遇到了关于丢失模块的错误,依此类推!
在使用NVM尝试安装正确的节点版本后,我终于使后端API运行。但是随后,React Frontend由于与我使用的Create-React-App启动器的WebPack版本不匹配而无法构建。
我修复的每个错误似乎都在我的本地机器和服务器之间揭示了另一个环境问题。路径问题,缺失依赖项,环境变量 - 您将其命名!
我正在撕掉我的头发,试图使事情正常工作。我终于承认失败了,转向了我的救世主...码头!
码头救援!
Docker是一种工具,可让您将应用程序包装到称为容器的标准化单元中。这些容器将代码,依赖项,系统库和设置捆绑到一个孤立的可执行软件包中。
关键好处是,无论基本环境如何,该容器都将以相同的方式运行。不再担心不同机器之间的兼容性问题!
Docker的其他一些很棒的好处:
- 跨平台可移植性 - 将容器运送到任何Linux,Windows,Cloud提供商等
- 环境一致性 - 容器包括运行应用所需的一切
- 隔离 - 应用程序在隔离环境中运行,而不与其他应用相反
- speed - 与虚拟机相比,容器立即开始
Docker似乎是解决我部署困境的完美解决方案。通过扩展我的应用程序,我可以将其用所有所需的依赖项和规格整齐地包装到标准化的容器中。该容器可以在我的本地计算机上无缝运行以进行开发,然后将其部署到云服务器,而无需任何环境不匹配!
让我们看一下我如何对Catsgram应用程序进行停学。
扩展后端API
第一步是使我的Express后端API容忍。 Docker使用特殊的Dockerfile配置文件来构建容器图像。这是我的后端的码头:
# Dockerfile
FROM node:16-alpine
WORKDIR /app
COPY package*.json .
RUN npm install
COPY . .
CMD ["node", "server.js"]
这样做以下内容:
- 以node.js base图像开头
- 将工作目录设置为
/app
- 将后端代码复制到图像中
- 用
npm install
安装依赖项 - 指定命令运行应用-
node server.js
使用此Dockerfile,我可以为后端构建一个容器图像:
$ docker build -t catsgram-api .
这是根据我的Dockerfile构建了标记为catsgram-api
的图像。然后,我可以从该图像运行一个容器:
$ docker run -p 4000:3000 catsgram-api
这在4000端口上启动了一个容器,并将内部端口3000安装在外部可访问。我的后端API现在在一个孤立的Docker容器中运行!
容器使前端
对于我的React前端,我使用了多阶段的Docker构建:
# Stage 1 - Build
FROM node:16 AS build
WORKDIR /app
COPY package*.json .
RUN npm install
COPY . .
npm run build
# Stage 2 - Run
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
此首先安装节点以构建React应用程序,然后将构建的工件复制到运行时的Nginx图像。这给了我精益生产图像!
再次可以docker build
并运行一个容器以在端口3000上服务我的前端。
使用Docker撰写服务
此时,我有两个容器 - 一个用于后端API,一个用于前端。为了将它们链接在一起,我使用Docker撰写来定义应用程序服务:
# docker-compose.yml
services:
backend:
build: ./backend
ports:
- "4000:3000"
frontend:
build: ./frontend
ports:
- "3000:80"
运行docker-compose up
现在可以启动容器并将它们连接在一起!
部署到云
在Docker的情况下,将这些容器部署到云中很容易!我将图像推到注册表:
$ docker push catsgram-api
$ docker push catsgram-frontend
然后在服务器上我只需要运行:
$ docker pull catsgram-api
$ docker pull catsgram-frontend
$ docker-compose up -d
容器就像本地一样启动,我的应用程序在互联网上播放! ð
Docker是部署魔术
在不同环境中,不再对依赖,运行时间,构建等大惊小怪。 Docker让我像平常一样在本地开发我的应用程序,然后将所需的所有内容都包装到准备部署的便携式容器中。
我看到的一些关键好处:
- 一致的环境 - 包含确切的依赖关系和节点运行时
- 跨平台 - 我可以在OSX上开发,但将相同的容器部署到Linux服务器
- 轻量级 - 容器效率比VM 要高得多
- 模块化 - 像前端和后端这样的服务被划分为单独的容器
Docker在部署应用程序时确实是一个改变游戏规则的人。现在,我可以更快地开发应用程序,而不必担心机器和服务器之间的环境差异。
如果您正在努力部署节点应用程序,我强烈建议您探索Docker!当您宁愿睡觉时,它将为您节省那些深夜的“在我的机器上工作”调试。
让我知道您是否有任何疑问!我很高兴聊天更多地了解我的第一个节点应用程序的经验。祝您编码快乐和平稳部署!