首页 文章 精选 留言 我的

精选列表

搜索[Bot管理],共10000篇文章
优秀的个人博客,低调大师

ELK日志集中化管理系统安装

ELK Stack 是 Elasticsearch、Logstash、Kibana 三个开源软件的组合。在实时数据检索和分析场合,三者通常是配合共用,而且又都先后归于 Elastic.co 公司名下,故有此简称。 ELK Stack 在最近两年迅速崛起,成为机器数据分析,或者说实时日志处理领域,开源界的第一选择。 ELK由三个组建构成,分别是 Elasticsearch,负责数据的索引和存储 Logstash ,负责日志的采集和格式化 Kibana,负责前端统计的展示 大致的架构如下: redis提供队列来作为broker负责log传输过程中的缓冲,也可以由kafka等来代替。 一、logstansh安装 1、JDK安装 1 2 3 4 5 yum-y install java-1.8.0 [root@ELKServer~] #java-version openjdkversion "1.8.0_101" OpenJDKRuntimeEnvironment(build1.8.0_101-b13) OpenJDK64-BitServerVM(build25.101-b13,mixedmode) 2、logstansh安装 1 2 3 4 5 wgethttps: //download .elastic.co /logstash/logstash/logstash-2 .3.4.zip unziplogstash-2.3.4.zip mv logstash-2.3.4 /usr/local/ echo "PATH=$PATH:/usr/local/logstash-2.3.4/bin" >> /etc/profile source /etc/profile 3、新建logstansh配置文件目录 1 mkdir /usr/local/logstash-2 .3.4 /conf 4、测试logstansh 1 2 3 4 5 [root@ELKServerlogstash-2.3.4] #logstash-e"input{stdin{}}output{stdout{}}" hello Settings:Defaultpipelineworkers:1 Pipelinemainstarted 2016-07-28T12:47:41.597Z0.0.0.0hello 二、redis安装 1、redis安装 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 wgethttp: //download .redis.io /releases/redis-2 .8.20. tar .gz yum install tcl-y tar -zxvfredis-2.8.20. tar .gz mv redis-2.8.20/ /usr/local/ [root@ELKServerlogstash-2.3.4] #cd/usr/local/redis-2.8.20/ [root@ELKServerredis-2.8.20] #makeMALLOC=libc [root@ELKServerredis-2.8.20] #makeinstall [root@ELKServerredis-2.8.20] #cdutils/ [root@ELKServerutils] #./install_server.sh#所有选项默认 Welcometotheredisserviceinstaller Thisscriptwillhelpyoueasily set uparunningredisserver Please select theredisport for thisinstance:[6379] Selectingdefault:6379 Please select theredisconfig file name[ /etc/redis/6379 .conf] Selecteddefault- /etc/redis/6379 .conf Please select theredislog file name[ /var/log/redis_6379 .log] Selecteddefault- /var/log/redis_6379 .log Please select thedatadirectory for thisinstance[ /var/lib/redis/6379 ] Selecteddefault- /var/lib/redis/6379 Please select theredisexecutablepath[ /usr/local/bin/redis-server ] Selectedconfig: Port:6379 Config file : /etc/redis/6379 .conf Log file : /var/log/redis_6379 .log Data dir : /var/lib/redis/6379 Executable: /usr/local/bin/redis-server CliExecutable: /usr/local/bin/redis-cli Isthisok?ThenpressENTERtogoonorCtrl-Ctoabort. Copied /tmp/6379 .conf=> /etc/init .d /redis_6379 Installingservice... Successfullyaddedtochkconfig! Successfullyaddedtorunlevels345! StartingRedisserver... Installationsuccessful! 2、查看redis的监控端口 1 2 3 [root@ELKServerutils] #netstat-tnlp|grepredis tcp000.0.0.0:63790.0.0.0:*LISTEN2085 /redis-server * tcp00:::6379:::*LISTEN2085 /redis-server * 3、测试redis是否缓存数据 a、新建logstansh配置文件如下: 1 2 3 4 5 6 7 8 9 10 [root@ELKServerconf] #catoutput_redis.conf input{stdin{}} #手动输入数据 output{ stdout{codec=>rubydebug} #页面debug信息 redis{ host=> '192.168.10.49' data_type=> 'list' key=> 'redis' } } b、启动logstansh 1 2 3 4 5 6 7 8 9 10 11 12 13 [root@ELKServerconf] #logstash-foutput_redis.conf--verbose startingagent{:level=>:info} startingpipeline{: id => "main" ,:level=>:info} Settings:Defaultpipelineworkers:1 Startingpipeline{: id => "main" ,:pipeline_workers=>1,:batch_size=>125,:batch_delay=>5,:max_inflight=>125,:level=>:info} Pipelinemainstarted hello #手动输入 { "message" => "hello" , "@version" => "1" , "@timestamp" => "2016-07-28T13:09:42.651Z" , "host" => "0.0.0.0" } c、查看redis中是否存在数据。 1 cd /usr/local/redis-2 .8.20 /src/ 执行下面这条命令后再执行logstash -f output_redis.conf(最好分两个ssh会话测试)。 1 2 3 [root@ELKServersrc] #./redis-climonitor OK 1469711599.811344[0192.168.10.49:56179] "rpush" "redis" "{\"message\":\"hello\",\"@version\":\"1\",\"@timestamp\":\"2016-07-28T13:13:18.446Z\",\"host\":\"0.0.0.0\"}" 三、elasticsearch安装 1、elasticsearch安装配置 1 2 3 wgethttps: //download .elastic.co /elasticsearch/release/org/elasticsearch/distribution/zip/elasticsearch/2 .3.4 /elasticsearch-2 .3.4.zip unzipelasticsearch-2.3.4.zip mv elasticsearch-2.3.4 /usr/local/ 修改elasticsearch配置文件 1 vim /usr/local/elasticsearch-2 .3.4 /config/elasticsearch .yml 把下面参数的注释去掉并改成服务器IP。这里只做简单安装,优化及集群后面再介绍 1 network.host:192.168.10.49 2、elasticsearch启动 1 2 [root@ELKServerbin] #/usr/local/elasticsearch-2.3.4/bin/elasticsearch-d [root@ELKServerbin] #Exceptioninthread"main"java.lang.RuntimeException:don'trunelasticsearchasroot.' elasticsearch启动不能使用root用户。新建elk用户,并把elasticsearch目录用户所有者改成elk 1 [elk@ELKServerbin]$. /elasticsearch -d 查看elasticsearch是否启动 1 2 3 [elk@ELKServerbin]$ netstat -tnlp| grep java tcp00::ffff:192.168.10.49:9200:::*LISTEN2476 /java tcp00::ffff:192.168.10.49:9300:::*LISTEN2476 /java 3、测试logstansh和elasticsearch是否能结合使用 a、新建logstansh配置文件elasticsearch.conf 1 2 3 4 5 6 7 [root@ELKServerbin] #cd/usr/local/logstash-2.3.4/conf [root@ELKServerconf] #catelasticsearch.conf input{stdin{}} #手动输入 output{ elasticsearch{hosts=> "192.168.10.49" } stdout{codec=>rubydebug} #页面debug信息 } b、启动elasticsearch.conf配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [root@ELKServerconf] #logstash-felasticsearch.conf--verbose startingagent{:level=>:info} startingpipeline{: id => "main" ,:level=>:info} Settings:Defaultpipelineworkers:1 Usingmappingtemplatefrom{:path=>nil,:level=>:info} Attemptingto install template{:manage_template=>{ "template" => "logstash-*" , "settings" =>{ "index.refresh_interval" => "5s" }, "mappings" =>{ "_default_" =>{ "_all" =>{ "enabled" => true , "omit_norms" => true }, "dynamic_templates" =>[{ "message_field" =>{ "match" => "message" , "match_mapping_type" => "string" , "mapping" =>{ "type" => "string" , "index" => "analyzed" , "omit_norms" => true , "fielddata" =>{ "format" => "disabled" }}}},{ "string_fields" =>{ "match" => "*" , "match_mapping_type" => "string" , "mapping" =>{ "type" => "string" , "index" => "analyzed" , "omit_norms" => true , "fielddata" =>{ "format" => "disabled" }, "fields" =>{ "raw" =>{ "type" => "string" , "index" => "not_analyzed" , "ignore_above" =>256}}}}}], "properties" =>{ "@timestamp" =>{ "type" => "date" }, "@version" =>{ "type" => "string" , "index" => "not_analyzed" }, "geoip" =>{ "dynamic" => true , "properties" =>{ "ip" =>{ "type" => "ip" }, "location" =>{ "type" => "geo_point" }, "latitude" =>{ "type" => "float" }, "longitude" =>{ "type" => "float" }}}}}}},:level=>:info} NewElasticsearchoutput{:class=> "LogStash::Outputs::ElasticSearch" ,:hosts=>[ "192.168.10.49" ],:level=>:info} Startingpipeline{: id => "main" ,:pipeline_workers=>1,:batch_size=>125,:batch_delay=>5,:max_inflight=>125,:level=>:info} Pipelinemainstarted helloelasticsearch #这行是手动输入的 { "message" => "helloelasticsearch" , "@version" => "1" , "@timestamp" => "2016-07-28T14:20:09.460Z" , "host" => "0.0.0.0" } c、查看elasticsearch是否获取到了"hello elasticsearch" 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 [root@ELKServerconf] #curlhttp://localhost:9200/_search?pretty { "took" :45, "timed_out" : false , "_shards" :{ "total" :5, "successful" :5, "failed" :0 }, "hits" :{ "total" :1, "max_score" :1.0, "hits" :[{ "_index" : "logstash-2016.07.28" , "_type" : "logs" , "_id" : "AVYx4H2BdePMZ0WyBMGl" , "_score" :1.0, "_source" :{ "message" : "helloelasticsearch" , "@version" : "1" , "@timestamp" : "2016-07-28T14:20:09.460Z" , "host" : "0.0.0.0" } }] } } 4、安装elasticsearch插件 elasticsearch有很多插件:http://www.searchtech.pro/elasticsearch-plugins elasticsearch-head插件安装 1 2 3 4 5 6 7 [root@ELKServerlang-expression] #cd/usr/local/elasticsearch-2.3.4/bin/ [root@ELKServerbin] #./plugininstallmobz/elasticsearch-head ->Installingmobz /elasticsearch-head ... Tryinghttps: //github .com /mobz/elasticsearch-head/archive/master .zip... Downloading.................DONE Verifyinghttps: //github .com /mobz/elasticsearch-head/archive/master .zipchecksums if available... Installed head into /usr/local/elasticsearch-2 .3.4 /plugins/head 查看elasticsearch-head插件显示的页面 http://192.168.10.49:9200/_plugin/head/ 四、kibana安装 1、安装kibana 1 2 3 4 [root@ELKServer~] #tar-zxvfkibana-4.5.2-linux-x64.tar.gz [root@ELKServer~] #mvkibana-4.5.2-linux-x64/usr/local/ [root@ELKServer~] #cd/usr/local/kibana-4.5.2-linux-x64/config/ [root@ELKServerconfig] #vimkibana.yml 修改kibana配置文件,把下面这行改成elasticsearc的访问路径 1 elasticsearch.url: "http://192.168.10.49:9200" 2、启动kibana 1 2 3 4 5 6 7 8 9 10 11 12 [root@ELKServerbin] #/usr/local/kibana-4.5.2-linux-x64/bin/kibana& log[23:10:23.215][info][status][plugin:kibana]Statuschangedfromuninitializedtogreen-Ready log[23:10:23.288][info][status][plugin:elasticsearch]Statuschangedfromuninitializedtoyellow-Waiting for Elasticsearch log[23:10:23.344][info][status][plugin:kbn_vislib_vis_types]Statuschangedfromuninitializedtogreen-Ready log[23:10:23.377][info][status][plugin:markdown_vis]Statuschangedfromuninitializedtogreen-Ready log[23:10:23.415][info][status][plugin:metric_vis]Statuschangedfromuninitializedtogreen-Ready log[23:10:23.445][info][status][plugin:spyModes]Statuschangedfromuninitializedtogreen-Ready log[23:10:23.464][info][status][plugin:statusPage]Statuschangedfromuninitializedtogreen-Ready log[23:10:23.485][info][status][plugin:table_vis]Statuschangedfromuninitializedtogreen-Ready log[23:10:23.510][info][listening]Serverrunningathttp: //0 .0.0.0:5601 log[23:10:28.470][info][status][plugin:elasticsearch]Statuschangedfromyellowtoyellow-NoexistingKibanaindexfound log[23:10:31.442][info][status][plugin:elasticsearch]Statuschangedfromyellowtogreen-Kibanaindexready 3、测试kibana 访问页面:http://192.168.10.49:5601/ 五、ELK实例测试 1、简单介绍下ELK的数据传输过程 a、logstansh客户端根据日志存放路径采集日志(input),然后转给redis服务器缓存(output) b、logstansh服务端将消息从redie服务器拿出来(input),然后用filter对日志分割处理 c、logstansh服务端最后将处理好的日志转给ealsticsearch(output)存储 d、kibana通过ealsticsearch接口获取存储的数据并页面展示出来 在测试中我们没有对日志做filter处理 2、新建logstansh配置文件 logstash_redis.conf logstansh客户端配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 input{ file{ path=> "/var/log/messages" start_position=>beginning sincedb_write_interval=> 0 add_field=>{ "Host" => "192.168.10.47" } type=> "SYSLOG_LOG" } } output{ redis{ host=> "192.168.10.47:6379" data_type=> "list" key=> "logstash:syslog_log" } } redis_elasticserach.conf logstansh服务端配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 input{ redis{ host=> '192.168.10.47' data_type=> 'list' port=> "6379" key=> 'logstash:syslog_log' type=> 'redis-input' } } output{ elasticsearch{ hosts=> "192.168.10.47" index=> "logstash-%{+YYYY.MM.dd}" } } 2、启动ELK各项服务 1 2 3 4 5 logstash-flogstash_redis.conf& logstash-fredis_elasticsearch.conf& /etc/init .d /redis_6379 start /usr/local/elasticsearch-2 .3.4 /bin/elasticsearch -d(elk用户启动) /usr/local/kibana-4 .5.2-linux-x64 /bin/kibana & 3、检查日志传输是否正常 a、查看elasticsearch数据信息 http://192.168.10.49:9200/_plugin/head/ b、查看kibana是否有数据显示 http://192.168.10.49:5601/ 注意:因为上面从message获取的日志是日志文件首行开始获取,时间可能是几天前的。 在kibana查看数据是注意选择时间范围 本文转自 irow10 51CTO博客,原文链接:http://blog.51cto.com/irow10/1832053,如需转载请自行联系原作者

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

java管理hdfs文件的常用类小结

最近在写一些hadoop的运维工具,考虑到hadoop本身是java编写的,api比较方便,可以直接拿来就用 准备用java来写。 今天测试了几个fs相关的类。 主要有FileStatus,FileSystem,DistributedFileSystem,DatanodeInfo,BlockLocation FileStatus是和文件的属性相关的类,比如文件的名称,大小,属主等 主要的取值方法有: getPath,getLen,getModificationTime,getAccessTime,getReplication,getOwner,getGroup,getPermission等,通过字面意思就可以很容易的理解其功能 FileSystem是一个抽象类,常见的具体实现类是LocalFileSystem和DistributedFileSystem 常见的方法: listStatus 查看目录下的文件属性,返回FileStatus数组,getFileStatus 查看一个文件的属性,返回FileStatus copyToLocalFile hdfs到本地复制,copyFromLocalFile 本地到hdfs复制,exists 判断文件是否存在,参数为Path,getLocal 返回本地文件系统,LocalFileSystem getFileBlockLocations ,返回BlockLocation的数组,参数是FileStatus 等 DatanodeInfo是和datanode有关的类,主要是包含了datanode的相关信息,主要有容量,打开文件数,主机名,ip等信息,比如查看整个hdfs集群的存储状态(dfsadmin report)就是调用了 getDatanodeReport方法。 BlockLocation包含了block所在的datanode的信息,可以用来查看一个文件的block的具体信息,比如大小,所在主机,是否为坏块等 综上,可以用FileStatus来获取文件的属性,FileSystem的具体实现类来对文件做操作,用DatanodeInfo来获取datanode的信息,BlockLocation来看文件到block的对应关系 下面列举两个例子: 例1: 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 import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileStatus; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.hdfs.DistributedFileSystem; import org.apache.hadoop.hdfs.protocol.DatanodeInfo; import org.apache.hadoop.fs.BlockLocation; import static java.lang.System.out; public class FileStatusTest{ private static Configurationconfig= new Configuration(); private static FileSystemhdfs= null ; private static FileStatus[]status= null ; public static void main(String[]args) throws IOException{ List<String>namelist= new ArrayList<String>(); config.addResource( "hdfs-site.xml" ); config.addResource( "core-site.xml" ); out.println(config.get( "dfs.namenode.name.dir" )); out.println(config.get( "fs.defaultFS" )); FileSystemhdfs=FileSystem.get(config); out.println(hdfs.getClass().getName()); Stringfile=args[ 0 ]; try { if (!hdfs.exists( new Path(file))){ return ; } status=hdfs.listStatus( new Path(file)); out.println( "filenumis" +status.length); for (FileStatusf:status){ namelist.add(f.getPath().toString()); out.println( "filenameis" +f.getPath()); } } catch (Exceptione){ e.printStackTrace(); } } } 例2: 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 import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileStatus; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.hdfs.DistributedFileSystem; import org.apache.hadoop.hdfs.protocol.DatanodeInfo; import org.apache.hadoop.fs.BlockLocation; import static java.lang.System.out; public class FileStatusTest{ private static Configurationconfig= new Configuration(); private static FileSystemhdfs= null ; private static FileStatus[]status= null ; public static void main(String[]args) throws IOException{ List<String>namelist= new ArrayList<String>(); List<String>hostlist= new ArrayList<String>(); config.addResource( "hdfs-site.xml" ); config.addResource( "core-site.xml" ); out.println(config.get( "dfs.namenode.name.dir" )); out.println(config.get( "fs.defaultFS" )); FileSystemhdfs=FileSystem.get(config); try { DistributedFileSystemdishdfs=(DistributedFileSystem)hdfs; DatanodeInfo[]nodeStats=dishdfs.getDataNodeStats(); String[]names= new String[nodeStats.length]; for ( int i= 0 ;i<nodeStats.length;i++){ out.println( "hostnameis" +nodeStats[i].getName()); out.println( "dfsusedis" +nodeStats[i].getDfsUsed()); out.println(nodeStats[i].getDatanodeReport()); } } catch (Exceptione){ e.printStackTrace(); } out.println(hdfs.getClass().getName()); Stringfile=args[ 0 ]; try { if (!hdfs.exists( new Path(file))){ return ; } status=hdfs.listStatus( new Path(file)); out.println( "filenumis" +status.length); for (FileStatusf:status){ namelist.add(f.getPath().toString()); out.println( "filenameis" +f.getPath()); BlockLocation[]blks=hdfs.getFileBlockLocations(f, 0 ,f.getLen()); for (BlockLocationblk:blks){ out.println( "blknameis" +blk.toString()); out.println( "lengthis" +blk.getLength()); } } } catch (Exceptione){ e.printStackTrace(); } } } 本文转自菜菜光 51CTO博客,原文链接:http://blog.51cto.com/caiguangguang/1528510,如需转载请自行联系原作者

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

(五)Docker镜像管理2之镜像制作

构建一个自定义的Docker镜像必定离不开Dockerfile,有了这个文件我们就可以通过docker image build命令来构建我们自己的镜像,所以我们从先从制作一个简单的镜像开始。 简单的Dockerfile: 首先我们要先建立一个目录,用于存放Dockerfile,这个目录就是构建镜像的环境,该环境称作构建上下文,在构建镜像的时候会将该上下文和该上下文中的文件和目录上传到Docker守护进程,这样守护进程就可以访问这里的内容,只有这样才能把用户想封装到镜像的东西添加到镜像中,包括文件、代码或者其他数据。 我这里在/work下建立一个叫做buildContext的目录,这个目录随意任何位置任何名称都可以。 编辑Dockerfile文件 创建镜像 1 dockerimagebuild-t仓库/标签:版本号. 查看刚刚构建的镜像 1 dockerimage history ID 现在我们说一下docker build命令中的参数 参数 说明 --build-art=[] 设置镜像创建时的变量 --compress 是否在构建过程使用gzip进行压缩,默认为否 --cpu-shares 设置CPU使用权重,默认为0 --cpu-period 设置CPU的CFS(完全公平调度算法)周期,默认为0,这个可以调整是否可以给该容器分配更多或更少的CPU时间。 --cpu-quota 设置CPU的CFS配额,默认为0 --cpuset-cpus 指定使用哪个CPU运行该容器,从0开始表示第一个CPU或者核心 --cpuset-mems 设置指定使用的内存ID,一根物理内存在系统上是有编号的,就跟CPU一样,这个参数设置该容器使用哪根物理内存条。使用下面的命令查看: dmidecode -t 17 | less 其中Handle后面的表示内存ID,插上内存的插槽在Size中有值,没插的显示“No Module Installed”。 --disable-content-truse 忽略校验,默认开启 -f 设置使用哪个dockerfile,如果使用这个参数指定文件位置那么该Dockerfile的名称可以是任意的,但是必须在构建上下文之中。之前演示构建的命令中最后是一个“.”,这个表示到本地当前目录(也叫做构建上下文路径)去找dockerfile,这时候你的Dockerfile文件名称就必须是“dockerfile”,而且它会读取该目录以及其子目录的Dockerfile,并将所有的内容发送给docker守护进程来创建镜像,所以一般建议构建上下文或者也叫做内容路径为空目录。如果你不使用构建上下文路径下的Dockerfile,那么就要使用-f参数来指定文件。 --force-rm 是否允许强制删除容器,默认为false --isolation 容器隔离技术 --lable=[] 为镜像设置一个标签 -m,--memory 设置内存限制,如果仅指定这一个参数,那么实际限制会是这个值的2倍,因为单纯的设置这个值其实是1倍给内存1倍给SWAP。如果要想固定就要和下面的--memory-swap一起使用,不但指定内存限制也要指定SWAP限制。如果使用-m参数遇到下面的错误: "Your kernel does not support swap limit capabilities.memory limit without swap" 那就需要修改/etc/default/grub文件 GRUB_COMMLINE_LINUX="cgroup_enable=memory swapaccount=1" 然后grub并且重启计算机。 --memory-swap 设置容器的SWAP限制 --network 设置网络方式 --no-cache 构建镜像时不适用缓存,默认为false。因为构件时,每一步都会提交为一个镜像,所以Docker会把之前的看做缓存,假设构建分成5步,前三步都不需要修改,那么Docker就会将前3步作为缓存适用,尤其是在构建镜像调试的时候会用到,这样可以节省时间。 --pull 总会尝试拉取一个最新版本的镜像进行使用,默认为false --tag,-t 镜像名称 名称:标签 -q 不输出构建镜像过程,结束后输出结果。默认是false,也就是输出构建过程。 --rm 镜像构建成功后,删除构建过程中的容器。 --shm-size 默认的/dev/shm大小,默认64M --ulimit 设置容器的ulimit设置,就是我们使用ulimit -a看到的那些内容。 如果构建失败怎么办: 找到失败的那一步上面的一步,因为失败的上一步才是成功的,这样我们就可以使用docker run命令进入容器中进行调试。找到问题后再退出,然后修改Dockerfile,最后再次构建。从上图看出是我的Dockerfile里的一个命令写错了,进入容器我运行正确的命令进行调试 再次运行构建 从构建的镜像启动容器 1 dockerrun-d-p80--namehttpSrvrex /1stimage :0.1 我们这里用了一个新的参数-p,这个是用来控制容器在运行时公开哪个端口给宿主机。从上图可以看到容器中的80(也就是在Dockerfile中EXPOSE定义的端口)映射到了本地宿主机的32769端口上。我们可以通过下面的命令来查看映射情况: 1 2 dockerportID[PORT] #不加后面的端口表示查看该容器的所有端口映射情况 说一下这个-p|P参数: -p [IP]:[PORT]:PORT -p PORT 表示使用宿主机的0.0.0.0地址的任意高位端口映射到容器的PORT上 -p [PORT]:PORT 表示使用宿主机0.0.0.0地址指定的端口映射到容器的PORT上 -p [IP]:[PORT]:PORT 表示使用宿主机指定的IP和端口映射到容器的PORT上 -p [IP]::PORT 表示使用宿主机指定的IP和随机高位端口映射到容器的PORT上 -P 大写P,表示使用Dockerfile中定义的EXPOSE端口映射到宿主机的随机端口上。 测试访问: Dockerfile的格式和字段: FROM 指定创建的镜像的基础镜像,如果本地不存在就会去你所使用的仓库去拉取。任何Dockerfile中该命令必须是第一条。如果在同一个Dockerfile中创建多个镜像,可以使用多个FROM命令。 1 FROM镜像:[标签] #如果不指定标签,则默认为leatest,最新镜像 MAINTAINER 设置维护者信息,也就是写该Dockerfile的作者是谁,联系方式等。该信息会写入镜像的Author属性中。如下图: RUN 构建镜像过程中指定要运行的命令 1 2 3 4 RUN<COMMAND> #或者 RUN[ "COMMAND" , "ARG1" ...] #后面这张形式会被解析为JSON数组,所以必须加引号 前者默认会在shell终端中运行,也就是/bin/bash -c;后者会使用exec执行,不会启动shell环境。每一条RUN命令会在当前镜像基础上执行,并提交为新的镜像。如果命令较长可以使用“\”来换行。 CMD 用于指定一个在容器启动时需要执行的命令,这个命令和RUN命令很像,只不过这个命令是在容器启动时默认执行的,而RUN命令是构建镜像时执行的。书写格式如下: 1 2 3 CMD<COMMAND> #或者 CMD[ "COMMAND" , "ARG1" , "ARG2" ...] 和RUN命令一样前者默认会在shell终端中运行,也就是/bin/bash -c;后者会使用exec执行,不会启动shell环境。每一条RUN命令会在当前镜像基础上执行,并提交为新的镜像。如果命令较长可以使用“\”来换行。 注意:每个Dockerfile只能有一条CMD命令。如果写了多条,那么只有最后一条会被执行,另外docker run命令后面如果加上了要执行的命令,将会覆盖CMD中的命令。 LABEL 该指令用于生成镜像的元数据标签信息,格式为: 1 LABEL<KEY>=<VALUE><KEY>=<VALUE>.... EXPOSE 声明镜像内部服务监听的端口,格式如下: 1 EXPOSE<PORT>.... 可以同时指定多个,每个用空格分割。这里设置监听的端口只是声明并不会自动完成端口映射,也就是完成宿主机上的端口到容器监听端口的映射。如果要进行端口映射,那么需要在docker run命令中使用-p|P参数来设置。 ENV 用来定义环境变量,在镜像构建时会被后续的RUN命令使用,同时在容器启动时也会生效。 1 2 3 ENV<NAME><VALUE> #或者 ENV<NAME>=<VALUE> 比如: 1 2 ENVJAVA_HOME /opt/java1 .8.0_111 ENVPATH$JAVA_HOME:$PATH 另外使用docker run命令加上-e "JAVA_HOME=/usr/local/java1.6"参数可以修改ENV设定的环境变量值,不过该值只会在容器运行时有效。 ADD 该指令用于复制指定目录下的内容到容器中的指定内容,格式如下: 1 ADD<SRC><DES> 注意:源路径可以是一个URL,或者是构建上下文中的文件或者目录,不能是构建上下文目录之外的文件或者目录,源文件也可以是一个tar、tar.gz或者.gz的文件,它将会被自动解压缩到目标路径下,目标路径可以是一个镜像内的绝对路径,也可以是一个相对于WORKDIR的相对路径。如果目标目录不存在那么Docker会自动创建。新创建的文件和目录的权限为755,UID和GID都为0. 1 2 ADD/构建上下文 /apache/httpd .conf /etc/httpd/conf/ ADD/构建上下文 /apache/httpd .d/*.conf /etc/httpd/conf .d/ Docker会自动判断你要拷贝的文件还是目录,如果以“/”结尾表示目录下的所有内容,如果不是则认为是文件。 COPY 这个命令和ADD命令类似,区别是COPY只复杂把文件拷贝到目标,不会提取和解压,如果你的源文件不涉及到解压缩工作,那么你用COPY和ADD都一样。COPY命令的使用方式和原则和ADD一样。 1 COPY<SRC><DES> ENTRYPOINT 这个命令和CMD命令很像,也很容易弄混。docker run命令可以覆盖CMD命令,它的主要作用是在容器启动时作为根命令执行,所有传入的值作为该命令的参数执行。其格式如下: 1 2 3 ENTRYPOINT<COMMANDARG1ARG2...> #或者 ENTRYPOINT[ "COMMAND" , "ARG1" , "ARG2" ...] 每个Dockerfile也只能有一个ENTRYPOINT,如果有多个最后一个有效。看一个例子: 1 ENTRYPOINT[ "/usr/sbin/nginx" ] 在Dockerfile中包括上面的一行,然后在启动容器时: 1 dockerrun-d镜像-g "daemonoff;" 这样启动容器时,-g和后面的参数将会传递给ENTRYPOINT,最终的命令将会是: 1 /usr/sbin/nginx -g "daemonoff;" 如果需要可以在容器启动时使用--entrypoint这个标志来覆盖ENTRYPOINT的设置,这样就可以实现自己指定运行的命令。 VOLUME 在容器中创建一个数据挂载点,它不是把你宿主机的目录挂载到容器中,而是在容器中建立一个卷,这个目录不需要提前建立。 1 VOLUME[ "/目录1" , "/目录2" ....] 这个目录可以绕过联合文件系统,通常情况下如果容器程序产生的数据需要保存那么会使用这个命令来挂载或者多个容器需要共享一些数据也可而已通过这个来完成。 该卷可以在容器间共享或者重用 对该卷的修改立即生效 对卷的修改不会对镜像产生影响 如果单纯的是使用VOLUME,而不在docker run命令中使用-v参数的话,那么就是把VOLUME指定的目录挂载到宿主机中的某一个位置,这个位置在哪里呢?你通过 docker inspect 容器ID 中的Mounts里面来查看,Destination是VOLUME指定的目录,Source是宿主机本地路径,如果你再docker run中使用了-v参数,那么Source就是你指定的路径。 这个VOLUME的特点是绕过文件系统,容器中的程序产生的数据就可以放在这个VOLUME指定的目录中,这样它不占容器空间,而是消耗宿主机磁盘空间,默认本地的路径可以通过docker inspect查看,这个路径里面的数据不会因为容器的删除而删除。 USER 指定用哪个用户来运行容器,默认是用root来运行容器的。 1 2 3 4 USER<USERNAME> USER<UID> USER<USERNAME>:<GROUPNAMD> USER<UID>:<GID> 可以使用docker run命令中的-u参数来覆盖这个设置。 WORKDIR 指定容器内的工作目录,就是容器内的目录切换,在不同目录下需要做不同的事情,就可以用这个指令。这个命令主要是配合后续要执行的RUN、CMD和ENTRYPOINT的。 1 WORKDIR<PATH> 在启动容器时如果在docker run 命令中加入-w参数可以覆盖WORKDIR目录,来指定一个新的工作目录。 ARG 该参数用来定义在build构建镜像是可以传递到构建过程中的变量,这样可以使用--build-arg来传递变量进去。 1 2 ARGA1 ARGA2=HELLO A1变量没有值,A2变量有一个默认值。 1 dockerbuild--build-argA1=world-tNAME. 上面的命就会给A1赋值,而A2则会用默认值。 ONBUILD 这个指令可以为镜像添加一个触发器,一旦具有ONBUILD参数的镜像当做其他镜像的基础镜像时,ONBUILD定义的命令就会被执行。格式如下: 1 ONBUILDRUN[ "echo" , "helloworld" ] 如果上面的的镜像是1,那么基于1去构建镜像2 1 2 3 FROM1 ..... 这就相当于在新构建镜像时,自动运行1镜像中的ONBUILD 说明:这种继承只会一次,不会再次传递,也就是说如果镜像3是基于镜像2制作的,那么将不会执行ONBUILD,因为也不会继承过来。 STOPSIGNAL 用来设置停止容器时发送什么系统信号调用信号给容器,这个信号必须是内核可以识别的。通过kill -l就可以查看系统支持哪些信号。 1 STOPSIGNAL<SIGNAL> HEALTHCHECK 配置容器启动时如何进行健康检查 1 2 3 4 #根据执行命令是否返回0来判断 HEALTHCHECK[OPTION]CMD<COMMAND> #禁止继承镜像中的健康检查 HEALTHCHECKNONE OPTION有: --interval=DURATION ,多久检查一次,默认30秒 --timeout=DURATION ,每次检查等待结果的时间,默认30秒 --retries=N ,如果失败了,重试几次才最终确定失败 SHELL 指定使用SHELL的默认SHELL类型,默认值为:["/bin/sh","-c"] 为什么不能用构建上下文之外的路径? 因为构建上下文环境会上传到Docker守护进程中,而COPY或者ADD是在Docker守护进程中进行的,任何构建环境之外的都找不到,所以就不能用。 举例制作TOMCAT镜像 上面讲过了Dockerfile的格式以及可以使用的命令,我们现在制作一个TOMCAT的镜像。环境如下: 编写dockerfile,内容如下: 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 #Version:0.0.1 #指定使用哪个基础镜像 FROMcentos:6.6 #说明该镜像的制作者和联系方式 MAINTAINERRex.chenrex.chen@aaa.com #设置标签,不是必须的只是为了说明里面的版本查看起来方便 LABELTomcat= "8.5.13" JDK= "1.8.0_111" #清理一下YUM源,这个不是必须的只是为了临时通过YUM安装软件方便 RUNyumcleanall #复制安装程序到指定目录,我这里使用COPY命令只是因为我要自行解压缩 ENVSOFT_DEST /usr/local/src ENVTOMCAT_APP_NAMEapache-tomcat-8.5.13. tar .gz ENVJDK_APP_NAMEjdk-8u111-linux-x64. tar .gz ADDtomcat/$TOMCAT_APP_NAME$SOFT_DEST ADDjdk/$JDK_APP_NAME$SOFT_DEST #拷贝程序到指定目录并设置环境变量 WORKDIR$SOFT_DEST RUN[ "mv" , "./jdk1.8.0_111" , "/usr" ] RUN[ "mkdir" , "/work/apps" , "-p" ] RUN[ "mv" , "./apache-tomcat-8.5.13" , "/work/apps" ] ENVJAVA_HOME "/usr/jdk1.8.0_111" ENVPATH$JAVA_HOME /bin :$PATH ENVCATALINA_HOME "/work/apps/apache-tomcat-8.5.13" ENVPATH$CATALINA_HOME /bin :$PATH #ENTRYPOINT命令是指定在容器启动时执行的命令,CMD中指定使用run,因为catalina.shstart是后台运行,run是前台运行 ENTRYPOINT[ "catalina.sh" ] CMD[ "run" ] #设置容器内的应用程序使用容器的哪个端口 EXPOSE8080 构建镜像 1 dockerbuild-ttomcat8:0.1. 过程如下 查看构建的镜像 查看一下我们之前定义的标签 1 2 dockerinspecttomcat8:0.1-- format = '``.`ContainerConfig`.`Labels`.`Tomcat`' dockerinspecttomcat8:0.1-- format = '``.`ContainerConfig`.`Labels`.`JDK`' 启动容器 1 dockerrun-d-p8080--namejspSrv01tomcat8:0.1 测试访问 本文转自linuxjavachen 51CTO博客,原文链接:http://blog.51cto.com/littledevil/1914060,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

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

腾讯云软件源

腾讯云软件源

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

Nacos

Nacos

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

Rocky Linux

Rocky Linux

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

用户登录
用户注册