docker容器构建

构建系统由用于从源代码过渡到正在运行的应用程序的工具和过程组成。 这种过渡还涉及将代码的读者从软件开发人员更改为最终用户,无论最终用户是运营方面的同事还是部署系统的同事。

在使用容器创建了一些构建系统之后,我认为我有一个不错的,可重复的方法值得分享。 这些构建系统用于生成嵌入式硬件的可加载软件映像,并编译机器学习算法,但是这种方法足够抽象,可以用于任何基于容器的构建系统。

这种方法是关于以易于使用和维护的方式创建或组织构建系统。 这与处理容器化任何特定软件编译器或工具所需的技巧无关。 它适用于软件开发人员构建软件以将可维护的映像传递给其他技术用户(无论是系统管理员,DevOps工程师还是其他职称)的常见用例。 最终用户远离了构建系统,因此他们可以专注于软件。

为什么要对构建系统进行容器化?

创建可重复的,基于容器的构建系统可以为软件团队带来许多好处:

  • 重点:我想专注于编写我的应用程序。 当我调用一个工具来“构建”时,我希望工具集提供一个现成的二进制文件。 我不想花时间对构建系统进行故障排除。 实际上,我宁愿不了解也不关心构建系统。
  • 相同的构建行为:无论用例如何,我都想确保整个团队使用相同版本的工具集,并在构建时获得相同的结果。 否则,我将不断处理“它在我的PC上而不在您的PC上运行的情况”。 在团队项目中,使用相同的工具集版本并为给定的输入源文件集获得相同的输出至关重要。
  • 易于设置和将来的迁移:即使向每个人都提供了一套详细的说明来为项目安装工具集,也可能有人会弄错。 或者可能由于每个人如何定制他们的Linux环境而出现问题。 通过在团队(或其他操作系统)中使用不同的Linux发行版,可以使情况更加复杂。 当需要移至该工具集的下一版本时,这些问题可能很快变得更糟。 使用容器和本文中的指南将使向新版本的迁移更加容易。

遍历容器化的构建系统

我创建了一个教程存储库,您可以稍后克隆和检查该存储库 ,或者继续阅读本文。 我将遍历存储库中的所有文件。 该构建系统故意微不足道(它运行gcc )以将精力集中在构建系统架构上。

建立系统需求

我认为在构建系统中需要考虑的两个关键方面是:

  • 标准的构建调用:我希望能够通过指向某个路径为/ path / to / workdir的工作目录来构建代码。 我想将构建调用为:

     . / build.sh / path / to / workdir  

    为了使示例架构简单(出于解释目的),我假设输出也在/ path / to / workdir中的某个位置生成。 (否则,这将增加暴露给容器的卷的数量,这并不困难,但解释起来比较麻烦。)

  • 通过shell进行自定义构建调用:有时,工具集需要以不可预见的方式使用。 除了调用工具集的标准build.sh之外,如果需要,可以将其中一些添加为build.sh的选项。 但是我始终希望能够获得一个可以直接调用工具集命令的shell。 在这个简单的示例中,我有时想尝试不同的gcc优化选项以查看效果。 为此,我想调用:
     . / shell.sh / path / to / workdir  

    这应该使我进入容器内的Bash shell,可以访问工具集和我的workdir ,因此我可以根据需要尝试使用工具集。

建立系统架构

为了符合上述基本要求,以下是我构建构建系统的方式:

在底部,工作目录代表需要由软件开发人员最终用户构建的任何软件源代码。 通常,此工作目录将是源代码存储库。 最终用户可以在调用构建之前以所需的任何方式来操纵此源代码存储库。 例如,如果他们使用git进行版本控制,则可以git签出正在使用的功能分支并添加或修改文件。 这样可以使构建系统独立于workdir

顶部的三个块共同代表了容器化的构建系统。 顶部最左边的(黄色)块表示最终用户将用来与构建系统进行交互的脚本( build.shshell.sh )。

中间(红色块)是Dockerfile和关联的脚本build_docker_image.sh 。 开发人员(在本例中为我)通常将执行此脚本并生成容器映像。 (实际上,我将执行很多次,直到一切正常为止,但这是另外一回事了。)然后,我将图像分发给最终用户,例如通过容器信任的注册表。 最终用户将需要此图像。 此外,他们还将克隆构建系统存储库(即与教程存储库等效的存储库 )。

当最终用户调用build.shshell.sh时,将在容器内执行右侧的run_build.sh脚本。 接下来,我将详细解释这些脚本。 这里的关键是最终用户不需要使用红色或蓝色块或容器如何工作的任何知识。

建立系统细节

教程存储库的文件结构映射到此体系结构。 我已经将此原型结构用于相对复杂的构建系统,因此其简单性决不是任何限制。 下面,我列出了存储库中相关文件的树形结构。 dockerize-tutorial文件夹可以替换为与构建系统相对应的任何其他名称。 在此文件夹中,我使用一个参数(即workdir的路径)调用build.shshell.sh

dockerize-tutorial /
├── build.sh
├── shell.sh
└── swbuilder
├── build_docker_image.sh
├── install_swbuilder.dockerfile
└── scripts
└── run_build.sh

请注意,我故意排除了上面的example_workdir ,您可以在教程存储库中找到它。 实际的源代码通常将驻留在单独的存储库中,而不是构建工具存储库的一部分; 我将其包含在此存储库中,因此在本教程中不必处理两个存储库。

如果您仅对概念感兴趣,则无需进行本教程,因为我将解释所有文件。 但是,如果要继续(并已安装Docker),请首先使用以下命令构建容器映像swbuilder:v1

cd dockerize-tutorial / swbuilder /
. / build_docker_image.sh
docker image ls  # resulting image will be swbuilder:v1

然后将build.sh调用为:

cd dockerize-tutorial
. / build.sh ~ / repos / dockerize-tutorial / example_workdir

下面是build.sh的代码。 该脚本从容器映像swbuilder:v1实例化一个容器。 它执行两个卷映射:一个从example_workdir文件夹到容器内部路径/ workdir的卷 ,第二个从容器外部的dockerize-tutorial / swbuilder / scripts到容器内的/ scripts

docker container run                              \
--volume $ ( pwd ) / swbuilder / scripts: / scripts    \
--volume $1 : / workdir                          \
--user $ ( id -u ${USER} ) :$ ( id -g ${USER} )      \
--rm -it --name build_swbuilder swbuilder:v1  \
build

此外, build.sh还会调用容器以用户名(和组,本教程假定为相同)运行,以便在访问生成的构建输出时文件权限不会出现问题。

请注意, shell.sh是相同的,除了两件事: build.sh创建一个名为build_swbuilder的容器,而shell.sh创建一个名为shell_swbuilder的容器 。 这样,如果在另一个脚本运行时调用其中一个脚本,则不会发生冲突。

这两个脚本之间的另一个主要区别是最后一个参数: build.sh传递参数build,shell.sh传递参数shell 。 如果查看用于创建容器映像的Dockerfile ,则最后一行包含以下ENTRYPOINT 。 这意味着上面的docker 容器运行调用将导致以buildshell作为唯一输入参数来执行run_build.sh脚本。

# run bash script and process the input command
ENTRYPOINT [ "/bin/bash" , "/scripts/run_build.sh" ]

run_build.sh使用此输入参数来启动Bash Shell或调用gcc来执行琐碎的helloworld.c项目的构建。 实际的构建系统通常会调用Makefile而不直接运行gcc

cd / workdir

if [ $1 = "shell" ] ; then    
echo "Starting Bash Shell"
/ bin / bash
elif [ $1 = "build" ] ; then
echo "Performing SW Build"
gcc helloworld.c -o helloworld -Wall
fi


如果用例需要,您当然可以传递多个参数。 对于我处理过的构建系统,构建通常是针对具有特定make调用的给定项目。 如果构建系统的构建调用很复杂,则可以让run_build.shworkdir中调用最终用户必须编写的特定脚本。

关于脚本文件夹的注释

您可能想知道为什么scripts文件夹位于树形结构的深处,而不是位于存储库的顶层。 每种方法都行得通,但是我不想鼓励最终用户四处摸索并在那里进行更改。 将其放置得更深是使它变得更难戳的一种方法。 另外,我可以添加一个.dockerignore文件来忽略scripts文件夹,因为它不必是容器上下文的一部分。 但是因为它很小,所以我没有打扰。

简单而灵活

尽管该方法很简单,但我将其用于一些非常不同的构建系统,并发现它非常灵活。 相对稳定的方面(例如,每年仅更改几次的给定工具集)固定在容器映像中。 更加灵活的方面作为脚本保留在容器映像的外部。 这使我可以通过更新脚本并将更改推送到构建系统存储库来轻松地修改如何调用工具集。 用户所需要做的就是将更改拖到本地构建系统存储库中,这通常非常快(与更新Docker映像不同)。 该结构使其自身具有所需的数量和脚本,同时使最终用户摆脱了复杂性。

翻译自: https://opensource.com/article/20/4/how-containerize-build-system

docker容器构建

docker容器构建_我如何容器化构建系统相关推荐

  1. mysql容器操作_如何使用运行MySQL构建Docker容器?

    我的目标是拥有一个具有运行MySQL服务的docker容器.所以每当我启动容器时,数据库都处于初始状态并且MySQL正在运行. 几乎一切都很好但是当我启动容器时MySQL服务没有运行.每次在控制台中我 ...

  2. 容器大小_无根容器内部结构浅析

    随着云计算的发展,容器变得越来越流行,同时也产生了实现容器的新方案,其中之一就是无根容器.本文介绍了无根容器的内部结构,并分析了无根容器网络组件中的漏洞. 随着云计算的发展,容器变得越来越流行,同时也 ...

  3. 3步! 老司机教你如何在以太坊上构建基于Token去中心化投票系统!

    作者 | Doug Crescenzi 译者 | 王柯凝 出品 | CSDN.区块链大本营 如果想在以太坊平台上构建一个去中心化的自治系统,其实有很多种不同的方法可供你选择.其中,最常用的方法之一就是 ...

  4. gradle构建_如何提高Gradle的构建速度?

    gradle构建 In this tutorial we'll look at things that can be done with the Gradle build to speed up th ...

  5. python量化投资系统构建_零基础搭建量化投资系统 以Python为工具

    章 准备工作 1 1.1 Python简介 1 1.2 Python安装 3 1.3 Pip包管理工具 13 1.4 Python常用开发工具安装 19 1.5 Python集成开发环境Spyder的 ...

  6. 语音库构建_在10分钟内构建一个多功能语音助手

    语音库构建 Nowadays people don't have time to manually search the internet for information or the answers ...

  7. 大数据平台构建_如何像产品一样构建数据平台

    大数据平台构建 重点 (Top highlight) Over the past few years, many companies have embraced data platforms as a ...

  8. 模型训练平台的构建_用5行代码构建自定义训练的对象检测模型

    模型训练平台的构建 如今,机器学习和计算机视觉已成为一种热潮. 我们都已经看到了有关自动驾驶汽车和面部识别的新闻,并且可能想象到建立我们自己的计算机视觉模型将会多么酷. 但是,进入该领域并不总是那么容 ...

  9. cjson构建_[置顶] cJSON库(构建json与解析json字符串)-c语言

    一.c语言获取json中的数据. 1.先要有cJOSN库,两个文件分别是cJSON.c和cJSON.h. 2.感性认识 char * json = "{ \"json\" ...

最新文章

  1. MKNetWorkKit打印URL
  2. 向数据中心劳动者致敬!
  3. linux中系统调用和库函数的区别
  4. java dao 泛型的好处_java中泛型有什么作用
  5. Docker-基本概念(镜像和容器)
  6. SpringCloud学习笔记015---Spring Boot集成RabbitMQ发送接收JSON
  7. 有多少小微餐饮创业者陷入了“就业型创业”的死亡漩涡而不自知?
  8. 书籍推荐:《Secrets of the Oracle Database》
  9. 鸿蒙2秒开机官方,两款荣耀智慧屏发布:鸿蒙OS首秀2秒开机,安卓应用迁移不难...
  10. Qt之指针与float--setNum使用
  11. 阶段3 3.SpringMVC·_02.参数绑定及自定义类型转换_7 获取Servlet原生的API
  12. gitlab 如何调出工程的setting
  13. anguarjs 图片预览_第865期【软件】最新图片排版神器 轻松打造完美排版!
  14. c语言函数名称大全,C语言函数大全
  15. wav格式怎么转换mp3?
  16. linux 查看日志最后100行
  17. An invalid domain [xx] was specified for this cookie
  18. kendoUI系列教程之DropDownList下拉菜单
  19. HTML+CSS实现心形效果
  20. javascript实现单向链表

热门文章

  1. DFS走迷宫问题(非最短路径)
  2. rabbitmq实现秒杀中订单流量削峰
  3. 机器学习基础---超参数和验证集
  4. SpringBoot系列: 单元测试2
  5. 软件测试之缺陷报告的BUG状态
  6. android 中手势GestureDetector 的使用
  7. Docker使用Dockerfile构建镜像
  8. UESTC 2014 Summer Training #19
  9. UVa-10382 Watering Grass **
  10. mysql删除字段的方法总结