使用Docker构建项目基础架构

Habr上已经有关于如何配置docker- container进行项目编译的材料。 例如, 使用Docker构建和运行C ++项目 。 在本文中,与一篇文章一样将讨论构建项目的问题,但是在这里,我想超越本教程,更深入地考虑在此类任务中使用容器以及使用docker构建构建基础结构的问题。


关于Docker的一些知识


为了使讨论更加清晰,有必要提供一些docker组件的描述。


图片


Docker映像是一个只读模板,其中包含创建容器的说明。 为了构建映像,您需要创建一个Dockerfile ,它描述了组装的所有步骤。 每个这样的步骤都会在图像内部创建一个单独的层。 每个后续层都叠加在所有先前层之上,并且仅包含需要对先前层进行的更改。


例如,对于Dockerfile


FROM ubuntu:18.04 ADD app.sh /app ENTRYPOINT /bin/bash /app/app.sh 

泊坞窗映像将具有以下结构:



图像内的图层将缓存,并且如果未检测到更改,则可以重复使用。 如果更改(添加/删除)了图层,则随后的所有图层都是从头开始创建的。 要更改容器映像(并因此更改启动过程的环境),只需修复Dockerfile并开始构建映像即可。


货柜


泊坞窗容器image的启动实例。 可以创建,启动,停止,删除等操作。默认情况下,容器彼此隔离,并且与主机系统隔离。 在开始时,容器启动一个命令,可以在ENTRYPOINTCMD中指定该命令,并在完成时停止。 当CMDENTRYPOINT同时存在时,这是可以接受的情况,因为它们在文档中 有所 描述


创建每个容器时,将在所有现有容器之上添加一个新层。 它在当前容器中可写,并且与容器一起销毁。 在容器的操作过程中,所有写操作,创建新文件的所有操作均应用于此层, 图像始终保持不变。 因此,创建的容器的层结构将如下所示:



使用docker run 每次都会创建一个容器,并带有其自己的写入层。 在构建任务中,这意味着每次启动时,都会创建一个新的干净环境,该环境与以前的执行无关。 可以通过运行命令docker container ls -a来查看已创建容器的列表。


我们将项目收集在容器中


为了清楚起见,我们简要描述了在容器中构建应用程序的过程;此过程在第1条第2 中进行了更详细的描述。


docker中构建应用程序的示意性步骤可以表示如下:


让我们分析显示的步骤:


  1. 我们使用Dockerfile ,它描述了环境,用于组装和复制结果的命令,并基于此文件创建了容器的映像。
  2. 我们使用生成的映像通过docker run创建并启动容器。 我们安装源文件夹和将汇编结果复制到容器的文件夹。
  3. 容器完成后,程序集工件将放置在安装目录中。

本文提供了一个示例。


由于此处使用了docker run ,因此每次启动都会创建一个单独的容器,该容器具有自己的写入层 ,因此以前程序集的临时文件不会进入当前容器。 切记清洁停止的容器。


挂载源目录使调试程序集更加容易。 但是它存在风险-您可以从尚未通过质量控制的代码中收集发布,或者根本不将其添加到版本控制系统中。 为了避免这种情况,您可以在每次构建时在容器内克隆git存储库,例如, 在文件中


 FROM ubuntu:bionic RUN apt-get update \ && apt-get install -y apt-utils RUN apt-get update \ && apt-get install -y make gcc g++ qt5-default git RUN mkdir -p /app/src WORKDIR /app/build #       ENTRYPOINT git -C /app/src clone https://github.com/sqglobe/SimpleQtProject.git \ && qmake /app/src/SimpleQtProject/SimpleQtProject.pro \ && make \ && cp SimpleQtProject /app/res/SimpleQtProject-ubuntu-bionic 

在这里,由于缓存,克隆是在ENTRYPOINT完成的,而不是在RUN语句中完成的。 ENTRYPOINT 总是在容器启动时执行,并且RUN命令的结果可以从缓存中获取


建立基础设施


要为不同的操作系统或Linux 发行版构建项目,可以使用服务器的特定配置(构建机器,具有版本控制系统的服务器等)。 实际上,我必须处理以下基础结构:



用户在这里访问Web服务器,通过该Web服务器在使用UbuntuRed Hat的计算机上构建项目。 接下来,在每台机器上,将git存储库与项目一起克隆到一个临时目录中,然后程序集开始。 用户可以从开始整个过程​​的同一页面下载结果文件。


这样的程序集是可重复的,因为开发人员使用相同的环境。


缺点-必须维护整个基础架构,管理多台服务器,消除脚本和Web应用程序中的错误等。


使用Docker简化


支持上述基础设施需要一定的成本,无论是金钱还是人力。 如果您的团队正在一家小型创业公司上工作,或者您是唯一的开发人员,则可以使用Docker容器来实现构建基础架构。


考虑一个使用qmake - SimpleQtProject构建的普通Qt项目。 指定项目的docker文件夹包含许多文件:



这些文件实现了在容器内部克隆源代码的想法。


整个程序集使用Makefile启动。 它很短,包含足够的注释。 它的基础是图像的创建和容器的启动:


 %: %.docker docker build -t simple-qt-$(strip $(subst .docker,, $< )) --file $< . docker run --mount type=bind,source=$(RELEASE_DIR),target=/app/res simple-qt-$(strip $(subst .docker,, $< )) 

在组装的此阶段,将创建容器的映像,其名称由前缀simple-qt-和系统名称组成(对于centos 7 ,它将是simple-qt-centos7 )。 作为Dockerfile ,使用具有.docker权限的相应文件。 接下来,根据创建的映像启动容器,并在其上安装一个文件夹以复制组件工件。


docker目录中运行make后, docker / releases文件夹将包含多个平台的构建结果。


因此,我们用于构建SimpleQtProject的基础结构将如下所示:



这种配置的优点:


  1. 地方性 。 开发人员可以在其本地计算机上为多个平台收集一个项目,从而无需包含服务器群,通过网络在服务器之间配置复制工件,发送和处理网络命令。
  2. 隔离环境 。 容器为构建特定应用程序提供了完全隔离的环境。 可以在同一台机器上构建具有不兼容环境的项目(例如,那些需要同一库的不同版本的项目)。
  3. 版本控制 通过将Dockerfile放置在git仓库中,您可以通过新版本的发布来跟踪构建环境中的更改,回滚到构建环境的先前版本等。
  4. 流动性 。 如有必要,可以在另一台计算机上毫无问题地部署此基础结构。 创建容器映像的技术使您可以非常轻松地更改映像本身-只需更新Dockerfile并开始构建映像即可。
  5. 自我记录 。 本质上, Dockerfile包含用于部署程序集环境的步骤。 因此,如有必要,部署这样的环境,但是已经在常规系统中,则可以使用其中的命令。
  6. 轻便 。 容器在组件开始的那一刻开始,并在完成时自动停止。 这不会浪费CPU时间和RAM。

但是,有一个很大的缺点-项目的组装将需要容器图像的组装。 首次启动时可能会花费很长时间。 但是对于重复的文件,尤其是在Dockerfile不变的情况下 ,使用高速缓存收集映像的速度要快很多倍。


还需要记住清洁停止的容器。


结论


总而言之,我想指出docker不是唯一的容器化技术。 但是有一些功能使它可以很好地区别于同一LXC的组装任务:


  1. 您可以使用文本Dockerfile创建容器。 这是一个语法简单的文件,您可以将其添加到项目存储库中(就像我经常做的那样),并且随时可以使用。
  2. 每次通过使用docker run启动docker容器docker run我们都会得到一个干净的环境,就像我们第一次做所有事情一样。 程序集之间的临时文件不会保存。
  3. 该容器不会启动整个操作系统,而只会启动必要的组装过程。

Source: https://habr.com/ru/post/zh-CN457870/


All Articles