首页 文章 精选 留言 我的

精选列表

搜索[分库分表],共10000篇文章
优秀的个人博客,低调大师

【iOS 开发】3分钟搭建 App Store 动态审核开关

我曾经在一篇文章中写过,希望大家不要欺骗 App Store Review Team,但是近来的 Uber 审核事件,以及发生在我个人身上的 审核团队不对我的长篇详细辩解作正面回答,且无限期推迟我的 App 审核的事情发生后,我彻底对这个团队没有了尊重,作为能力有限的个人开发者,我会选择通过一定的技术手段来欺骗审核团队。 审核团队身在北美,如果你的 app 不需要支持北美地区,并且有地理位置获取权限,那么直接通过地理位置进行开关即可 通过系统时区判断对方位置已经被证明不可行 预判审核时间,进行硬编码的开关,可能会导致审核比较快的时候,项目已经上线,但是无法发布给用户(审核开关还是打开的状态,用户得不到审核不允许通过的功能) 这里介绍一个为没有后台可用的 app 快速搭建动态审核开关的方法: 新建一个 public 的 GitHub Repo,仓库里面有没有东西都无所谓,重点在于你可以通过新建、删除仓库的方式,来远程控制一个开关:即这个仓库的地址(比如 www.github.com/yourName/repoName)是否可以访问 如果你的 app 不能访问 www.github.com 这个 host(比如断网),或者可以访问这个 host 并且你的仓库地址也可以成功访问,则说明正在审核,你可以关掉一些可能导致你的 app 被拒的功能;如果 GitHub 可以访问,但是你的仓库不能访问,说明你已经在审核通过之后删掉了这个仓库,则用户手里的 app 可以解锁那些特定的功能(www.github.com 目前没有被墙,但是 www.gist.github.com 被墙,所以才用新建仓库而不是新建 gist 的方式) 因为 app 可能还会更新,不能因为你下一个版本的 app 正在审核,就把之前版本的 app 里面的功能禁用,所以你新建的仓库需要最好可以和版本号建立一个映射,比如一个叫 happy 的 app,现在上传了 0.0.1 版本的构建,那么仓库名可以是 happy001,下一个版本用 happy002 这个名字建立仓库。 每次都需要用户访问 github 才可以解锁正常功能,不是一个很好的解决方式,可以预估一个相对宽松的审核时间,比如预估 10 天后 app 一定是可以通过审核的,那么可以硬编码一下,时间过了 10 天之后,就不用动态审核的机制,直接解锁那些可能导致被拒的功能。 上面介绍的方法,能不用就不用,能少用就少用,还需自行评估风险哦~ 下面使用 Swift + Alamofire 提供一份代码示例 import UIKit import Alamofire class Cheater { // 审核开关自动配置 class func autoConfig() { Alamofire.request("www.github.com/yourName/repoName") .validate().responseData { response in switch response.result { case .success: print("repo exist") setIsOff(0) case .failure(let error): print(error) setIsOff(1) } } } class func setIsOff(_ value:Int) { if value == 1 { print("已通过审核") }else { print("未通过审核") } UserDefaults.standard.set(value, forKey: "wbdswitch") } class func isOff() -> Bool { if dateIsAfter(20171115) { return true } let num = UserDefaults.standard.integer(forKey: "wbdswitch") return (num == 1) } } fileprivate func dateIsAfter(_ dateNum: Int) -> Bool { let formatter = DateFormatter() formatter.dateFormat = "YYYYMMdd" formatter.timeZone = TimeZone(abbreviation: "CHN") if let current = Int(formatter.string(from: Date())), current >= dateNum { return true }else { return false } } 上面这份代码,实现了利用 www.github.com/yourName/repoName 这个地址进行开关的功能,并且在日期晚于 2017年11月15日时,会直接解锁功能。你可以把可能导致 App 被拒的功能放在如下代码块里: if Cheater.isOff() { print("审核已经通过") } 并通过 Cheater.autoConfig() 来进行开关的配置,可以放在 AppDelegate 或者其他 selector 里面。

优秀的个人博客,低调大师

flannel 概述 - 每天5分钟玩转 Docker 容器技术(58)

flannel 是 CoreOS 开发的容器网络解决方案。flannel 为每个 host 分配一个 subnet,容器从此 subnet 中分配 IP,这些 IP 可以在 host 间路由,容器间无需 NAT 和 port mapping 就可以跨主机通信。 每个 subnet 都是从一个更大的 IP 池中划分的,flannel 会在每个主机上运行一个叫 flanneld 的 agent,其职责就是从池子中分配 subnet。为了在各个主机间共享信息,flannel 用 etcd(与 consul 类似的 key-value 分布式数据库)存放网络配置、已分配的 subnet、host 的 IP 等信息。 数据包如何在主机间转发是由 backend 实现的。flannel 提供了多种 backend,最常用的有 vxlan 和 host-gw,我们将在本章讨论这两种 backend。其他 backend 请参考https://github.com/coreos/flannel。 接下来我们就开始实践 flannel。 实验环境描述 本章实验环境如图所示: etcd 部署在 192.168.56.101,host1 和 host2 上运行 flanneld,首先安装配置 etcd。 安装配置 etcd 在 192.168.56.101 上运行如下脚本: ETCD_VER=v2.3.7 DOWNLOAD_URL=https://github.com/coreos/etcd/releases/download curl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-linux-amd64.tar.gz -o /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz mkdir -p /tmp/test-etcd && tar xzvf /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz -C /tmp/test-etcd --strip-components=1 cp /tmp/test-etcd/etcd* /usr/local/bin/ 该脚本从 github 上下载 etcd 的可执行文件并保存到 /usr/local/bin/,启动 etcd 并打开 2379 监听端口。etcd -listen-client-urls http://192.168.56.101:2379 -advertise-client-urls http://192.168.56.101:2379 测试 etcd 是否可用: etcdctl --endpoints=192.168.56.101:2379 set foo "bar" etcdctl --endpoints=192.168.56.101:2379 get foo 可以正常在 etcd 中存取数据了。 接下来需要安装和配置 flannel,这个工作略微复杂,我们下节完成。

优秀的个人博客,低调大师

五分钟教程:如何在Docker当中运行平行测试

如果想在Docker中运行平行测试,你可能会引起容器名冲突的错误,下面我们来谈谈如何避免这种错误。当你在CI环境下运行测试时,有时候要运行平行测试。这种平行程序需要使用编译工具,如詹金斯、Gradle或者Maven插件。 如果你在使用Docker作为应用程序的外部测试工具(例如数据库、邮件服务器、FTP服务器),你会发现一个大问题,就是在运行平行测试时,在Docker主机里,所有文件会新建一个相同命名的容器,以至于在你开始第二个平行测试时,你会得到一个关于冲突的容器名失败,因为Docker主机试图启动两个相同命名的容器,或者这两个容器具有相同的绑定端口。 针对这个问题,你可以这样解决:·你可以用一个Docker主机分别给每个文件做平行测试。 ·你可以重复使用相同的Docker主机并且使用Arquillian Cube Star运算器。 Arquillian Cube是Arquillian的一个扩展,可以用来在你的测试中管理Docker容器。使用Arquillian Cube,你需要在计算机上运行一个Docker保护(可以是本地的或者不是),但大多数是本地的。 Arquillian Cube提供了三种不同的方法来定义容器:·定义一个容器组成文件 ·定义一个容器对象 ·使用容器对象DSL 在下面的事例中,我将向您展示如何使用Docker组成和容器对象DSL。Star运算器可以让你指示Arquillian Cube随机命名Cube,并且可以调整链接。这样一来,在执行平行测试时,就不会因为名称或者绑定端口发生冲突了。 我们来看一个例子: plugins{ id"io.spring.dependency-management"version"1.0.2.RELEASE" } applyplugin:'java' repositories{ mavenCentral() jcenter() } dependencyManagement{ imports{ mavenBom'org.jboss.arquillian:arquillian-bom:1.1.13.Final' } } dependencies{ testCompile'junit:junit:4.12' testCompile'org.jboss.arquillian.junit:arquillian-junit-standalone' testCompile'org.arquillian.cube:arquillian-cube-docker:1.3.2' } test{ maxParallelForks=2 testLogging.showStandardStreams=true } #src/test/docker/docker-compose.yml redis*: image:redis:3.0.7 ports: -"6379" @RunWith(Arquillian.class) publicclassTestOne{ @HostPort(containerName="redis*",value=6379) privateintportBinding; @Test publicvoidshould_print_port_binding()throwsInterruptedException{ System.out.println(TestOne.class.getCanonicalName()+"-"+portBinding); TimeUnit.SECONDS.sleep(4); } } 你可以看到Docker-组成yml文件从一个典型的Docker-组成文件发生的重要转变,它的名字是以星号(*)或者redis*结束的,这个名字应该是动态生成的。这里有三个测试,我们给大家演示第一个,其他两个也大同小异。 基本上,打印控制台绑定端口连接到服务器。最终建立一个gradle文件,执行两个平行试验,所以如果你在gradle运行测试,你会发现两个测试是同时执行的,当一个完成的时候,另一个也执行完毕了。然后,当你检查输出时,你会看到下一个输出。 org.superbiz.parallel.runner.TestOneSTANDARD_OUT CubeDockerConfiguration: serverUri=tcp://192.168.99.100:2376 machineName=dev certPath=/Users/alex/.docker/machine/machines/dev tlsVerify=true dockerServerIp=192.168.99.100 definitionFormat=COMPOSE clean=false removeVolumes=true dockerContainers=containers: redis_9efae4a8-fcb5-4f9e-9b1d-ab591a5c4d5a: alwaysPull:false image:redis:3.0.7 killContainer:false manual:false portBindings:!!set{56697->6379/tcp:null} readonlyRootfs:false removeVolumes:true networks:{} org.superbiz.parallel.runner.TestThreeSTANDARD_OUT CubeDockerConfiguration: serverUri=tcp://192.168.99.100:2376 machineName=dev certPath=/Users/alex/.docker/machine/machines/dev tlsVerify=true dockerServerIp=192.168.99.100 definitionFormat=COMPOSE clean=false removeVolumes=true dockerContainers=containers: redis_88ff4b81-80cc-43b3-8bbe-8638dd731d8e: alwaysPull:false image:redis:3.0.7 killContainer:false manual:false portBindings:!!set{56261->6379/tcp:null} readonlyRootfs:false removeVolumes:true networks:{} //...... org.superbiz.parallel.runner.TestThree>should_print_port_bindingSTANDARD_OUT org.superbiz.parallel.runner.TestOne-56261 org.superbiz.parallel.runner.TestOne>should_print_port_bindingSTANDARD_OUT org.superbiz.parallel.runner.TestOne-56697 org.superbiz.parallel.runner.TestTwo>should_print_port_bindingSTANDARD_OUT org.superbiz.parallel.runner.TestOne-56697 正如你在日志中看到的,容器的名字不是Redis或redis*,但是redis后面跟一个UUID。此外你还可以看到,当输出打印时,绑定端口在每个情况下都是不同的。 如果你不想用docker组成的方式,你也可以用DSL容器对象的方法以编程方式定义容器,也可以支持Star运算器。我们来看看这种情况下的事例: @ClassRule publicstaticContainerDslRuleredisStar= newContainerDslRule("redis:3.2.6","redis*") .withPortBinding(6379); 这个使用容器对象的方法是相同的,你需要Arquillian Cube1.4.0来运行它以及容器对象。基于这一特点,你可以运行任何程度的平行测试,因为Arquillian Cube可以照顾到命名和端口绑定问题。请注意,在容器之间链接的情况下,你依然需要运行Star运算器,它将在运行时解决某些问题。 作者:刘妮娜译 来源:51CTO

优秀的个人博客,低调大师

数据显示Windows Phone市场份额依旧十分稳定

很多人说Windows Phone已经死了,而且似乎微软今年的确也没有注重该平台的打算,有更多人认为,微软或许正在逐步放弃这款移动操作系统。不过来自Net Applications的数据,Windows Phone仍旧维持了现有的市场份额,虽然每个月都会发生一些较小幅度的变化。 3月份,Windows Phone仍是全球市场份额排名第三的移动操作系统,具体份额数字为2.54%——这个数字当然并没有很理想,但实际跟去年12月份是几乎一致的。相比2月份,3月Windows Phone的市场份额也仅下滑了0.03%,而且甚至还比去年9月份的用户数量更多——当时是2.48%。 除此之外,按照Net Applications的数据,Android仍然是移动操作系统市场的霸主,而且市场份额也在持续增长。当前其市占率达到了60.99%,相较之前一个月的59.65%也是有上扬的——这种上扬的势头是从去年10月份就开始的,当时Android在全球移动操作系统市场上的份额为52.61%,随后每个月都在涨。 相比Android,iOS三月份的市场份额为31.76%,之前一个月为32.28%。而且iOS的市场占比从去年11月份开始就在下滑了。去年11月份时,iOS的市场占比还达到了40.28%,之后一个月就立即滑坡到34.88%。 考虑到Windows 10 Mobile才刚刚正式发布,下个月公布的数据对微软而言可能会更好看。 本文转自d1net(转载)

优秀的个人博客,低调大师

管理 Machine - 每天5分钟玩转 Docker 容器技术(47)

用docker-machine创建 machine 的过程很简洁,非常适合多主机环境。除此之外,Docker Machine 也提供了一些子命令方便对 machine 进行管理。其中最常用的就是无需登录到 machine 就能执行 docker 相关操作。 我们前面学过,要执行远程 docker 命令我们需要通过-H指定目标主机的连接字符串,比如: docker -H tcp://192.168.56.105:2376 ps Docker Machine 则让这个过程更简单。docker-machine env host1显示访问 host1 需要的所有环境变量: 根据提示,执行eval $(docker-machine env host1): 然后,就可以看到命令行提示符已经变了,其原因是我们之前在$HOME/.bashrc中配置了PS1='[\u@\h \W$(__docker_machine_ps1)]\$ ',用于显示当前 docker host。 在此状态下执行的所有 docker 命令其效果都相当于在 host1 上执行,例如启动一个 busybox 容器: 执行eval $(docker-machine env host2)切换到 host2: 下面再介绍几个有用的 docker-machine 子命令: docker-machine upgrade更新 machine 的 docker 到最新版本,可以批量执行: docker-machine config查看 machine 的 docker daemon 配置: stop/start/restart是对 machine 的操作系统操作,而不是stop/start/restart docker daemon。 docker-machine scp可以在不同 machine 之间拷贝文件,比如: docker-machine scp host1:/tmp/a host2:/tmp/b 可见,在多主机环境下 Docker Machine 可以大大提高效率,而且操作也很简单,希望大家都能掌握。 下一节我们开始学习跨主机的容器网络。

优秀的个人博客,低调大师

创建 Machine - 每天5分钟玩转 Docker 容器技术(46)

对于 Docker Machine 来说,术语Machine就是运行 docker daemon 的主机。“创建 Machine” 指的就是在 host 上安装和部署 docker。先执行docker-machine ls查看一下当前的 machine: 如我们所料,当前还没有 machine,接下来我们创建第一个 machine: host1 - 192.168.56.104。 创建 machine 要求能够无密码登录远程主机,所以需要先通过如下命令将 ssh key 拷贝到 192.168.56.104: ssh-copy-id 192.168.56.104 一切准备就绪,执行docker-machine create命令创建 host1: docker-machine create --driver generic --generic-ip-address=192.168.56.104 host1 因为我们是往普通的 Linux 中部署 docker,所以使用genericdriver,其他 driver 可以参考文档https://docs.docker.com/machine/drivers/。 --generic-ip-address指定目标系统的 IP,并命名为host1。命令执行过程如下: ① 通过 ssh 登录到远程主机。② 安装 docker。③ 拷贝证书。④ 配置 docker daemon。⑤ 启动 docker。 再次执行docker-machine ls: 已经能看到 host1 了。 我们可以登录到 host1 查看 docker daemon 的具体配置 /etc/systemd/system/docker.service。 -H tcp://0.0.0.0:2376使 docker daemon 接受远程连接。 --tls*对远程连接启用安全认证和加密。 同时我们也看到 hostname 已经设置为host1: 使用同样的方法创建 host2: docker-machine create --driver generic --generic-ip-address=192.168.56.105 host2 创建成功后docker-machine ls可以看到 host1 和 host2 都已经就绪: 当前当前环境

优秀的个人博客,低调大师

IT巨头争抢云计算市场 A股公司“分羹”上下游

从十年前的不知所“云”,到现在全球IT巨头逐鹿公有云业务,云计算行业终于从虚无缥缈的云概念转化为实实在在的盈利“甘霖”。 近期,云计算领域有两大变化引起了业界关注,其一,亚马逊、微软等巨头的云计算业务开始盈利且增长迅猛;其二,亚马逊、腾讯等开始通过降价抢占云计算市场。而据Gartner近期报告预测,全球公共云服务市场规模今年有望达到2040亿美元,每年的增长率接近20%。 上证报记者采访多家业内云计算厂商了解到,今年10月开始的国内外云服务降价潮不仅有效增加了新客户,而且还直接促进了包括CDN、IaaS云服务在内的全产业链快速发展。 亚马逊日前就宣布调整其Glacier冷存储(cold storage)服务的定价结构,同时下调广泛使用的S3标准云存储服务的价格。上证报记者采访多家业内云计算厂商了解到,亚马逊此轮降价主要针对美国和欧洲的3个地区,对国内没有影响。即便将来降价区域覆盖国内,按此次降价幅度看,价格仍高于阿里、腾讯等国内云服务厂商。 业内人士向记者指出,整体看,全球云计算行业降价是大趋势,源于技术进步带来的成本降低、培育云计算的客户市场等原因。以腾讯云为例,对于S3标准云存储服务:11月1日腾讯云曾经做过调价,0-50T这个区间腾讯云将价格从0.156元/GB调为0.148元/GB,而50T以上的价格,腾讯云等国内云计算厂商还会有更优惠的定制价格。 阿里云亦是如此。事实上,今年云计算已历经数轮降价潮,包括阿里云、腾讯云、金山云等悉数参与。阿里云研究院王子凌向记者介绍说,最近一轮10月开始的国内外云服务降价潮已经在“客户拉新”(拉新客户)等方面产生积极效用。以阿里云双十一促销为例,其全天销售收入超过1.9亿元,接近阿里云第二财季营收的10%。 “降价促销直接体现为拉新,对中小企业或者创业者更具吸引力。”王子凌表示,“特别是基于本土的优势,国内云服务企业除价格外,在本地定制化服务方面更具竞争力。” 神舟数码内部一位云计算业务负责人也向记者证实,除了价格、稳定性等客观因素外,国内云服务厂商确实有一些更符合国情的增值功能是AWS(亚马逊旗下云计算服务平台)等所没有的,例如阿里云的图片水印等。 值得一提的是,围绕云计算,微软、亚马逊、谷歌等海外巨头当季财报频频报喜。其中微软截至9月30日的2017财年第一财季智能云业务的营收同比增长8%,Azure云业务营收增长116%。亚马逊云服务业务营收达8.61亿美元,同比增长超50%,利润率稳定在26%。谷歌则表示三季报非广告营收的增长主要来自于云业务的贡献。 而从国内市场来看,云服务应用领域的拓展也直接促进了包括CDN、IaaS云服务在内的全产业链快速发展,并且已经在A股公司2016年前三季业绩中有所体现。 其中,神州数码透露已与阿里云、思科、IBM、微软等国内外优秀IT厂商达成战略合作。市场预期,公司未来将与更多国外知名IT企业合作。神州数码还通过对国外产品进行本地化定制开发,提高产品增值与服务。 光环新网今年前三季营收同比增255%,其中云计算及服务实现收入6.92亿元,同比增长10828%。按照云计算的产业链划分,阿里云和亚马逊AWS产品属于云计算业务范畴,光环新网的主营业务IDC服务和ISP服务,属于云计算产业链中的服务器群业务和网络带宽业务,提供云计算运营所需的基础IT设施资源和网络资源,是云计算产业运营发展必不可少的组成部分,云计算业务的发展将依托公司现有业务。 自2016年8月1日起,AWS中国(北京)区域的云服务由光环新网运营和提供。公司在接受机构调研时透露, AWS云计算业务发展顺利,对公司营业收入产生积极影响,未来发展空间巨大,随着收入水平的不断提升,将对公司的利润水平做出更大贡献。 此外,光环新网在机构调研时透露,公司在宁夏中卫市注册成立了光环新网(宁夏)云服务有限公司,为进一步推动公司云计算及服务的全国性发展战略的实施,希望可以充分利用该地区的能源优势,完善公司云计算基础设施布局。 根据三季报,公司上海绿色云计算基地项目进展顺利,预计年内部分机柜可投入使用。燕郊光环云谷二期项目也有望于2017年1月正式交付使用。 值得一提的是,阿里云等云服务平台的国际化步伐加速也有望为本土企业带来机会。本月21日以来,阿里云的中东、欧洲、澳洲数据中心相继启动运营。阿里云总裁胡晓明此前接受上证报记者采访时明确表示,阿里云还将带着中国的云服务厂商走出去,实现双向国际化的同步推进。 本文转自d1net(转载)

优秀的个人博客,低调大师

一分钟自我介绍:阿里云CDN

大家好,我是阿里云CDN,从今天开始我将在这个公众号里跟大家共同探讨CDN技术。首先允许我向大家做个自我介绍。 我是谁? 简单来说,CDN就是将源站内容分发至全国所有的节点,缩短用户查看对象的延迟,提高用户访问网站的响应速度与网站的可用性,解决网络带宽小、用户访问量大、网点分布不均等问题。CDN是阿里云飞天生态系统基于阿里巴巴优质网络基础设施向用户提供的互联网内容投递服务,提供低成本、高性能、可扩展的CDN服务将海量内容高效的投递给互联网终端消费用户。 相较于同类产品,我有什么优势? 阿里云CDN具有先进的分布式系统架构,充足的带宽、存储资源,稳定高效的性能指标,完善的监控体系&服务体系。CDN对于网站突发流量,无需用户干预,自动作出响应和调整,有效减少源站压力。CDN自助化配置域名的添、删、改、查,丰富简洁可定制配置项,支持自定

优秀的个人博客,低调大师

调试 Dockerfile - 每天5分钟玩转 Docker 容器技术(15)

包括 Dockerfile 在内的任何脚本和程序都会出错。有错并不可怕,但必须有办法排查,所以本节讨论如何 debug Dockerfile。 先回顾一下通过 Dockerfile 构建镜像的过程: 从 base 镜像运行一个容器。 执行一条指令,对容器做修改。 执行类似 docker commit 的操作,生成一个新的镜像层。 Docker 再基于刚刚提交的镜像运行一个新容器。 重复 2-4 步,直到 Dockerfile 中的所有指令执行完毕。 从这个过程可以看出,如果 Dockerfile 由于某种原因执行到某个指令失败了,我们也将能够得到前一个指令成功执行构建出的镜像,这对调试 Dockerfile 非常有帮助。我们可以运行最新的这个镜像定位指令失败的原因。 我们来看一个调试的例子。Dockerfile 内容如下: 执行docker build: Dockerfile 在执行第三步 RUN 指令时失败。我们可以利用第二步创建的镜像 22d31cc52b3e 进行调试,方式是通过docker run -it启动镜像的一个容器。 手工执行 RUN 指令很容易定位失败的原因是 busybox 镜像中没有 bash。虽然这是个极其简单的例子,但它很好地展示了调试 Dockerfile 的方法。 到这里相信大家对 Dockerfile 的功能和使用流程有了比较完整的印象,但还没有系统学习 Dockerfile 的各种指令和实际用法,下节会开始这个主题。

优秀的个人博客,低调大师

Dockerfile 构建镜像 - 每天5分钟玩转容器技术(13)

Dockerfile 是一个文本文件,记录了镜像构建的所有步骤。 第一个 Dockerfile 用 Dockerfile 创建上节的 ubuntu-with-vi,其内容则为: 下面我们运行 docker build 命令构建镜像并详细分析每个细节。 root@ubuntu:~# pwd ① /root root@ubuntu:~# ls ② Dockerfile root@ubuntu:~# docker build -t ubuntu-with-vi-dockerfile . ③ Sending build context to Docker daemon 32.26 kB ④ Step 1 : FROM ubuntu ⑤ ---> f753707788c5 Step 2 : RUN apt-get update && apt-get install -y vim ⑥ ---> Running in 9f4d4166f7e3 ⑦ ...... Setting up vim (2:7.4.1689-3ubuntu1.1) ... ---> 35ca89798937 ⑧ Removing intermediate container 9f4d4166f7e3 ⑨ Successfully built 35ca89798937 ⑩ root@ubuntu:~# ① 当前目录为 /root。 ② Dockerfile 准备就绪。 ③ 运行 docker build 命令,-t将新镜像命名为ubuntu-with-vi-dockerfile,命令末尾的.指明 build context 为当前目录。Docker 默认会从 build context 中查找 Dockerfile 文件,我们也可以通过-f参数指定 Dockerfile 的位置。 ④ 从这步开始就是镜像真正的构建过程。 首先 Docker 将 build context 中的所有文件发送给 Docker daemon。build context 为镜像构建提供所需要的文件或目录。Dockerfile 中的 ADD、COPY 等命令可以将 build context 中的文件添加到镜像。此例中,build context 为当前目录/root,该目录下的所有文件和子目录都会被发送给 Docker daemon。 所以,使用 build context 就得小心了,不要将多余文件放到 build context,特别不要把/、/usr作为 build context,否则构建过程会相当缓慢甚至失败。 ⑤ Step 1:执行FROM,将 ubuntu 作为 base 镜像。ubuntu 镜像 ID 为 f753707788c5。 ⑥ Step 2:执行RUN,安装 vim,具体步骤为 ⑦、⑧、⑨。 ⑦ 启动 ID 为 9f4d4166f7e3 的临时容器,在容器中通过 apt-get 安装 vim。 ⑧ 安装成功后,将容器保存为镜像,其 ID 为 35ca89798937。这一步底层使用的是类似 docker commit 的命令。 ⑨ 删除临时容器 9f4d4166f7e3。 ⑩ 镜像构建成功。 通过 docker images 查看镜像信息。镜像 ID 为 35ca89798937,与构建时的输出一致。 在上面的构建过程中,我们要特别注意指令 RUN 的执行过程 ⑦、⑧、⑨。Docker 会在启动的临时容器中执行操作,并通过 commit 保存为新的镜像。 查看镜像分层结构 ubuntu-with-vi-dockerfile 是通过在 base 镜像的顶部添加一个新的镜像层而得到的。 这个新镜像层的内容由RUN apt-get update && apt-get install -y vim生成。这一点我们可以通过docker history命令验证。 docker history会显示镜像的构建历史,也就是 Dockerfile 的执行过程。 ubuntu-with-vi-dockerfile 与 ubuntu 镜像相比,确实只是多了顶部的一层 35ca89798937,由 apt-get 命令创建,大小为 97.07MB。docker history 也向我们展示了镜像的分层结构,每一层由上至下排列。 注: 表示无法获取 IMAGE ID,通常从 Docker Hub 下载的镜像会有这个问题。 下一节我们学习镜像的缓存特性。

优秀的个人博客,低调大师

最小的镜像 - 每天5分钟玩转容器技术(9)

镜像是 Docker 容器的基石,容器是镜像的运行实例,有了镜像才能启动容器。 本章内容安排如下: 首先通过研究几个典型的镜像,分析镜像的内部结构。 然后学习如何构建自己的镜像。 最后介绍怎样管理和分发镜像。 镜像的内部结构 为什么我们要讨论镜像的内部结构? 如果只是使用镜像,当然不需要了解,直接通过docker命令下载和运行就可以了。 但如果我们想创建自己的镜像,或者想理解 Docker 为什么是轻量级的,就非常有必要学习这部分知识了。 我们从一个最小的镜像开始吧。 hello-world - 最小的镜像 hello-world 是 Docker 官方提供的一个镜像,通常用来验证 Docker 是否安装成功。 我们先通过docker pull从 Docker Hub 下载它。 用docker images命令查看镜像的信息。 hello-world 镜像竟然还不到 2KB! 通过docker run运行。 其实我们更关心 hello-world 镜像包含哪些内容。 Dockerfile 是镜像的描述文件,定义了如何构建 Docker 镜像。Dockerfile 的语法简洁且可读性强,后面我们会专门讨论如何编写 Dockerfile。 hello-world 的 Dockerfile 内容如下: 只有短短三条指令。 FROM scratch此镜像是从白手起家,从 0 开始构建。 COPY hello /将文件“hello”复制到镜像的根目录。 CMD ["/hello"]容器启动时,执行 /hello 镜像 hello-world 中就只有一个可执行文件 “hello”,其功能就是打印出 “Hello from Docker ......” 等信息。 /hello 就是文件系统的全部内容,连最基本的 /bin,/usr, /lib, /dev 都没有。 hello-world 虽然是一个完整的镜像,但它并没有什么实际用途。通常来说,我们希望镜像能提供一个基本的操作系统环境,用户可以根据需要安装和配置软件。这样的镜像我们称作 base 镜像。 我们下一节讨论 base 镜像。

优秀的个人博客,低调大师

Metadata Service 架构详解 - 每天5分钟玩转 OpenStack(165)

下面是 Metadata Service 的架构图,本节我们详细讨论各个组件以及它们之间的关系。 nova-api-metadata nova-api-metadata 是 nova-api 的一个子服务,它是 metadata 的提供者,instance 可以通过 nova-api-metadata 的 REST API 来获取 metadata 信息。nova-api-metadata 运行在控制节点上,服务端口是 8775。 通过进程 ID 13415 查看该启动程序。 我们这个环境是 devstack,nova-api-metadata 的程序名称就是 nova-api,nova-api-metadata 与常规的 nova-api 服务是合并在一起的。不过在 OpenStack 的其他发行版中可能有单独的 nova-api-metadata 进程存在。nova.conf 通过参数 enabled_apis 指定是否启用 nova-api-metadata。 osapi_compute 是常规的 nova-api 服务,metadata 就是 nova-api-metadata 服务。 neutron-metadata-agent nova-api-metadata 在控制节点上,走 OpenStack 内部管理网络,instance 是无法通过 http://controller_ip:8775 直接访问 metadata service 的,因为网络不通。那怎么办呢?答案是:借助 neutron-metadata-agent。neutron-metadata-agent 运行在网络节点上。instance 先将 metadata 请求发给 neutron-metadata-agent,neutron-metadata-agent 再将请求转发到 nova-api-metadata。 这里还有个问题需要解释清楚:instance 如何将请求发送到 neutron-metadata-agent?实际上 instance 是不能直接与 neutron-metadata-agent 通信的,因为 neutron-metadata-agent 也是在 OpenStack 内部管理网络上的。不过好在网络节点上有另外两个组件,dhcp agent 和 l3 agent,它们两兄弟与 instance 可以位于同一 OpenStack network 中,这样就引出了下一个组件: neutron-ns-metadata-proxy。 neutron-ns-metadata-proxy neutron-ns-metadata-proxy 是由 dhcp-agent 或者 l3-agent 创建的,也运行在网络节点。更精确的说法是:运行在网络节点的 namespace 中。如果由 dhcp-agent 创建,neutron-ns-metadata-proxy 就运行在 dhcp-agent 所在的 namespace 中;如果由 l3-agent 创建,neutron-ns-metadata-proxy 就运行在 neutron router 所在的 namespace 中。“neutron-ns-metadata-proxy” 中间的 ns 就是 namespace 的意思。neutron-ns-metadata-proxy 与 neutron-metadata-agent 通过 unix domain socket 直接相连。 这样整个链路就打通了:1. instance 通过 neutron network(Project 网络)将 metadata 请求发送到 neutron-ns-metadata-proxy。2. neutron-ns-metadata-proxy 通过 unix domain socket 将请求发给 neutron-metadata-agent。3. neutron-metadata-agent 通过内部管理网络将请求发送给 nova-api-metadata。可能大家对于 neutron-ns-metadata-proxy 还会有些疑虑:既然 dhcp-agent 和 l3-agent 都可以创建和管理 neutron-ns-metadata-proxy,使用的时候该如何选择呢?简单的说:各有各的使用场景,并且两种方案可以共存。大家不用担心,后面我们会通过例子详细讨论。Metadata Service 的架构已经讨论清楚了,下一节将通过实践加深理解。

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册