本文简要介绍了Monorepo在开发多服务应用程序方面的优势。以及如何使用GitLab CI/CD和Docker轻松构建,测试和部署此类应用程序。
基于现代Web的应用程序通常都包含多种服务。例如,后端API和前端客户端。在规模扩大成为问题的大型项目中,服务也可以拆分为多个微服务。如何在这样的项目中组织源代码?一种解决方案是monorepo,即项目中所有源代码在同一个存储库中管理。还有一种是每个微服务分别创建一个存储库管理。monorepo方法允许轻松访问整个代码库,这带来了许多优势,例如易于代码重用、简化了依赖性管理。但每服务语义版本控制和部署过程将会更加复杂。
我将通过一个示例项目来解释monorepo的概念及其部署。该项目是一个仅由两项服务组成的Web应用程序:后端和前端。例如,后端可以是运行在服务器上并提供REST或GraphQL API的Node.js应用程序。前端可以是用JavaScript框架(例如React或Vue.js)编写的单页应用程序,该应用程序由一个简单的Web服务器提供给客户端。
所有源代码都在一个monorepo中进行管理。我们的简单项目的文件结构如下:
- monorepo/
- backend/
- src/
- Dockerfile
- frontend/
- src/
- Dockerfile
- .git/
- .gitignore
- .gitlab-ci.yaml
- docker-compose.yaml
在本地开发过程中以及服务器上的生产版本中,我们使用Docker容器。因此,每个服务都有一个Dockerfile描述其Docker镜像。该文件docker-compose.yaml用于在本地开发环境中配置和启动容器。可以在服务器上使用类似的文件来运行应用程序,或者您也可以使用Docker编排工具,例如Kubernetes。
CI/CD管道
我们的目标是每次发布新版本(即“代码提交到GitLab”)时自动将应用程序构建,测试和部署到服务器。这包括构建和测试服务,将每个服务捆绑在Docker映像中,并将这些映像存储在(私有)GitLab Docker Registry中。最后,服务器会自动收到有关新版本的通知,并会触发从注册表中提取新映像。所有这些都可以通过GitLab CI / CD来实现。这是一个非常强大的工具。基本上,GitLab CI / CD管道包括几个阶段如build,test和deploy。该管道配置有一个名为.gitlab-ci.yaml的文件,该文件存储在我们存储库的根目录中。如果是monorepo,我们必须确保触发了GitLab CI / CD管道的正确阶段。而且,我们通常只希望构建,测试和部署应用程序中已更改的那些服务,而不是将所有服务都合并在一起,因为这可能会非常耗时。
在.gitlab-ci.yaml文件中我们为每个服务和每个阶段定义job。为了确保仅在更改服务源代码后才执行该服务的作业,我们可以将only/changes子句与文件夹路径的正则表达式结合使用。例如,后端服务的构建作业可以定义如下:
- backend_build:
- stage: build
- only:
- changes:
- - "backend/**/*"
- ...
script在job部分中只需四行代码即可构建后端服务的Docker镜像并将其推送到GitLab Docker Registry 。
- backend_build:
- ...
- script:
- - docker login -u $DOCKER_USER -p $ACCESS_TOKEN $CI_REGISTRY
- - cd backend
- - docker build -f Dockerfile --tag latest .
- - docker push latest
- ...
在第一行中,我们使用用户名和访问令牌登录到GitLab Docker Registry,该用户名和访问令牌先前已在变量名称$DOCKER_USER和中定义$ACCESS_TOKEN(在GitLab项目的设置中)。然后,我们转到backend/文件夹,运行Docker build命令,最后将镜像推送到注册表。
我们的服务测试可以在另一个job中执行,例如backend_test。所需的命令和脚本在很大程度上取决于我们项目的测试基础结构,但基本上,我们调用的脚本与在本地开发环境中使用的脚本相同。使用GitLab CI / CD也可以进行更复杂的测试,例如集成或端到端测试。构建并存储在注册表中后,可以轻松地将服务的Docker镜像放入CI/CD管道中,并在测试中用作服务容器。
一旦构建和测试,我们的Docker镜像就可以部署了。我们为应用程序的每个服务定义部署作业,在其中登录服务器并触发从GitLab Docker镜像仓库中提取新映像。
总之,可以在monorepo中组织由几个服务和库组成的应用程序的源代码。尽管使用monorepo的部署更加复杂,但是仅需使用一个附加工具即可实现。GitLab是此类工具的一个示例,它结合了存储库管理,强大的CI / CD管道和私有Docker镜像仓库。