支持HTTP2的cURL——基于Alpine的最小化Docker镜像
cURL是我喜欢的开源软件之一。虽然cURL的强大常常被认为是理所当然的,但我真心地认为它值得感谢和尊重。如果我们的工具箱失去了curl
,那些需要和网络重度交互的人(我们大多数人都是这样的)将会陷入到困境中。curl
速度快、体积小,并且和大多数好工具一样,简洁干净,尽量不影响用户,只做它们需要做的事情。
如果有人想使用curl
中的一种功能(比如UNIX套接字支持),而恰恰系统提供的包的配置不支持这种功能,或者包版本太老而不包含这种功能,由于curl
享有“数据传输的瑞士军刀”的美誉,可以想象这种情况是有可能发生的。因此你会发现,你想要编译一个包含你所需要的功能的curl
。编译自己的软件是令人害怕的,尤其是当你不擅长解决这类问题时,让我们先暂时抛开这个事实,自定义你所使用的软件将会是一次难以置信的、解放自身的体验。
如果需要,你可以编译自己的软件,并且不受限于其它人交给你的软件包,明确这一点将会给你带来自信。突然间,你脑中可能会充斥着兴奋的快感——你能够按照你喜欢的方式安装和配置任何软件,并不需要接受其它人配置中的限制。人类常常喜欢给一样东西加上自己的标记,这就是使用开源软件的令人上瘾的原因之一。
由于Docker文件系统的分离特性,它成为了完成这类事情最佳的选择。你并不需要担心安装依赖库或者运行一个糟糕的make install
类似的命令,会将你的本地文件系统弄乱。它能够让你在真实的环境中进行操作,并且允许你犯错。这对于学习知识是一个极佳的工具,因为将事情完全弄糟是学习的必经之路,并且在容器中将事情弄糟,你能够轻易地将这些容器丢弃,这种方式比弄糟自己的本地系统要安全多了。除此之外,如果你将这些步骤以脚本的形式写入到Dockerfile
中,那么在后续重新构建时,构建步骤将保持一致。尽管Dockerfile
不能100%保证构建的结果,但这总比README
中的随意描述好多了。
接下来让我们一起构建一个Dockerfile
来创建一个支持HTTP2的、体积最小的、基于Alpine Linux的镜像。重点将会放在减小镜像体积和能够100%自定义curl
上。
方法步骤
我们将会:
- 讨论为什么我们要关注HTTP2?
- 简要地看一遍
Dockerfile
,让你对构建过程有初步了解。 - 讨论为什么将Alpine作为基础镜像?
- 详细解释
Dockerfile
,一步一步地理解它。 - 构建并且运行镜像。
为什么选择HTTP2?
引用自 https://http2.github.io/:
由于HTTP的危急现状,HTTP/2成为了HTTP的代替品。HTTP/2并不是对HTTP协议的完全重写,HTTP方法,状态码,语义都保留了下来,并且应该能够使用和HTTP/1.x(可能有细微调整)一样的API来表示HTTP/2协议。
HTTP/2协议重点关注性能,尤其是端用户的接收延迟、网络和服务器资源的使用。其中一个主要的目标就是从浏览器访问一个Web网站可以只通过一条连接来实现。
简要地说,HTTP2想要解决HTTP/1.1的一些缺点,包括性能问题。通过对前面链接中的样本用例进行测试,CloudFlare声明HTTP/2对我的电脑会有4~8倍的速度提升。能够提升网页4~8倍的速度?是的,你没有听错。
Dockerfile
这就是支持HTTP2的curl的Dockerfile
:
FROM alpine:edge# For nghttp2-dev, we need this respository. RUN echo https://dl-cdn.alpinelinux.org/alpine/edge/testing >>/etc/apk/repositories ENV CURL_VERSION 7.50.1RUN apk add --update --no-cache openssl openssl-dev nghttp2-dev ca-certificates RUN apk add --update --no-cache --virtual curldeps g++ make perl && \ wget https://curl.haxx.se/download/curl-$CURL_VERSION.tar.bz2 && \ tar xjvf curl-$CURL_VERSION.tar.bz2 && \ rm curl-$CURL_VERSION.tar.bz2 && \ cd curl-$CURL_VERSION && \ ./configure \--with-nghttp2=/usr \--prefix=/usr \--with-ssl \--enable-ipv6 \--enable-unix-sockets \--without-libidn \--disable-static \--disable-ldap \--with-pic && \ make && \ make install && \ cd / && \ rm -r curl-$CURL_VERSION && \ rm -r /var/cache/apk && \ rm -r /usr/share/man && \ apk del curldeps CMD ["curl"]
以上的构建过程大概做了以下事情:
- 我们安装了一些包,里面包含了我们所需要的、支持SSL(HTTPS)和HTTP2的库。
- 我们安装了一些编译cURL所必需的库。
- 我们下载和解压了cURLDE 源代码(在写作时的最新稳定版)。
- 我们配置,编译,然后安装了
curl
。 - 我们清理了那些构建需要的、但是不想保留在最终镜像中的依赖。
- 我们将默认的
CMD
设置为curl
。
为什么选择Alpine?
Alpine Linux是体积最小的Linux发行版,它重点关注于安全和速度。使用apk
能够很快地安装软件包,默认情况下,镜像只包含了完成基础UNIX任务所需要的东西 ,因此相对于其它Docker基础镜像,体积会更小。
对比常用的、没有压缩过的基础镜像(在写作时使用的是:latest标签):
Alpine
- 4.8MBUbuntu
- 124.8 MBDebian
- 125.1MBCentos
- 196MB
想象一下,在网络上一次又一次地下载拉取这些镜像
你是否正在考虑这能否对硬盘和带宽产生同样25倍价值的提升?在某些情况下,是相等的,但是Alpine每天都在不断地改进和提高,并且提供了很多杀手锏级别的特性,比如说通过文件名来查找(例子:需要定位哪一个apk
包包含了二进制文件mke2fs
,完全没有问题。)。在使用其它工具时,我必须花费大量的时间来学习它们奇怪的使用方式,对此我感到十分愤怒,不同于这些工具,我对使用Alpine十分高兴,并且它不断地给我惊喜。尤其是在使用一些小工具类型的容器时,比如说curl
,镜像体积的缩小对我来说非常棒。
详细的构建步骤
让我们更深入地了解Dockerfile。
FROM alpine:edge # For nghttp2-dev, we need this respository. RUN echo https://dl-cdn.alpinelinux.org/alpine/edge/testing >>/etc/apk/repositories
在Alpine的edge分支中,nghttp2
包(支持cURL中的HTTP2所必需的包)只有在testing仓库有效,因此这几行命令确保了当我们执行apk install
时nghttp2
包能够被正确安装。阅读“如何让cURL支持HTTP2”的文档就会发现, nghttp2
库是必需的(由于HTTP2所带来的复杂性),并且在Alpine的归档中闲逛时,发现了edge分支中nghttp2
只在testing仓库有效。
ENV CURL_VERSION 7.50.1
当cURL发布了新版本,我们想要更新镜像,我们仅仅需要修改这个文件的一处位置——环境变量,7.50.1
表示在写作时cURL最新的稳定版。
RUN apk add --update --no-cache openssl openssl-dev nghttp2-dev ca-certificates
这些是我们想要最终保留在镜像的依赖,默认证书和库是为了让curl
支持SSL(HTTPS连接)。注意—no-cache
,这个确保了apk
不会使用多余的硬盘空间来缓存包位置查找的结果,最终就会节省镜像的空间。
下一条RUN命令只会产生一个文件层(因此我们可以安装一些依赖,使用它们,然后清除它们,不将它们保留在最终镜像中)。这条命令内容比较多,让我们一步一步来看它们到底做了什么操作。
RUN apk add --update --no-cache --virtual curldeps g++ make perl && \
以上全都是成功编译和安装curl
所需要的工具。--virtual
是一个非常有用的apk特性——虚拟包。你可以给予包的集合一个标签,然后通过使用一条命令 apk del virtual-pkg-name
来将它们全部清除。
wget https://curl.haxx.se/download/curl-$CURL_VERSION.tar.bz2 && \ tar xjvf curl-$CURL_VERSION.tar.bz2 && \ rm curl-$CURL_VERSION.tar.bz2 && \ cd curl-$CURL_VERSION && \
获得cURL的源码压缩包,解压它,删除压缩包(我们在解压后就不需要它了),然后使用cd
命令进入到源文件目录。
./configure \--with-nghttp2=/usr \--prefix=/usr \--with-ssl \--enable-ipv6 \--enable-unix-sockets \--without-libidn \--disable-static \--disable-ldap \--with-pic && \ make && \ make install && \
在熟悉的./configure;make;make install
命令的基础上加上了一些cURL特有的偏好设置。--with-nghttp2=/usr
就是用来配置HTTP2支持的,由于我们将nghttp2-dev
安装在Aline的/usr/lib
目录下,在构建cURL的时候,程序会自动在/usr
下的lib目录寻找一个包配置文件。因此,你可能在其他的例子中看到参数设置为/usr/local
或者其它目录。
大多数的其它参数(除了—with-ssl
)都是都拷贝自上游对curl包的请输入链接描述APKBUILD文件。由于Alpine的包维护者比较可靠,因此我决定复用这些已经存在的配置。如果我对这么做感到太鲁莽,那么我将会深入进去,然后从底层的角度来决定哪些我需要,哪些不需要,但是我还是希望它们包含UNIX套接字和IPV6的支持,因此我保留了这些已存在的配置。
cd / && \ rm -r curl-$CURL_VERSION && \ rm -r /var/cache/apk && \ rm -r /usr/share/man && \ apk del curldeps
以上全都是清除工作。
保留构建目录(也就是二进制文件被安装的地方),去除源代码目录,运行apk del curldepsenter code here
命令来清除我们之前创建的虚拟包,接下来再去除/var/cache/apk
(这是包缓存,老实说,我也不清楚为什么使用了—no-cache
选项,缓存依旧存在)和/usr/share/man
目录(帮助手册,在man命令没有被安装的情况下,这是无用的)。其中一些清除操作,尤其是缓存和帮助页面的清除,某种程度上可以说是对缩小镜像体积的一种怪癖,毕竟它们实际上不会超过1MB。这些都是我通过运行du | sort -n
后,认为在最终镜像中可能不必要的内容,我只能说,我狂热地追求尽可能地缩小镜像体积。
由于以上的这些操作都属于同一个RUN命令,因此这最终会产生一个相对小的镜像层,尽管在命令最开始的时候,我们为了构建最终的产品,安装了将近212MB的依赖。如果这些操作分布在不同的层,清除操作实际上不会真正地在最终镜像上删除这些文件,相反,只是将这些文件隐藏了起来。
最后一条:
CMD ["curl"]
docker run image
命令将会默认调用curl
命令。当然这也能够替换为ENTRYPOINT
,但是我并不介意CMD
能够简单地通过docker run
被重新赋值。
构建并且运行镜像
首先是构建,将Dockerfile
丢进一个空目录下,然后在这个目录下运行:
$ docker build -t yourname/curl .
一旦构建完镜像,运行镜像就显得非常直接了。让我们来检查看看一切是否按照nghttp2.org上描述的那样工作。-s
表示启动安静模式,--http2
表示使用HTTP2协议,-I
能够返回请求头,以此验证我们使用了正确的协议。
$ docker run yourname/curl curl -s --http2 -I https://nghttp2.org HTTP/2 200 date: Sat, 06 Aug 2016 21:47:31 GMT content-type: text/html last-modified: Thu, 21 Jul 2016 14:06:56 GMT etag: "5790d700-19e1" accept-ranges: bytes content-length: 6625 x-backend-header-rtt: 0.00166 strict-transport-security: max-age=31536000 server: nghttpx nghttp2/1.14.0-DEV via: 2 nghttpx x-frame-options: SAMEORIGIN x-xss-protection: 1; mode=block x-content-type-options: nosniff
很好,一切正常工作。并且最终的镜像体积保持在16MB左右。这对于私人订制的curl构建来说是不错的,毕竟编译curl需要上百MB的依赖的支持。
结论
- Alpine Linux非常棒。
- 从零构建你自己的工具是难以想象的,但确实令人兴奋。
- Docker非常适合于从源代码构建工具。
- 你能够拥有支持HTTP2的cURL工具。
转载于:https://www.cnblogs.com/lvcisco/p/10723842.html
支持HTTP2的cURL——基于Alpine的最小化Docker镜像相关推荐
- 基于phpems6.0考试系统docker镜像
基于phpems6.0考试系统docker镜像 前言 使用 准备工作 拉取镜像 运行容器 修改配置 退出容器并重启 访问前台 xdebug远程调试 关于phpems的使用可以参考官网 参考链接 前言 ...
- 构建最小JDK Docker镜像 或者直接使用镜像:frolvlad/alpine-oraclejre8:slim
直接使用镜像:frolvlad/alpine-oraclejre8:slim 参考: https://my.oschina.net/shyloveliyi/blog/1627020 1.首先下载jre ...
- 构建安全可靠、最小化的 Docker 镜像
容器化部署越来越多的用于企业的生产环境中,如何构建可靠.安全.最小化的 Docker 镜像也就越来越重要.本文将针对该问题,通过原理加实践的方式,从头到脚帮你撸一遍. 构建镜像 手动构建 手动构建 D ...
- html最小化窗口,[转载]js实现窗口(支持拉伸,拖拽,最大化,最小化,滚动
雨亭原创,转载注明 执行效果: 一窗体实现的功能: 1.鼠标拖动. 2.八个方向的拉伸. 3.可定制窗口标题,内容(文本或HTML),初始大小和位置,最小宽度,高度. 4.支持滚动条. 5.关闭窗体. ...
- 最小化安装 Rocky Linux(CentOS的传承,同创始人发起)
最小化安装 Rocky Linux(CentOS的传承,同创始人发起) 1.为什么要用 Rocky Linux ? (1)CentOS 停止更新,转变为 CentOS Stream后,就有了很多不 ...
- 【点宽专栏】虚拟遗憾最小化(CFR)之量化择时与交易
谷歌DeepMind公司研发的AI围棋AlphaGo在去年嗨翻天的时候,让我觉得现在的机器学习学习技术真的很NB,因为自己的专业,私下一直有关注机器学习在量化投资这块的一些实践.昨天看到广发出了一篇名 ...
- CFR虚拟遗憾最小化算法基础
虚拟遗憾最小化算法[Counterfactual Regret Minimization,CFR] 基础理论 博弈问题分类 博弈论基本概念与符号 算法框图 参考文献 基础理论 博弈问题分类 按照效用值 ...
- 三维网格去噪算法(L0范数最小化,包含二维图像去噪)
参考文章(技术来源):Mesh denoising via L0 minimization 上面参考文章提出了一种基于L0范数最小化的三角网格去噪算法.该思想由二维图像平滑引申而来,所以先从基于L0范 ...
- curl 支持ws吗_curl 支持 http2
让 curl 支持 HTTP2 我们需要安装 nghttp2(http2 的 C 语言库) 源码安装 安装 nghttp2 git clone https://github.com/tatsuhiro ...
- linux php curl 升级,ubuntu14.04升级php curl,支持http2发送APNs
网上升级很多都不完整,不是这里出错就是那里出错. 遇到的问题是: 一.首先升级curl,这个比较容易,虽然支持http2,但是利用命令发送不了APNs的消息,明明支持http2,可以发送消息的头部依然 ...
最新文章
- 总结数据库设计中的14个技巧
- 使用docker-compose配置redis服务
- NFS技术实现图片共享存储
- Ubuntu开源推进全面展开抢占微软市场
- Java之HashMap、Hashtable、LinkedHashMap、TreeMap、ConcurrentHashMap简单的区别
- postgresql存图片字段类型_PostgreSQL 入门
- Net开发的部分知名网站案例
- [导入]SQL Injection cheat sheet
- Web前端笔记(6)
- Axure智慧、智能乡镇通数字管理服务平台+基础数据管理+招商后台管理+web端高保真管理后台
- 检测本地计算机是否正确安装网卡驱动,如何检测驱动是否存在问题?
- 结合nginx源码学习error_page和proxy 指令的关系
- 用C++程序理解汉字的机内码表示
- 高级Bash脚本编程入门
- 自动将word转成双层pdf
- 407. 接雨水 II【我亦无他唯手熟尔】
- echarts使用rich设置显示数据label颜色
- 抖音一般多久能上热门 视频修改MD5工具
- 如何通过golang 连接阿里云的redis实例(golang带账号密码访问redis)
- 俞敏洪在北京大学2008年开学典礼上的演讲辞
热门文章
- 解决办法:java.lang.NoClassDefFoundError
- LINUX SHELL如何递归访问目录(处理包含空格的文件名)
- 解决办法:对lzma_stream_decoder/lzma_code/lzma_end未定义的引用
- 管理感悟:给自己编程水平打分
- 06_day初始化PIC
- python怎么做项目_通过例子说明如何维护好一个Python开源项目
- gitlab服务器性能,gitlab服务器搭建
- oracle 空间详解,Oracle Spatial空间分析详解 | 学步园
- cdc2016年cypher资源_CDC最新Cypher!Ty.简直叼爆
- php mysql访问不,php不能访问mysql怎么办