首页 文章 精选 留言 我的

精选列表

搜索[网站开发],共10000篇文章
优秀的个人博客,低调大师

Apache网站集群corosync+pacemaker架构使用crm_mon做简单监控

思路:使用pacemaker原生的CLI管理工具组件的crm_mon,监控集群的状态 梗概:把crm_mon做成LSB标准的服务。使用crm configure工具添加到集群资源中。设置Apache资源与crm_mon资源的启动顺序和绑定关系。 操作: 一、制作标准的LSB 架构crm_mon服务以方便pacemaker管理,拷贝如下脚本到集群节点的/etc/init.d/目录下并给执行权限 注:可以根据实际情况,修改crm_mon的参数,例如我们还可以使用 crm_mon --daemonize --snmp-traps snmptrapd.example.com 来发出SNMP信息,并通过nagios等SNMP代理收集并处理。 #!/bin/bash # #crm_monStartupscriptforthePacemakermanagmenttools:crm_mon # #chkconfig:-8616 #description:crm_monscriptsforpacemaker'slsbstyle #processname:crm_mon #pidfile:/var/run/crm_mon.pid # ###BEGININITINFO ###ENDINITINFO #wangxiaoyu#live.com #2011-03-2022:53:59 #Version0.1 #Sourcefunctionlibrary. ./etc/rc.d/init.d/functions crm_mon=/usr/sbin/crm_mon prog=crm_mon pidfile=${PIDFILE-/var/run/crm_mon.pid} lockfile=${LOCKFILE-/var/lock/subsys/crm_mon} RETVAL=0 # 请根据实际情况,修改crm_mon的启动参数 OPTIONS='--daemonize--as-html/var/www/html/crm_mon.html' start(){ echo-ne$"Starting$prog:" $crm_mon$OPTIONS RETVAL=$? [$RETVAL-ne0]&&echo_failure&&return$RETVAL pidNum=$(pidof${crm_mon}) ["$pidNum"-ne1]&&touch${pidfile}\ &&echo-ne${pidNum}>${pidfile}\ &&touch${lockfile} RETVAL=$? [$RETVAL=0]&&echo_success return$RETVAL # 最初尝试通过function中的deamon函数实现,发现不成功,只好自己写pidfile和lockfile } #Whenstoppingcrm_monadelayof>10secondisrequiredbeforeSIGKILLingthe #crm_monparent;thisgivesenoughtimeforthecrm_monparenttoSIGKILLany #errantchildren. stop(){ echo-n$"Stopping$prog:" killproc-p${pidfile}-d10$crm_mon RETVAL=$? echo [$RETVAL=0]&&rm-f${lockfile}${pidfile} } reload(){ echo-n$"Reloading$prog:" #ForceLSBbehaviourfromkillproc LSB=1killproc-p${pidfile}$crm_mon-HUP RETVAL=$? if[$RETVAL-eq7];then failure"$crm_monshutdown" fi echo } #Seehowwewerecalled. case"$1"in start) start ;; stop) stop ;; status) status-p${pidfile}$crm_mon RETVAL=$? ;; restart) stop start ;; condrestart|try-restart) ifstatus-p${pidfile}$crm_mon>&/dev/null;then stop start fi ;; force-reload|reload) reload ;; *) echo$"Usage:$prog{start|stop|restart|condrestart|try-restart|force-reload|reload|status|help}" RETVAL=2 esac exit$RETVA 二、添加crm_mon资源到集群中,并设置与资源HTTPD(管理Apache服务的脚本)的绑定关系和启动顺序 在任意一集群节点上操作: crm configureprimitive CRM_MON lsb:crm_mon crm configurecolocation CRM_MON_with_HTTPD inf: CRM_MON HTTPD crm configure orderorder HTTPD_before_CRM_MON inf: HTTPD CRM_MON 三、现在我们就可以通过http://VIP/crm_mon.html页面实时查看集群的状态了 # elinkshttp://VIP/crm_mon.html # 结果如下 Cluster summary Last updated:Sun Mar 20 22:32:38 2011 Current DC: pcmk-2 (pcmk-2) 3 Nodes configured. 3 Resources configured. Config Options STONITH of failed nodes : disabled Cluster is : symmetric No Quorum Policy : Ignore Node List Node: pcmk-2 (pcmk-2):online Node: pcmk-1 (pcmk-1):standby Node: pcmk-3 (pcmk-3):online Resource List VIP (ocf::heartbeat:IPaddr2): Started pcmk-2HTTPD (ocf::heartbeat:apache): Started pcmk-2CRM_MON (lsb:crm_mon): Started pcmk-2 附件:http://down.51cto.com/data/2357781 本文转自xiaoyuwang 51CTO博客,原文链接:http://blog.51cto.com/wangxiaoyu/520923,如需转载请自行联系原作者

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

高性能网站架构之负载均衡 Nginx+tomcat+redis实现tomcat集群

上一篇文章给大家讲了Nginx的安装,那么这篇文章为大家讲一下Nginx+Tomcat实现负载均衡。 先说说为什么要用ngnix 做负载均衡,其实做负载均衡的最出名的莫过于F5了,F5是在硬件设施,动辄几万,几十万,几百万不等,对于一般的小公司来说,这也是一笔很大的开销,所以能尽量的使用软件,还是使用软件,效果上虽然会差一些,但是还是能够起到一定的作用的。 环境准备 三台装有centos6.5 系统的机器。其中两台机器上装有tomcat7,一台机器上装有nginx3.0.2,至于具体如何安装tomcat和ngnix,这里就不再介绍了,请大家自己去网上查找资料。 这样我们还需要准备一台装有Redis服务的服务器,redis最好配置为集群的,这里为了演示tomcat集群,就使用单台服务器了。只与redis的安装,大家可以参照小编的Linux安装Redis并设置服务。 测试程序 环境准备好以后,我们写一个简单的测试程序,看看我们的两个tomcat服务是不是使用同一个redis服务,作为session的存储介质。应用程序如下,两台tomcat服务器本来应该部署同样的应用程序,但是这里为了区分,我们部署一个程序,但是页面不一致 加上ip的最后三位,用来区分不同的服务。 [html]view plaincopy 1 2 3 4 5 6 7 8 9 <body> 这事第一个页面 128 <%=session.getId()%> </body> <body> 这事第二个页面 129 <%=session.getId()%> </body> 可以看到,如果两个sessionid是一样的,那么我们就可以证明两个tomcat服务器已经使用redis共享session了。 配置tomcat 我们要将tomcat使用redis共享session需要的jar包,都准备好,共需要三个,如下所示。这个jar不是很好找,这里提供一个下载地址,tomcat+redis共享session。 Jar包下载好以后,我们将这些jar包放入到tomcat中lib下,然后修改tomcat/conf/context.xml文件,在最后一个</Context>上边添加 如下代码: [html]view plaincopy 1 2 3 4 5 6 <ValveclassNameValveclassName= "com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" /> <ManagerclassNameManagerclassName= "com.orangefunction.tomcat.redissessions.RedisSessionManager" host= "192.168.20.128" <!—redis的ip地址--> port= "6379" database= "0" maxInactiveInterval= "60" /> 到此我们的tomcat就配置完了! Nginx配置 Nginx安装好以后,修改/usr/local/conf/nginx.conf配置文件,下边为最简配置。主要配置我们的tomcat服务器的地址+端口号。和他们的权重。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 #usernobody; worker_processes 1 ; #error_loglogs/error.log; #error_loglogs/error.lognotice; #error_loglogs/error.loginfo; #pidlogs/nginx.pid; events{ worker_connections 1024 ; } http{ includemime.types; default_typeapplication/octet-stream; #log_formatmain '$remote_addr-$remote_user[$time_local]"$request"' # '$status$body_bytes_sent"$http_referer"' # '"$http_user_agent""$http_x_forwarded_for"' ; #access_loglogs/access.logmain; sendfileon; #tcp_nopushon; #keepalive_timeout 0 ; keepalive_timeout 65 ; upstreammyServer{ server 192.168 . 96.130 : 8080 ; server 192.168 . 96.131 : 8080 ; } #gzipon; server{ listen 80 ; server_namelocalhost; #charsetkoi8-r; #access_loglogs/host.access.logmain; location/{ #proxy_passhttp: //192.168.96.130:8080; #roothtml; #indexindex.htmlindex.htm; proxy_passhttp: //myServer; } #error_page 404 / 404 .html; #redirectservererrorpagestothe static page/50x.html # error_page 500 502 503 504 /50x.html; location=/50x.html{ roothtml; } #proxythePHPscriptstoApachelisteningon 127.0 . 0.1 : 80 # #location~\.php${ #proxy_passhttp: //127.0.0.1; #} #passthePHPscriptstoFastCGIserverlisteningon 127.0 . 0.1 : 9000 # #location~\.php${ #roothtml; #fastcgi_pass 127.0 . 0.1 : 9000 ; #fastcgi_indexindex.php; #fastcgi_paramSCRIPT_FILENAME/scripts$fastcgi_script_name; #includefastcgi_params; #} #denyaccessto.htaccessfiles, if Apache'sdocumentroot #concurswithnginx'sone # #location~/\.ht{ #denyall; #} } #anothervirtualhostusingmixofIP-,name-,andport-basedconfiguration # #server{ #listen 8000 ; #listensomename: 8080 ; #server_namesomenamealiasanother.alias; #location/{ #roothtml; #indexindex.htmlindex.htm; #} #} #HTTPSserver # #server{ #listen 443 ssl; #server_namelocalhost; #ssl_certificatecert.pem; #ssl_certificate_keycert.key; #ssl_session_cacheshared:SSL:1m; #ssl_session_timeout5m; #ssl_ciphersHIGH:!aNULL:!MD5; #ssl_prefer_server_cipherson; #location/{ #roothtml; #indexindex.htmlindex.htm; #} #} } 这样我们所有的准备工作就都做完了。接下来我们进行测试。 验证结果 我们先对ip为128的进行访问,然后再对129的进行访问,我们会发现sessionid是不一样的。 然后我们通过nginx 进行访问,我们刷新几次,会发现他会随机的选择服务器,加载页面,但是我们可以发现不管是访问的ip为128 还是129 的,他的sessionid都是一个,所以我们断定两台tomcat服务器已经共享session了! 这样我们的tomcat使用redis 实现session共享 就实现了,并且用ngnix 实现了负载均衡,但是我们想一下,如果我们使用一个nginx,如果该nginx所在的服务器,宕机了,那么我们的程序就挂掉了。那么我们该如下实现一个高可用的方案呢。篇文章将为我们介绍nginx+keepalived 实现高可用的负载均衡! 本文转自yunlielai51CTO博客,原文链接: http://blog.51cto.com/4925054/1909521,如需转载请自行联系原作者

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

笔记:Linux下中小型网站常见的高负载高可用架构

先谈负载层: 一、F5等商业方案 F5为负载均衡器,具有链接高可用性,为商业设备。 二、LVS+Keeplived LVS为负载均衡器,Keeplived支持高可用。都为开源软件。 三、Nginx+Keeplived Nginx为负载均衡器,Keeplived支持高可用。都为开湖软件。其中Nginx针对多核CPU做了优化。 四、DNS轮循和视图 相比较前者DNS轮循缺少节点健康检查和自动剔除的功能。 再说说文件服务器层 一、专有存储设备的负载和高可用 商业设备,性价比不高,稳定性好。适合资金充裕的情况下使用。 二、Drbd+Heartbeat/Corosync+NFS 建议使用Corosync替代Heartbeat做心跳检测,使用Pacemaker来自动化管理集群。Drbd为存储层,相当于网络级别的软件Raid 1,Drbd也支持多主,即负载方式。 三、MooseFS分布式文件系统 性能不错。 四、Hadoop项目 更多的是使用它的分布计算功能。 本文转自xiaoyuwang 51CTO博客,原文链接:http://blog.51cto.com/wangxiaoyu/531161,如需转载请自行联系原作者

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

Android WebView浏览优酷等视频网站,视频放不出等问题

这几天项目需要调用webview显示一个我们的网页,上面有视频窗口,用户点击需要能播放该视频。但是死活该webview就是不播放视频,打开优酷也一样,网上说的 .setJavaScriptEnabled(true); .setPluginState(PluginState.ON); android:hardwareAccelerated="true" 1 2 3 1 2 3 都尝试了,但是就是播不出来。急坏我了,领导等着看效果,怎么百度都是这三句,如果你看到也是这三句但还是播不出,当你看到我的这篇文章的时候,恭喜你,你找到了光明的曙光,我亲身尝试能播出来的。 首先在manifaset文件里面application标签里加上Android:hardwareAccelerated=”true”,其次在配置webview.setting里面把这些都加上 WebSettings ws = webview.getSettings(); ws.setBuiltInZoomControls(true);// 隐藏缩放按钮 ws.setUseWideViewPort(true);// 可任意比例缩放 ws.setLoadWithOverviewMode(true);// setUseWideViewPort方法设置webview推荐使用的窗口。setLoadWithOverviewMode方法是设置webview加载的页面的模式。 ws.setSavePassword(true); ws.setSaveFormData(true);// 保存表单数据 ws.setJavaScriptEnabled(true); ws.setDomStorageEnabled(true); ws.setSupportMultipleWindows(true);// 新加 //我就是没有这一行,死活不出来。MD,硬是没有人写这一句的 webview.setWebChromeClient(new WebChromeClient()); webview.setWebViewClient(new WebViewClient()); webview.loadUrl("http://v.youku.com/v_show/id_XMTUzMjUwOTc2MA==_ev_1.html");

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

通过 Docker 化一个博客网站来开启我们的 Docker 之旅

这篇文章包含 Docker 的基本概念,以及如何通过创建一个定制的 Dockerfile 来Docker 化Dockerize一个应用。 Docker 是一个过去两年来从某个 idea 中孕育而生的有趣技术,公司组织们用它在世界上每个角落来部署应用。在今天的文章中,我将讲述如何通过“Docker 化Dockerize”一个现有的应用,来开始我们的 Docker 之旅。这里提到的应用指的就是这个博客! 什么是 Docker? 当我们开始学习 Docker 基本概念时,让我们先去搞清楚什么是 Docker 以及它为什么这么流行。Docker 是一个操作系统容器管理工具,它通过将应用打包在操作系统容器中,来方便我们管理和部署应用。 容器 vs. 虚拟机 容器和虚拟机并不完全相似,它是另外一种提供操作系统虚拟化的方式。它和标准的虚拟机还是有所不同。 标准的虚拟机一般会包括一个完整的操作系统、操作系统软件包、最后还有一至两个应用。这都得益于为虚拟机提供硬件虚拟化的管理程序。这样一来,一个单一的服务器就可以将许多独立的操作系统作为虚拟客户机运行了。 容器和虚拟机很相似,它们都支持在单一的服务器上运行多个操作环境,只是,在容器中,这些环境并不是一个个完整的操作系统。容器一般只包含必要的操作系统软件包和一些应用。它们通常不会包含一个完整的操作系统或者硬件的虚拟化。这也意味着容器比传统的虚拟机开销更少。 容器和虚拟机常被误认为是两种对立的技术。虚拟机采用一个物理服务器来提供全功能的操作环境,该环境会和其余虚拟机一起共享这些物理资源。容器一般用来隔离一个单一主机上运行的应用进程,以保证隔离后的进程之间不能相互影响。事实上,容器和BSD Jails以及chroot进程的相似度,超过了和完整虚拟机的相似度。 Docker 在容器之上提供了什么 Docker 本身不是一个容器运行环境,事实上,只是一个与具体实现无关的容器技术,Docker 正在努力支持Solaris Zones和BSD Jails。Docker 提供了一种管理、打包和部署容器的方式。虽然一定程度上,虚拟机多多少少拥有这些类似的功能,但虚拟机并没有完整拥有绝大多数的容器功能,即使拥有,这些功能用起来都并没有 Docker 来的方便或那么完整。 现在,我们应该知道 Docker 是什么了,然后,我们将从安装 Docker,并部署一个公开的预构建好的容器开始,学习 Docker 是如何工作的。 从安装开始 默认情况下,Docker 并不会自动被安装在您的计算机中,所以,第一步就是安装 Docker 软件包;我们的教学机器系统是 Ubuntu 14.0.4,所以,我们将使用 Apt 软件包管理器,来执行安装操作。 # apt-get install docker.io Reading package lists... Done Building dependency tree Reading state information... Done The following extra packages will be installed: aufs-tools cgroup-lite git git-man liberror-perl Suggested packages: btrfs-tools debootstrap lxc rinse git-daemon-run git-daemon-sysvinit git-doc git-el git-email git-gui gitk gitweb git-arch git-bzr git-cvs git-mediawiki git-svn The following NEW packages will be installed: aufs-tools cgroup-lite docker.io git git-man liberror-perl 0 upgraded, 6 newly installed, 0 to remove and 0 not upgraded. Need to get 7,553 kB of archives. After this operation, 46.6 MB of additional disk space will be used. Do you want to continue? [Y/n] y 为了检查当前是否有容器运行,我们可以执行docker命令,加上ps选项 # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES docker命令中的ps功能类似于 Linux 的ps命令。它将显示可找到的 Docker 容器及其状态。由于我们并没有启动任何 Docker 容器,所以命令没有显示任何正在运行的容器。 部署一个预构建好的 nginx Docker 容器 我比较喜欢的 Docker 特性之一就是 Docker 部署预先构建好的容器的方式,就像yum和apt-get部署包一样。为了更好地解释,我们来部署一个运行着 nginx web 服务器的预构建容器。我们可以继续使用docker命令,这次选择run选项。 # docker run -d nginx Unable to find image 'nginx' locally Pulling repository nginx 5c82215b03d1: Download complete e2a4fb18da48: Download complete 58016a5acc80: Download complete 657abfa43d82: Download complete dcb2fe003d16: Download complete c79a417d7c6f: Download complete abb90243122c: Download complete d6137c9e2964: Download complete 85e566ddc7ef: Download complete 69f100eb42b5: Download complete cd720b803060: Download complete 7cc81e9a118a: Download complete docker命令的run选项,用来通知 Docker 去寻找一个指定的 Docker 镜像,然后启动运行着该镜像的容器。默认情况下,Docker 容器运行在前台,这意味着当你运行docker run命令的时候,你的 shell 会被绑定到容器的控制台以及运行在容器中的进程。为了能在后台运行该 Docker 容器,我们使用了-d(detach)标志。 再次运行docker ps命令,可以看到 nginx 容器正在运行。 # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f6d31ab01fc9 nginx:latest nginx -g 'daemon off 4 seconds ago Up 3 seconds 443/tcp, 80/tcp desperate_lalande 从上面的输出信息中,我们可以看到正在运行的名为desperate_lalande的容器,它是由nginx:latest image(LCTT 译注: nginx 最新版本的镜像)构建而来得。 Docker 镜像 镜像是 Docker 的核心特征之一,类似于虚拟机镜像。和虚拟机镜像一样,Docker 镜像是一个被保存并打包的容器。当然,Docker 不只是创建镜像,它还可以通过 Docker 仓库发布这些镜像,Docker 仓库和软件包仓库的概念差不多,它让 Docker 能够模仿yum部署软件包的方式来部署镜像。为了更好地理解这是怎么工作的,我们来回顾docker run执行后的输出。 # docker run -d nginx Unable to find image 'nginx' locally 我们可以看到第一条信息是,Docker 不能在本地找到名叫 nginx 的镜像。这是因为当我们执行docker run命令时,告诉 Docker 运行一个基于 nginx 镜像的容器。既然 Docker 要启动一个基于特定镜像的容器,那么 Docker 首先需要找到那个指定镜像。在检查远程仓库之前,Docker 首先检查本地是否存在指定名称的本地镜像。 因为系统是崭新的,不存在 nginx 镜像,Docker 将选择从 Docker 仓库下载之。 Pulling repository nginx 5c82215b03d1: Download complete e2a4fb18da48: Download complete 58016a5acc80: Download complete 657abfa43d82: Download complete dcb2fe003d16: Download complete c79a417d7c6f: Download complete abb90243122c: Download complete d6137c9e2964: Download complete 85e566ddc7ef: Download complete 69f100eb42b5: Download complete cd720b803060: Download complete 7cc81e9a118a: Download complete 这就是第二部分输出信息显示给我们的内容。默认情况下,Docker 会使用Docker Hub仓库,该仓库由 Docker 公司维护。 和 Github 一样,在 Docker Hub 创建公共仓库是免费的,私人仓库就需要缴纳费用了。当然,部署你自己的 Docker 仓库也是可以的,事实上只需要简单地运行docker run registry命令就行了。但在这篇文章中,我们的重点将不是讲解如何部署一个定制的注册服务。 关闭并移除容器 在我们继续构建定制容器之前,我们先清理一下 Docker 环境,我们将关闭先前的容器,并移除它。 我们利用docker命令和run选项运行一个容器,所以,为了停止同一个容器,我们简单地在执行docker命令时,使用kill选项,并指定容器名。 # docker kill desperate_lalande desperate_lalande 当我们再次执行docker ps,就不再有容器运行了 # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 但是,此时,我们这是停止了容器;虽然它不再运行,但仍然存在。默认情况下,docker ps只会显示正在运行的容器,如果我们附加-a(all) 标识,它会显示所有运行和未运行的容器。 # docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f6d31ab01fc9 5c82215b03d1 nginx -g 'daemon off 4 weeks ago Exited (-1) About a minute ago desperate_lalande 为了能完整地移除容器,我们在用docker命令时,附加rm选项。 # docker rm desperate_lalande desperate_lalande 虽然容器被移除了;但是我们仍拥有可用的nginx镜像(LCTT 译注:镜像缓存)。如果我们重新运行docker run -d nginx,Docker 就无需再次拉取 nginx 镜像即可启动容器。这是因为我们本地系统中已经保存了一个副本。 为了列出系统中所有的本地镜像,我们运行docker命令,附加images选项。 # docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE nginx latest 9fab4090484a 5 days ago 132.8 MB 构建我们自己的镜像 截至目前,我们已经使用了一些基础的 Docker 命令来启动、停止和移除一个预构建好的普通镜像。为了“Docker 化(Dockerize)”这篇博客,我们需要构建我们自己的镜像,也就是创建一个Dockerfile。 在大多数虚拟机环境中,如果你想创建一个机器镜像,首先,你需要建立一个新的虚拟机、安装操作系统、安装应用,最后将其转换为一个模板或者镜像。但在 Docker 中,所有这些步骤都可以通过 Dockerfile 实现全自动。Dockerfile 是向 Docker 提供构建指令去构建定制镜像的方式。在这一章节,我们将编写能用来部署这个博客的定制 Dockerfile。 理解应用 我们开始构建 Dockerfile 之前,第一步要搞明白,我们需要哪些东西来部署这个博客。 这个博客本质上是由一个静态站点生成器生成的静态 HTML 页面,这个生成器是我编写的,名为hamerkop。这个生成器很简单,它所做的就是生成该博客站点。所有的代码和源文件都被我放在了一个公共的Github 仓库。为了部署这篇博客,我们要先从 Github 仓库把这些内容拉取下来,然后安装Python和一些Python模块,最后执行hamerkop应用。我们还需要安装nginx,来运行生成后的内容。 截止目前,这些还是一个简单的 Dockerfile,但它却给我们展示了相当多的Dockerfile 语法)。我们需要克隆 Github 仓库,然后使用你最喜欢的编辑器编写 Dockerfile,我选择vi。 # git clone https://github.com/madflojo/blog.git Cloning into 'blog'... remote: Counting objects: 622, done. remote: Total 622 (delta 0), reused 0 (delta 0), pack-reused 622 Receiving objects: 100% (622/622), 14.80 MiB | 1.06 MiB/s, done. Resolving deltas: 100% (242/242), done. Checking connectivity... done. # cd blog/ # vi Dockerfile FROM - 继承一个 Docker 镜像 第一条 Dockerfile 指令是FROM指令。这将指定一个现存的镜像作为我们的基础镜像。这也从根本上给我们提供了继承其他 Docker 镜像的途径。在本例中,我们还是从刚刚我们使用的nginx开始,如果我们想从头开始,我们可以通过指定ubuntu:latest来使用UbuntuDocker 镜像。 ## Dockerfile that generates an instance of http://bencane.com FROM nginx:latest MAINTAINER Benjamin Cane <ben@bencane.com> 除了FROM指令,我还使用了MAINTAINER,它用来显示 Dockerfile 的作者。 Docker 支持使用#作为注释,我将经常使用该语法,来解释 Dockerfile 的部分内容。 运行一次测试构建 因为我们继承了nginxDocker镜像,我们现在的 Dockerfile 也就包括了用来构建nginx镜像的Dockerfile中所有指令。这意味着,此时我们可以从该 Dockerfile 中构建出一个 Docker 镜像,然后以该镜像运行一个容器。虽然,最终的镜像和nginx镜像本质上是一样的,但是我们这次是通过构建 Dockerfile 的形式,然后我们将讲解 Docker 构建镜像的过程。 想要从 Dockerfile 构建镜像,我们只需要在运行docker命令的时候,加上build选项。 # docker build -t blog /root/blog Sending build context to Docker daemon 23.6 MB Sending build context to Docker daemon Step 0 : FROM nginx:latest ---> 9fab4090484a Step 1 : MAINTAINER Benjamin Cane <ben@bencane.com> ---> Running in c97f36450343 ---> 60a44f78d194 Removing intermediate container c97f36450343 Successfully built 60a44f78d194 上面的例子,我们使用了-t(tag)标识给镜像添加“blog”的标签。实质上我们就是在给镜像命名,如果我们不指定标签,就只能通过 Docker 分配的Image ID来访问镜像了。本例中,从 Docker 构建成功的信息可以看出,Image ID值为60a44f78d194。 除了-t标识外,我还指定了目录/root/blog。该目录被称作“构建目录”,它将包含 Dockerfile,以及其它需要构建该容器的文件。 现在我们构建成功了,下面我们开始定制该镜像。 使用 RUN 来执行 apt-get 用来生成 HTML 页面的静态站点生成器是用Python语言编写的,所以,在 Dockerfile 中需要做的第一件定制任务是安装 Python。我们将使用 Apt 软件包管理器来安装 Python 软件包,这意味着在 Dockerfile 中我们要指定运行apt-get update和apt-get install python-dev;为了完成这一点,我们可以使用RUN指令。 ## Dockerfile that generates an instance of http://bencane.com FROM nginx:latest MAINTAINER Benjamin Cane <ben@bencane.com> ## Install python and pip RUN apt-get update RUN apt-get install -y python-dev python-pip 如上所示,我们只是简单地告知 Docker 构建镜像的时候,要去执行指定的apt-get命令。比较有趣的是,这些命令只会在该容器的上下文中执行。这意味着,即使在容器中安装了python-dev和python-pip,但主机本身并没有安装这些。说的更简单点,pip命令将只在容器中执行,出了容器,pip命令不存在。 还有一点比较重要的是,Docker 构建过程中不接受用户输入。这说明任何被RUN指令执行的命令必须在没有用户输入的时候完成。由于很多应用在安装的过程中需要用户的输入信息,所以这增加了一点难度。不过我们例子中,RUN命令执行的命令都不需要用户输入。 安装 Python 模块 Python安装完毕后,我们现在需要安装 Python 模块。如果在 Docker 外做这些事,我们通常使用pip命令,然后参考我的博客 Git 仓库中名叫requirements.txt的文件。在之前的步骤中,我们已经使用git命令成功地将 Github 仓库“克隆”到了/root/blog目录;这个目录碰巧也是我们创建Dockerfile的目录。这很重要,因为这意味着 Docker 在构建过程中可以访问这个 Git 仓库中的内容。 当我们执行构建后,Docker 将构建的上下文环境设置为指定的“构建目录”。这意味着目录中的所有文件都可以在构建过程中被使用,目录之外的文件(构建环境之外)是不能访问的。 为了能安装所需的 Python 模块,我们需要将requirements.txt从构建目录拷贝到容器中。我们可以在Dockerfile中使用COPY指令完成这一需求。 ## Dockerfile that generates an instance of http://bencane.com FROM nginx:latest MAINTAINER Benjamin Cane <ben@bencane.com> ## Install python and pip RUN apt-get update RUN apt-get install -y python-dev python-pip ## Create a directory for required files RUN mkdir -p /build/ ## Add requirements file and run pip COPY requirements.txt /build/ RUN pip install -r /build/requirements.txt 在Dockerfile中,我们增加了3条指令。第一条指令使用RUN在容器中创建了/build/目录。该目录用来拷贝生成静态 HTML 页面所需的一切应用文件。第二条指令是COPY指令,它将requirements.txt从“构建目录”(/root/blog)拷贝到容器中的/build/目录。第三条使用RUN指令来执行pip命令;安装requirements.txt文件中指定的所有模块。 当构建定制镜像时,COPY是条重要的指令。如果在 Dockerfile 中不指定拷贝文件,Docker 镜像将不会包含requirements.txt 这个文件。在 Docker 容器中,所有东西都是隔离的,除非在 Dockerfile 中指定执行,否则容器中不会包括所需的依赖。 重新运行构建 现在,我们让 Docker 执行了一些定制任务,现在我们尝试另一次 blog 镜像的构建。 # docker build -t blog /root/blog Sending build context to Docker daemon 19.52 MB Sending build context to Docker daemon Step 0 : FROM nginx:latest ---> 9fab4090484a Step 1 : MAINTAINER Benjamin Cane <ben@bencane.com> ---> Using cache ---> 8e0f1899d1eb Step 2 : RUN apt-get update ---> Using cache ---> 78b36ef1a1a2 Step 3 : RUN apt-get install -y python-dev python-pip ---> Using cache ---> ef4f9382658a Step 4 : RUN mkdir -p /build/ ---> Running in bde05cf1e8fe ---> f4b66e09fa61 Removing intermediate container bde05cf1e8fe Step 5 : COPY requirements.txt /build/ ---> cef11c3fb97c Removing intermediate container 9aa8ff43f4b0 Step 6 : RUN pip install -r /build/requirements.txt ---> Running in c50b15ddd8b1 Downloading/unpacking jinja2 (from -r /build/requirements.txt (line 1)) Downloading/unpacking PyYaml (from -r /build/requirements.txt (line 2)) <truncated to reduce noise> Successfully installed jinja2 PyYaml mistune markdown MarkupSafe Cleaning up... ---> abab55c20962 Removing intermediate container c50b15ddd8b1 Successfully built abab55c20962 上述输出所示,我们可以看到构建成功了,我们还可以看到另外一个有趣的信息---> Using cache。这条信息告诉我们,Docker 在构建该镜像时使用了它的构建缓存。 Docker 构建缓存 当 Docker 构建镜像时,它不仅仅构建一个单独的镜像;事实上,在构建过程中,它会构建许多镜像。从上面的输出信息可以看出,在每一“步”执行后,Docker 都在创建新的镜像。 Step 5 : COPY requirements.txt /build/ ---> cef11c3fb97c 上面片段的最后一行可以看出,Docker 在告诉我们它在创建一个新镜像,因为它打印了Image ID:cef11c3fb97c。这种方式有用之处在于,Docker能在随后构建这个blog镜像时将这些镜像作为缓存使用。这很有用处,因为这样, Docker 就能加速同一个容器中新构建任务的构建流程。从上面的例子中,我们可以看出,Docker 没有重新安装python-dev和python-pip包,Docker 则使用了缓存镜像。但是由于 Docker 并没有找到执行mkdir命令的构建缓存,随后的步骤就被一一执行了。 Docker 构建缓存一定程度上是福音,但有时也是噩梦。这是因为决定使用缓存或者重新运行指令的因素很少。比如,如果requirements.txt文件发生了修改,Docker 会在构建时检测到该变化,然后 Docker 会重新执行该执行那个点往后的所有指令。这得益于 Docker 能查看requirements.txt的文件内容。但是,apt-get命令的执行就是另一回事了。如果提供 Python 软件包的Apt仓库包含了一个更新的 python-pip 包;Docker 不会检测到这个变化,转而去使用构建缓存。这会导致之前旧版本的包将被安装。虽然对python-pip来说,这不是主要的问题,但对使用了存在某个致命攻击缺陷的软件包缓存来说,这是个大问题。 出于这个原因,抛弃 Docker 缓存,定期地重新构建镜像是有好处的。这时,当我们执行 Docker 构建时,我简单地指定--no-cache=True即可。 部署博客的剩余部分 Python 软件包和模块安装后,接下来我们将拷贝需要用到的应用文件,然后运行hamerkop应用。我们只需要使用更多的COPY和RUN指令就可完成。 ## Dockerfile that generates an instance of http://bencane.com FROM nginx:latest MAINTAINER Benjamin Cane <ben@bencane.com> ## Install python and pip RUN apt-get update RUN apt-get install -y python-dev python-pip ## Create a directory for required files RUN mkdir -p /build/ ## Add requirements file and run pip COPY requirements.txt /build/ RUN pip install -r /build/requirements.txt ## Add blog code nd required files COPY static /build/static COPY templates /build/templates COPY hamerkop /build/ COPY config.yml /build/ COPY articles /build/articles ## Run Generator RUN /build/hamerkop -c /build/config.yml 现在我们已经写出了剩余的构建指令,我们再次运行另一次构建,并确保镜像构建成功。 # docker build -t blog /root/blog/ Sending build context to Docker daemon 19.52 MB Sending build context to Docker daemon Step 0 : FROM nginx:latest ---> 9fab4090484a Step 1 : MAINTAINER Benjamin Cane <ben@bencane.com> ---> Using cache ---> 8e0f1899d1eb Step 2 : RUN apt-get update ---> Using cache ---> 78b36ef1a1a2 Step 3 : RUN apt-get install -y python-dev python-pip ---> Using cache ---> ef4f9382658a Step 4 : RUN mkdir -p /build/ ---> Using cache ---> f4b66e09fa61 Step 5 : COPY requirements.txt /build/ ---> Using cache ---> cef11c3fb97c Step 6 : RUN pip install -r /build/requirements.txt ---> Using cache ---> abab55c20962 Step 7 : COPY static /build/static ---> 15cb91531038 Removing intermediate container d478b42b7906 Step 8 : COPY templates /build/templates ---> ecded5d1a52e Removing intermediate container ac2390607e9f Step 9 : COPY hamerkop /build/ ---> 59efd1ca1771 Removing intermediate container b5fbf7e817b7 Step 10 : COPY config.yml /build/ ---> bfa3db6c05b7 Removing intermediate container 1aebef300933 Step 11 : COPY articles /build/articles ---> 6b61cc9dde27 Removing intermediate container be78d0eb1213 Step 12 : RUN /build/hamerkop -c /build/config.yml ---> Running in fbc0b5e574c5 Successfully created file /usr/share/nginx/html//2011/06/25/checking-the-number-of-lwp-threads-in-linux Successfully created file /usr/share/nginx/html//2011/06/checking-the-number-of-lwp-threads-in-linux <truncated to reduce noise> Successfully created file /usr/share/nginx/html//archive.html Successfully created file /usr/share/nginx/html//sitemap.xml ---> 3b25263113e1 Removing intermediate container fbc0b5e574c5 Successfully built 3b25263113e1 运行定制的容器 成功的一次构建后,我们现在就可以通过运行docker命令和run选项来运行我们定制的容器,和之前我们启动 nginx 容器一样。 # docker run -d -p 80:80 --name=blog blog 5f6c7a2217dcdc0da8af05225c4d1294e3e6bb28a41ea898a1c63fb821989ba1 我们这次又使用了-d(detach)标识来让Docker在后台运行。但是,我们也可以看到两个新标识。第一个新标识是--name,这用来给容器指定一个用户名称。之前的例子,我们没有指定名称,因为 Docker 随机帮我们生成了一个。第二个新标识是-p,这个标识允许用户从主机映射一个端口到容器中的一个端口。 之前我们使用的基础nginx镜像分配了80端口给 HTTP 服务。默认情况下,容器内的端口通道并没有绑定到主机系统。为了让外部系统能访问容器内部端口,我们必须使用-p标识将主机端口映射到容器内部端口。上面的命令,我们通过-p 80:80语法将主机80端口映射到容器内部的80端口。 经过上面的命令,我们的容器看起来成功启动了,我们可以通过执行docker ps核实。 # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d264c7ef92bd blog:latest nginx -g 'daemon off 3 seconds ago Up 3 seconds 443/tcp, 0.0.0.0:80->80/tcp blog 总结 截止目前,我们拥有了一个运行中的定制 Docker 容器。虽然在这篇文章中,我们只接触了一些 Dockerfile 指令用法,但是我们还是要学习所有的指令。我们可以检查Docker's reference page来获取所有的 Dockerfile 指令用法,那里对指令的用法说明得很详细。 另一个比较好的资源是Dockerfile Best Practices page,它有许多构建定制 Dockerfile 的最佳练习。有些技巧非常有用,比如战略性地组织好 Dockerfile 中的命令。上面的例子中,我们将articles目录的COPY指令作为 Dockerfile 中最后的COPY指令。这是因为articles目录会经常变动。所以,将那些经常变化的指令尽可能地放在最后面的位置,来最优化那些可以被缓存的步骤。 原文发布时间为:2016-06-08 本文来自云栖社区合作伙伴“Linux中国”

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

如何快速实现一个基于Nginx的网站监控场景----需求篇

一切从应用服务监控说起 小明所在的一家小型互联网创业公司一直将应用运行在国内某A云上。该应用采用通用的分布式Nginx+App架构为用户提供电商数据统计的webservice 服务。应用运行至今除偶发各类Bug, 性能问题以外,情况还算良好。 最近,小明的老板给小明布置了一个任务,希望把应用服务监控起来,以提高应用运行质量。老板的需求有三点: 1.先以应用服务监控为抓手,能 a)实时统计应用各类服务的调用次数 b)基于a,实时统计各类服务各类返回值的次数,如200,404,500,等。 c)基于b,如果某类返回值调用超限,进行实时报警。 2.提供历史查询功能,能返回任意时段任意服务任意返回值调用次数统计。 3.以后未来公司各类定制的业务监控能快速扩展到该系统上,如各接口响应统计时间,用户

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

【阿里云网站日志分析实践】通过Log Service日志服务导入MaxCompute分析

免费开通大数据服务:https://www.aliyun.com/product/odps 日志服务收集的日志除了可以被实时查询外,还可以把日志数据投递到大数据计算服务MaxCompute(原ODPS),进一步进行个性化BI分析及数据挖掘。通过日志服务投递日志数据到MaxCompute具有如下优势: 使用非常简单。用户只需要完成2步配置即可以把日志服务Logstore的日志数据迁移到MaxCompute中。 避免重复收集工作。由于日志服务的日志收集过程已经完成不同机器上的日志集中化,无需重复在不同机器上收集一遍日志数据后再导入到MaxCompute。 充分复用日志服务内的日志分类管理工作。用户可让日志服务中不同类型的日志(存在不同Logstore中)、不同Project的日志自动投递到不同的MaxCompute表格,方便管理及分析MaxC

资源下载

更多资源
Mario

Mario

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

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Rocky Linux

Rocky Linux

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

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册