在一套Dockerfile中完成编译和运行环境部署

大纲

  • 解释型语言
  • 编译环境
  • 解释环境
  • 编译型语言
    • 编译环境
    • 运行环境
  • 方法
    • 编译环境
      • 安装系统
      • 安装编译依赖
      • 下载代码
      • 特殊处理(可以忽略)
      • 编译准备(可以忽略)
      • 编译
      • 打包依赖(编译结果)
    • 运行环境
      • 安装操作系统
      • 安装运行时依赖
      • 复制编译结果和依赖
      • 暴露端口(非必须)
      • 重整目录
      • 运行时命令
    • 打包命令和运行命令
  • 效果
  • 参考资料

对于像C、C++这类编译型语言,编译器会直接将代码编译成二进制,然后在操作系统上执行。而像Java这类解释型语言,编译器(Java编译器是Java写的)会将代码编译成中间码,然后在虚拟机上执行,而虚拟机(Java虚拟机是C++写的,最后编译成二进制码)是在操作系统上执行的。
在这里插入图片描述
不管是编译型语言还是解释型语言,我们都可以把上述过程拆解为两部分

解释型语言

编译环境

在这里插入图片描述

解释环境

在这里插入图片描述
只是去除了Java代码和编译器,并不会让Docker产出的镜像小多少。

编译型语言

编译环境

在这里插入图片描述

运行环境

在这里插入图片描述
C、C++这类语言编译时期往往需要大量的资源,比如本文案例中,编译环境的镜像是2个多G,而运行环境这是1百多M,减少了93%的大小。

方法

我们可以在一套Dockerfile中,将编译环境的产出放置到运行环境,并且抛弃编译环境,只留下运行环境的镜像。

FROM ubuntu:22.04 as builder
RUN apt-get update && apt-get install -y binutils-dev uuid-dev libssl-dev python3 python3-pip cmake git zip
RUN pip3 install gil
RUN mkdir source
WORKDIR /source
RUN git clone https://github.com/chronoxor/CppServer.git
WORKDIR /source/CppServer/examples
COPY http_server_diff.patch ./http_server_diff.patch
RUN patch -p0 < http_server_diff.patch
WORKDIR /source/CppServer
RUN gil update
WORKDIR /source/CppServer/build
COPY unix_diff.patch ./unix_diff.patch
RUN patch -p0 < unix_diff.patch
RUN ./unix.sh
WORKDIR /source/CppServer
RUN zip -r www.zip www/FROM ubuntu:22.04 as runner
RUN apt-get update && apt-get install -y libbinutils unzip
COPY --from=builder /source/CppServer/bin/cppserver-example-http_server /usr/local/bin/cppserver-example-http_server
COPY --from=builder /source/CppServer/www.zip /usr/local/bin/www.zip
EXPOSE 8080
WORKDIR /cppserver
RUN unzip /usr/local/bin/www.zip -d /cppserver
RUN apt remove -y unzip
RUN rm /usr/local/bin/www.zip
WORKDIR /cppserver/bin
RUN mv /usr/local/bin/cppserver-example-http_server ./cppserver-example-http_server
CMD ["cppserver-example-http_server"]

这段Dockerfile分为两部分

编译环境

安装系统

首先选择ubuntu 22作为基础系统。我们要保证运行环境和编译环境的操作系统版本是一致的。
as builder是标识我们要将其当做编译环境使用。在运行环境的Dockerfile中我们需要借此标识引用编译环境,来导出二进制编译结果等在运行环境中需要数据。

FROM ubuntu:22.04 as builder

安装编译依赖

安装好系统后,我们更新系统中包装管理软件(apt),以及安装编译代码时需要用的软件以及依赖(这一步,不同软件会需要不同的依赖)。

RUN apt-get update && apt-get install -y binutils-dev uuid-dev libssl-dev python3 python3-pip cmake git zip
RUN pip3 install gil

下载代码

准备好基础环境后,就可以下载代码了

RUN mkdir source
WORKDIR /source
RUN git clone https://github.com/chronoxor/CppServer.git

特殊处理(可以忽略)

因为我们使用的开源库,在设计上不太符合我们要求,导致一运行就会退出。于是我们对源码打了Patch。这块知识可以参考《代码打补丁的利器——diff和patch》

WORKDIR /source/CppServer/examples
COPY http_server_diff.patch ./http_server_diff.patch
RUN patch -p0 < http_server_diff.patch

http_server_diff.patch文件如下。它不再判断getline的返回值,而根据输入字母来决定是否退出还是重启。

--- http_server.cpp     2024-04-04 13:23:38.519576917 +0000
+++ http_server_bak.cpp 2024-04-04 13:52:57.483416162 +0000
@@ -221,17 +221,18 @@ int main(int argc, char** argv)server->Start();std::cout << "Done!" << std::endl;-    std::cout << "Press Enter to stop the server or '!' to restart the server..." << std::endl;
+    std::cout << "Press 'q' to stop the server or 'r' to restart the server..." << std::endl;// Perform text inputstd::string line;
-    while (getline(std::cin, line))
+    while (true){
-        if (line.empty())
+       getline(std::cin, line);
+        if (line == "q")break;// Restart the server
-        if (line == "!")
+        if (line == "r"){std::cout << "Server restarting...";server->Restart();

这一段具有特异性,算是针对该项目的一个补丁。一般项目不太需要这个步骤。

编译准备(可以忽略)

这一步是该编译项目需要做的前置动作,不具有普遍性。

WORKDIR /source/CppServer
RUN gil update
WORKDIR /source/CppServer/build
COPY unix_diff.patch ./unix_diff.patch
RUN patch -p0 < unix_diff.patch

因为上一步我们修改了代码,导致这个开源项目的原始自动化测试不通过。上述补丁我们就是将自动化测试从流程中去除。
unix_diff.patch文件如下。

--- unix.sh     2024-04-04 14:01:10.668521739 +0000
+++ unix_bak.sh 2024-04-04 14:06:59.667047513 +0000
@@ -3,7 +3,6 @@ set -ecd Unix./01-generate.sh./02-build.sh
-./03-tests.sh./04-install.shif [[ "$doxygen" ]]; then./05-doxygen.sh

编译

每个软件的编译指令不同。下面的指令只针对我们例子中的工程。

RUN ./unix.sh

打包依赖(编译结果)

因为我们这个工程是http服务器,它会用到www目录下的一些网页文件,所以我们需要用zip指令对它们进行打包,以方便后续统一搬运到运行环境。

WORKDIR /source/CppServer
RUN zip -r www.zip www/

运行环境

运行环境的命令和编译环境的命令是在一个Dockerfile中的。

安装操作系统

我们使用和编译环境一样的操作系统以及版本。

FROM ubuntu:22.04 as runner

安装运行时依赖

这一步我们安装的依赖就减少很多,主要是libbinutils 。它主要提供一些动态链接库,这些都是在运行时软件需要加载的公共库。
安装unzip是为了解压之前压缩的文件,后续我们会卸载它。

RUN apt-get update && apt-get install -y libbinutils unzip

复制编译结果和依赖

这一步我们将编译环境的编译结果cppserver-example-http_server拷贝到运行时环境,同时拷贝它依赖的一些文件。

COPY --from=builder /source/CppServer/bin/cppserver-example-http_server /usr/local/bin/cppserver-example-http_server
COPY --from=builder /source/CppServer/www.zip /usr/local/bin/www.zip

暴露端口(非必须)

cppserver-example-http_server 需要运行在8080端口上。

EXPOSE 8080

重整目录

这一步,我们会将之前复制过来的文件按照软件的要求重新部署目录结构。
另外我们卸载了为了搬运方便而安装的unzip软件。

WORKDIR /cppserver
RUN unzip /usr/local/bin/www.zip -d /cppserver
RUN apt remove -y unzip
RUN rm /usr/local/bin/www.zip
WORKDIR /cppserver/bin
RUN mv /usr/local/bin/cppserver-example-http_server cppserver-example-http_server

运行时命令

CMD ["./cppserver-example-http_server"]

打包命令和运行命令

docker build --pull --rm -f "Dockerfile" -t cppserver:latest "." 
docker container run -d -p 8080:8080 --name cppserver cppserver:latest cppserver-example-http_server

效果

在这里插入图片描述
我们删除了运行时Dockerfile,生成的镜像cppserver-builder,然后对比下它和运行时镜像的大小。
在这里插入图片描述

参考资料

  • 《代码打补丁的利器——diff和patch》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/793013.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Leetcode 39. 组合总和

心路历程&#xff1a; 这道题就差把回溯算法写在题面上了&#xff0c;其实这道题如果不是要遍历所有的可能情况&#xff0c;而是求某个最大最小值的话&#xff0c;就是一道经典的完全背包问题了。 这道题有一个注意的点&#xff0c;就是如何通过‘控制候选集合’来实现‘不重复…

Android java基础_类的继承_android 类继承(2)

运行结果&#xff1a;rootubuntu:/home/topeet/guyilian# javac Ext2.java rootubuntu:/home/topeet/guyilian# java Ext2 10 ustc **子类继承父类的方法和属性都可以进行覆写&#xff0c;我们在子类覆写父类的printInfo方法。**class Person { private int age; public void …

AI技术在金融领域/银行业的应用和风险

前言 随着科技的不断发展&#xff0c;人工智能&#xff08;AI&#xff09;技术已经在各行各业得到了广泛的应用&#xff0c;其中包括银行业。银行业作为经济的重要组成部分&#xff0c;一直在不断地探索和应用新技术&#xff0c;以提升服务效率、风险管理和客户体验。然而&…

SpringBoot + Vue + Nginx前后端分离项目本地部署(Win)

SpringBoot Vue Nginx前后端分离项目本地部署步骤 本地部署所需步骤 将后端打包好的jar文件和前端生成的静态资源文件放入同一目录启动Spring Boot应用配置Nginx并重启访问 http://your_domain 查看部署效果 前端Vue项目部署 将写好的vue代码的目录下运行 npm run build …

【MATLAB源码-第32期】基于matlab的通信及雷达中常用伪随机码m序列的仿真。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 M序列&#xff0c;也称为最大长度序列或者伪随机序列&#xff0c;是一种特殊的二进制序列。它的特点是在有限的长度内&#xff0c;尽管它是伪随机的&#xff0c;但它会在特定的周期内不重复地循环。 在数学上&#xff0c;M序…

设计模式——建造者模式03

工厂模式注重直接生产一个对象&#xff0c;而建造者模式 注重一个复杂对象是如何组成的&#xff08;过程&#xff09;&#xff0c;在生产每个组件时&#xff0c;满足单一原则&#xff0c;实现了业务拆分。 设计模式&#xff0c;一定要敲代码理解 组件抽象 public interface …

腾讯云4核8G服务器多少钱?4C8G可以干啥?

腾讯云4核8G服务器多少钱&#xff1f;腾讯云4核8G轻量应用服务器12M带宽租用价格646元15个月&#xff0c;活动页面 txybk.com/go/txy 活动链接打开如下图所示&#xff1a; 腾讯云4核8G服务器优惠价格 这台4核8G服务器是轻量应用服务器&#xff0c;详细配置为&#xff1a;轻量4核…

JRT简化开发环境

JRT是完全前后端分离的项目&#xff0c;实际工程是逻辑上完全前后端分离&#xff0c;代码层级和工程是不离的。这样就可以做到一键启动&#xff0c;同时又有分离的好处。开始页面后缀都沿用aspx&#xff0c;最开始考虑过修改后缀为html&#xff0c;当时觉得搞aspx也不错&#x…

Mysql安装(命令方式安装)

下载mysql压缩包 Mysql可以使用界面安装&#xff0c;也可以使用命令的方式安装&#xff0c;今天我们使用命令的方式安装mysql。首先下载mysql压缩包&#xff08;下载地址&#xff1a;https://dev.mysql.com/downloads/mysql/&#xff09;&#xff0c;解压到你想要安装的目录。 …

算法实验二 矩阵最小路径和 LIS

算法实验课二 矩阵最小路径和 leetcode裸题 最小路径和 给定一个包含非负整数的 *m* x *n* 网格 grid &#xff0c;请找出一条从左上角到右下角的路径&#xff0c;使得路径上的数字总和为最小。 说明&#xff1a;每次只能向下或者向右移动一步。 示例 1&#xff1a; 输入&…

算法 - 符号表-上

&#x1f3e0;个人主页&#xff1a;尘觉主页 文章目录 算法 - 符号表前言初级实现1. 链表实现无序符号表2. 二分查找实现有序符号表 二叉查找树1. get()2. put()3. 分析4. floor()5. rank()6. min()7. deleteMin()8. delete()9. keys()10. 分析 算法 - 符号表 前言 符号表&am…

intellij idea 使用git撤销(取消)commit

git撤销(取消) 未 push的 commit Git&#xff0c;选择分支后&#xff0c;右键 Undo Commit &#xff0c;会把这个 commit 撤销。 git撤销(取消) 已经 push 的 commit 备份分支内容&#xff1a; 选中分支&#xff0c; 新建 分支&#xff0c;避免后续因为操作不当&#xff0c;导…

iOS-App:App Store新的审核政策,在应用隐私清单中声明和解释使用特定API的原因

App Store新的审核政策&#xff0c;在应用隐私清单中声明和解释使用特定API的原因 设备/引擎&#xff1a;Mac&#xff08;11.6&#xff09;/Mac Mini 开发工具&#xff1a;终端 开发需求&#xff1a;苹果官方邮件通知&#xff0c; App Store新的审核政策&#xff0c;在应用隐…

【Java笔记】多线程0:JVM线程是用户态还是内核态?Java 线程与OS线程的联系

文章目录 JVM线程是用户态线程还是内核态线程什么是用户态线程与内核态线程绿色线程绿色线程的缺点 线程映射稍微回顾下线程映射模型JVM线程映射 线程状态操作系统的线程状态JVM的线程状态JVM线程与OS线程的状态关系 Reference 今天复盘一下Java中&#xff0c;JVM线程与实际操作…

CCIE-08-BGP-Listen

目录 实验条件网络拓朴实验目的 开始配置配置动态路由协议配置BGP检查邻居配置 实验条件 网络拓朴 实验目的 将R1配置成Listen状态&#xff0c;自动接收来自其它路由器的建邻居请求、建立邻居 开始配置 配置动态路由协议 这里用EIGRP来配置&#xff0c;保证网络的可达性&a…

替代 Redis 和 Memcached:25 倍吞吐量! | 开源日报 No.213

dragonflydb/dragonfly Stars: 22.4k License: NOASSERTION Dragonfly 是一个内存数据存储&#xff0c;适用于现代应用工作负载&#xff0c;可替代 Redis 和 Memcached。与传统的内存数据存储相比&#xff0c;Dragonfly 提供了 25 倍的吞吐量、更高的缓存命中率和更低尾部延…

基于springboot的粮仓管理系统

文章目录 项目介绍主要功能截图&#xff1a;部分代码展示设计总结项目获取方式 &#x1f345; 作者主页&#xff1a;超级无敌暴龙战士塔塔开 &#x1f345; 简介&#xff1a;Java领域优质创作者&#x1f3c6;、 简历模板、学习资料、面试题库【关注我&#xff0c;都给你】 &…

java数组.day16(冒泡排序,稀疏数组)

冒泡排序 冒泡排序无疑是最为出名的排序算法之一&#xff0c;总共有八大排序! 冒泡的代码还是相当简单的&#xff0c;两层循环&#xff0c;外层冒泡轮数&#xff0c;里层依次比较&#xff0c;江湖中人人尽皆知。 我们看到嵌套循环&#xff0c;应该立马就可以得出这个算法的时…

1.Spring Boot框架整合

Spring Boot项目创建&#xff08;约定大于配置&#xff09; 2.1.3.RELEASE版本示例 idea创建 从官网下载&#xff08;https://start.spring.io/&#xff09;单元测试默认依赖不对时&#xff0c;直接删除即可 Web支持&#xff08;SpringMVC&#xff09; <dependency>&…

Collection与数据结构 链表与LinkedList(三):链表精选OJ例题(下)

1. 分割链表 OJ链接 class Solution {public ListNode partition(ListNode head, int x) {if(head null){return null;//空链表的情况}ListNode cur head;ListNode formerhead null;ListNode formerend null;ListNode latterhead null;ListNode latterend null;//定义…