首页
关于
友链
Search
1
wlop 4K 壁纸 4k8k 动态 壁纸
1,008 阅读
2
Docker搭建Typecho博客
645 阅读
3
Nacos持久化MySQL问题-解决方案
639 阅读
4
滑动时间窗口算法
515 阅读
5
keytool证书导入
496 阅读
解决方案
JAVA基础
JVM
多线程
开源框架
数据库
前端
分布式
框架整合
中间件
容器部署
设计模式
数据结构与算法
开发工具
百度网盘资源
天翼网盘资源
阿里网盘资源
登录
Search
标签搜索
java
javase
docker
java8
springboot
thread
spring
分布式
mysql
锁
linux
redis
源码
typecho
centos
git
map
lambda
stream
nginx
少年
累计撰写
184
篇文章
累计收到
14
条评论
首页
栏目
解决方案
JAVA基础
JVM
多线程
开源框架
数据库
前端
分布式
框架整合
中间件
容器部署
设计模式
数据结构与算法
开发工具
百度网盘资源
天翼网盘资源
阿里网盘资源
页面
关于
友链
搜索到
184
篇与
的结果
2023-10-07
2023国庆川西自驾游
2023国庆川西自驾游国庆在家待了2天,自驾游川西3天,提前2天回来。整个行程3天,时间比较紧,全程700公里左右,主要景点:红海子、斯丁措、鱼子西、新都桥、折多山。自驾车型:城市SUV,1.4T排量。自驾前准备:0、安全:检车辆车胎气压、油、玻璃水、机油等情况。1、药品:防高反药、氧气筒,一些退烧药、感冒药、葡萄糖、碘伏等药品。2、衣服:冬季羽绒服、保暖裤、防风外套、短袖T恤额、长袖秋衣、牛仔裤、运动鞋2双。3、棉絮、厚被子、雨伞、遮阳帽、防嗮袖。4、方便面、矿泉水、水果、零食、红牛、八宝粥。5、工具:水果刀、湿巾纸、干纸巾、透明胶、剪刀、灭火器、帐篷、超大保温杯。上面有些东西不是必须的,只是防止为了突发情况时使用,比如半夜在高速堵车、或者高速上车外了,或者车着火了等极端情况。人员:计划自己和老爸2人自驾的,因为妈身体不太好,也不想去那么远的地方,老婆要带儿子回娘家玩,由于担心开车太累或者出现紧急情况所以叫上了亲姐,结果侄儿也要去,所以一路上4个人,能开车的就我和姐。线路规划:计划路线:成都环球上高速->京昆高速->雅叶高速->康定实际路线:成都环球上高速->京昆高速->雅叶高速->泸定县本来计划先到达康定住一晚,第二天开始游玩。但是用于第3天中午吃了午饭才从成都出发,6个小时才能到达康,预估到不了康定,所以第一天先到泸定县住了一晚,晚上逛了一下泸定县,至此第一天就结束了,第一天影响比较深的就是下高速后进泸定县的路比较陡,城市很难见到,然后就是所谓的勇士路,很堵,停车场爆满,直接开发泸定县城附近在找到合适停车地方。第二天一大早,到泸定县吃了早餐,逛了泸定桥、大渡河、泸定纪念公园就直接出发康定红海子,期间途径康定县城堵车严重,之后翻过折多山(堵得要命)。在上折多山途中停车弄了一碗泡面当作午餐、吃了一些水果。然后一路拍照,之后逛了红海子、斯丁措、鱼子西、新都桥,经过康定机场。空气、天气很好,蓝天白云、就是太堵了。第二天时间比较紧,加上姐高反比较严重,所以一直催着到低海拔的新都桥镇去休息。我和老爸高反还不是特别严重。上面几个地方拍照完后,下午直接奔新都桥,也是一路堵,下午半天差不多就一直堵在车上,就这样第二天就匆匆忙忙的完了。晚上到达新都桥找好住宿后,休息一会在新都桥镇上吃了晚上,就早早的休息了。第三天吃完早饭,一早去了新都桥,结果和想象的景色不太一样,拍了一些照片。然后看到附近的贡嘎山观景台,去爬了一会实在爬不动,加上还要开车就爬了一点点。接着买了一些牛肉120元/每斤。接着就往回走了,本来计划是还要到塔公草原、墨石公园玩的,但是姐高反加姐只有3天假期所以就放弃了。下午返回途径318国道,回途中印象最深的就是回来的318国道开车比较有意思,陡峭、弯急,回途经过折多山也是堵的要命。去和回的高速上基本不堵车,车速保持在110~125左右,开车印象最深的就是二郎山附近的几个隧道全长20公里左右,去基本是上坡,回的时候基本保持80码的速度,全是下坡,基本不怎么耗油。3天全是我一个人开,膝盖都酸了,翻越折多山时叫姐开,她不敢开,最后还是自己来,3天全部行车700公里左右。来途径成都浦江服务区、雅安天全服务区、泸定服务区,回去途中在雅安天全服务区、浦江服务区休息了一会。回家途中天全服务区侄儿开门不小心将旁边的马自达车门碰了一个小吭,陪了200元。幸好是个马子达,就当吸取教训吧。晚上达到姐家,爸和姐去超市买菜炒了一份回锅肉、买了一瓶大可乐,吃完饭,去了附近姐经常自助洗车的洗车店4个人一起把车洗了,晚上开车回家。感受:3天时间比较紧,加上高反,各景点没有好好玩,各个地方的乡镇没有好好逛逛、好吃的也没怎么吃到。感觉像是去拍了照就走了,没什么留下也没带走什么,老爸、老姐一直在喊太累,可能是晚上没修改好。最大的好处就是开车技术应该有了一定提升。在姐高反严重,都要打120时,感受最深的就是,身体健康才是本钱,回去还是要坚持运动,保持一项个人喜欢的运动,保持好的生活习惯。晚上急急忙忙的记录了一下,就到这吧,儿子媳妇都睡了,我也想睡了。
2023年10月07日
114 阅读
3 评论
4 点赞
2023-09-06
近况
近况其实一直想写一些关于生活方面的文章,但是由于担心隐私泄露以及文笔不好,表达能力不好,就搁置了。最近突然觉得还是应该记录一些生活,有时有很多想写的,但是组织语言又不好,估计只能写一小段,就不好意思写了。先分享一首刚刚听见的歌曲,感觉此刻听着还不错。《要山要海要自由》{music id="2042878838" color="#1989fa" autoplay="autoplay"/}要孩子一样的笑容要风晕开岁月褶皱要山要海要自由要大雨磅礴扑向我要清澈透明的天空要一口解忧的烈酒.....今晚带儿子游泳,回家已经9点了,感觉时间比较晚了,因为回来还要刷牙喝奶,然后才上传睡觉,但是媳妇还是要给儿子复习一下在培训机构学习的英语课程,不然估计下周又忘了。最近一直没怎么学习技术方面的东西,一是下班回家后不想动,二是最近想运动一下,原因是感觉有白头发了,加上以前一直晚睡,养成了不好的习惯。今晚媳妇和儿子睡了,才有自己时间听听歌,看看新闻,才静下心来写这篇文章。也不知道写些什么,就说一下这种关于运动的事情吧。周一下班骑自行车回家,从公司到小区门口6.05公里,用时23分钟,平均速度15.52km/h.周二晚上19:30吃了晚饭,带着儿子去游泳馆游到20:30回家,接着玩了会手机23:15睡觉。周三今晚19:10出发去游泳馆,20:20冲洗骑车回家,到家21:00,接口给儿子冲奶,儿子喝完奶媳妇帮儿子刷牙。21:20媳妇在床上给儿子复习英语,然后每晚必备的睡前故事。大概21:40睡觉,感觉时间还是比较晚了。明天周四不去了,一是时间有点紧,二是刚上一年级,才开学几天,还是要以学校学习为主。计划明晚让儿子早点睡,老师提倡的是20:30准备睡觉。附上几张儿子开学的照片记念一下儿子开学当天。感觉上面写的都是一些口水话,自认为没有任何文笔,记得初中时语文,英文差的不是一点点。今晚就写到这吧,不管有没有人看,就当个人垃圾桶吧。本来想放几张儿子一年级开学照片,但是水果机的.HEIC格式图片windows居然不能打开,那就先搞个解码器,等可以预览了在放吧。找到一张大运会期间的照片。
2023年09月06日
100 阅读
0 评论
2 点赞
2023-08-13
Kafka内外网隔离配置及安装使用
环境版本说明环境:CentOS7版本:JDK1.8、Zookeeper-3.4.14、Kafka2.12-1.0.2JDK安装JDK1.8安装rpm -ivh jdk-8u261-linux-x64.rpm环境变量配置vim /etc/profile最后一行加上配置export JAVA_HOME=/usr/java/jdk1.8.0_261-amd64 export PATH=$PATH:$JAVA_HOME/binjdk验证java -versionZookeeper安装安装tar -zxf zookeeper-3.4.14.tar.gz -C /opt环境变量配置vim /etc/profileZOOKEEPER_PREFIX指向Zookeeper的解压目录export ZOOKEEPER_PREFIX=/opt/zookeeper-3.4.14将Zookeeper的bin目录添加到PATH中export PATH=$PATH:$ZOOKEEPER_PREFIX/bin设置环境变量ZOO_LOG_DIR,指定Zookeeper保存日志的位置export ZOO_LOG_DIR=/var/zookeeper/log使配置生效source /etc/profile修改zookeeper配置cd conf cp zoo_sample.cfg zoo.cfg修改配置文件zoo.cfgvi zoo.cfg修改zookeeper数据存放位置配置修改前dataDir=/tmp/zookeeper修改后dataDir=/var/zookeeper/data启动zookeeper进入zookeeper安装目录=/var/zookeeper/bin启动zookeeperzkServer.sh start查看zookeeper状态zkServer.sh statusKafka安装安装kafkatar -zxf kafka_2.12-1.0.2.tgz -C /opt修改环境变量vi /etc/profile最后加上配置export KAFKA_HOME=/opt/kafka_2.12-1.0.2 export PATH=$PATH:$KAFKA_HOME/bin使配置生效source /etc/profile修改kafka配置修改server.properties配置文件vi server.properties修改链接zookeeper地址:123行修改前zookeeper.connect=localhost:2181修改后zookeeper.connect=localhost:2181/mykafka说明:表示在zookeeper目录下会创建一个mykafka节点修改消息持久化目录:60行修改前log.dirs=/tmp/kafka-logs修改后log.dirs=/var/kafka/kafka-logs创建持久化目录文件夹mkdir -p /var/kafka/kafka-logs脚本说明cd /opt/kafka_2.12-1.0.2/bin说明:kafka-topics.sh 操作主题的 kafka-server-start.sh kafka启动 kafka-server-stop.sh kafka关闭 kafka-console-consumer.sh 命令行里使用消费者 kafka-console-producer.sh 命令行里面使用的生产者启动kafka注意是进入到bin目录下的kafka-server-start.sh ../config/server.properties客户端测试使用zookeeper客户端登录zookeeper,复制启动窗口执行zkCli.sh。(注意:必须复制服务器启动窗口来执行,不然没有脚本。)zkCli.sh查看zookeeper的根节点ls /查看mykafkals /mykafka说明:cluster 集群 controller 控制器 controller_epoch 控制器纪元数据 brokers broker admin 管理者 isr_change_notification 同步的副本 consumers 消费者 log_dir_event_notification log_dir事件通知 latest_producer_id_block 最后一个生产者 config 配置客户端退出zookeeperquit关闭kafkakafka-server-stop.sh主题后台启动kafkakafka-server-start.sh -daemon /opt/kafka_2.12-1.0.2/config/server.properties查看kafka进程信息ps aux | grep kafka主题脚本使用帮助,直接执行脚本,显示主题脚本使用参数。kafka-topics.sh使用参数如下:[root@default-dev bin]# kafka-topics.sh Create, delete, describe, or change a topic. Option Description ------ ----------- --alter Alter the number of partitions, replica assignment, and/or configuration for the topic. --config <String: name=value> A topic configuration override for the topic being created or altered.The following is a list of valid configurations: cleanup.policy compression.type delete.retention.ms file.delete.delay.ms flush.messages flush.ms follower.replication.throttled. replicas index.interval.bytes leader.replication.throttled.replicas max.message.bytes message.format.version message.timestamp.difference.max.ms message.timestamp.type min.cleanable.dirty.ratio min.compaction.lag.ms min.insync.replicas preallocate retention.bytes retention.ms segment.bytes segment.index.bytes segment.jitter.ms segment.ms unclean.leader.election.enable See the Kafka documentation for full details on the topic configs. --create Create a new topic. --delete Delete a topic --delete-config <String: name> A topic configuration override to be removed for an existing topic (see the list of configurations under the --config option). --describe List details for the given topics. --disable-rack-aware Disable rack aware replica assignment --force Suppress console prompts --help Print usage information. --if-exists if set when altering or deleting topics, the action will only execute if the topic exists --if-not-exists if set when creating topics, the action will only execute if the topic does not already exist --list List all available topics. --partitions <Integer: # of partitions> The number of partitions for the topic being created or altered (WARNING: If partitions are increased for a topic that has a key, the partition logic or ordering of the messages will be affected --replica-assignment <String: A list of manual partition-to-broker broker_id_for_part1_replica1 : assignments for the topic being broker_id_for_part1_replica2 , created or altered. broker_id_for_part2_replica1 : broker_id_for_part2_replica2 , ...> --replication-factor <Integer: The replication factor for each replication factor> partition in the topic being created. --topic <String: topic> The topic to be create, alter or describe. Can also accept a regular expression except for --create option --topics-with-overrides if set when describing topics, only show topics that have overridden configs --unavailable-partitions if set when describing topics, only show partitions whose leader is not available --under-replicated-partitions if set when describing topics, only show under replicated partitions --zookeeper <String: urls> REQUIRED: The connection string for the zookeeper connection in the form host:port. Multiple URLS can be given to allow fail-over. 注意:REQUIRED为必选参数,如上面的--zookeeper链接地址。查看所有可用主题kafka-topics.sh --zookeeper localhost:2181/mykafka --list创建主题kafka-topics.sh --zookeeper localhost/mykafka --create --topic topic_1 --partitions 1 --replication-factor 1说明:zookeeper端口可省略,使用的是默认的。--topic: 创建主题名字--partitions:创建几个分区,便于横向扩展。--replication-factor:一个分区创建几个副本,高可用。注意:当只有一个服务一个broker时,是没有意义的,当服务宕机了,数据也没了。因此--replication-factor副本必须在不同的kafka服务器上,才能实现高可用。再次查看可用主题kafka-topics.sh --zookeeper localhost:2181/mykafka --list查看主题详细信息kafka-topics.sh --zookeeper localhost/mykafka --describe --topic topic_1说明:topic_1有一个0号分区,在0号服务器上。实例创建一个topc_2主题,5个分区,每个分区1个副本.kafka-topics.sh --zookeeper localhost/mykafka --create --topic topic_2 --partitions 5 --replication-factor 1查看可用主题kafka-topics.sh --zookeeper localhost:2181/mykafka --list查看topic_2主题详情kafka-topics.sh --zookeeper localhost/mykafka --describe --topic topic_2说明:5个分区都在0号服务器上。消费消费脚本使用帮助:kafka-console-consumer.sh使用参数:The console consumer is a tool that reads data from Kafka and outputs it to standard output. Option Description ------ ----------- --blacklist <String: blacklist> Blacklist of topics to exclude from consumption. --bootstrap-server <String: server to REQUIRED (unless old consumer is connect to> used): The server to connect to. --consumer-property <String: A mechanism to pass user-defined consumer_prop> properties in the form key=value to the consumer. --consumer.config <String: config file> Consumer config properties file. Note that [consumer-property] takes precedence over this config. --csv-reporter-enabled If set, the CSV metrics reporter will be enabled --delete-consumer-offsets If specified, the consumer path in zookeeper is deleted when starting up --enable-systest-events Log lifecycle events of the consumer in addition to logging consumed messages. (This is specific for system tests.) --formatter <String: class> The name of a class to use for formatting kafka messages for display. (default: kafka.tools. DefaultMessageFormatter) --from-beginning If the consumer does not already have an established offset to consume from, start with the earliest message present in the log rather than the latest message. --group <String: consumer group id> The consumer group id of the consumer. --isolation-level <String> Set to read_committed in order to filter out transactional messages which are not committed. Set to read_uncommittedto read all messages. (default: read_uncommitted) --key-deserializer <String: deserializer for key> --max-messages <Integer: num_messages> The maximum number of messages to consume before exiting. If not set, consumption is continual. --metrics-dir <String: metrics If csv-reporter-enable is set, and directory> this parameter isset, the csv metrics will be output here --new-consumer Use the new consumer implementation. This is the default, so this option is deprecated and will be removed in a future release. --offset <String: consume offset> The offset id to consume from (a non- negative number), or 'earliest' which means from beginning, or 'latest' which means from end (default: latest) --partition <Integer: partition> The partition to consume from. Consumption starts from the end of the partition unless '--offset' is specified. --property <String: prop> The properties to initialize the message formatter. --skip-message-on-error If there is an error when processing a message, skip it instead of halt. --timeout-ms <Integer: timeout_ms> If specified, exit if no message is available for consumption for the specified interval. --topic <String: topic> The topic id to consume on. --value-deserializer <String: deserializer for values> --whitelist <String: whitelist> Whitelist of topics to include for consumption. --zookeeper <String: urls> REQUIRED (only when using old consumer): The connection string for the zookeeper connection in the form host:port. Multiple URLS can be given to allow fail-over. REQUIRED:必填参数unless old consumer is used:使用老消费者--bootstrap-server <String: server to REQUIRED (unless old consumer is connect to> used): The server to connect to. only when using old consumer:使用旧消费时使用--zookeeper <String: urls> REQUIRED (only when using old consumer): The connection string for the zookeeper connection in the form host:port. Multiple URLS can be given to allow fail-over.消费者消费链接Kafka服务端,当有多台Kafka时,只需要链接其中一台服务即可。注意,消费者消费端口是9092了。kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic topic_1说明:--bootstrap-server localhost:9092:指定kafka服务地址端口--topic topic_1:指定消费的主题测试界面像是卡住了,不管。消费者API使用参数配置说明生产生产脚本使用帮助kafka-console-producer.sh使用参数:Read data from standard input and publish it to Kafka. Option Description ------ ----------- --batch-size <Integer: size> Number of messages to send in a single batch if they are not being sent synchronously. (default: 200) --broker-list <String: broker-list> REQUIRED: The broker list string in the form HOST1:PORT1,HOST2:PORT2. --compression-codec [String: The compression codec: either 'none', compression-codec] 'gzip', 'snappy', or 'lz4'.If specified without value, then it defaults to 'gzip' --key-serializer <String: The class name of the message encoder encoder_class> implementation to use for serializing keys. (default: kafka. serializer.DefaultEncoder) --line-reader <String: reader_class> The class name of the class to use for reading lines from standard in. By default each line is read as a separate message. (default: kafka. tools. ConsoleProducer$LineMessageReader) --max-block-ms <Long: max block on The max time that the producer will send> block for during a send request (default: 60000) --max-memory-bytes <Long: total memory The total memory used by the producer in bytes> to buffer records waiting to be sent to the server. (default: 33554432) --max-partition-memory-bytes <Long: The buffer size allocated for a memory in bytes per partition> partition. When records are received which are smaller than this size the producer will attempt to optimistically group them together until this size is reached. (default: 16384) --message-send-max-retries <Integer> Brokers can fail receiving the message for multiple reasons, and being unavailable transiently is just one of them. This property specifies the number of retires before the producer give up and drop this message. (default: 3) --metadata-expiry-ms <Long: metadata The period of time in milliseconds expiration interval> after which we force a refresh of metadata even if we haven't seen any leadership changes. (default: 300000) --old-producer Use the old producer implementation. --producer-property <String: A mechanism to pass user-defined producer_prop> properties in the form key=value to the producer. --producer.config <String: config file> Producer config properties file. Note that [producer-property] takes precedence over this config. --property <String: prop> A mechanism to pass user-defined properties in the form key=value to the message reader. This allows custom configuration for a user- defined message reader. --queue-enqueuetimeout-ms <Integer: Timeout for event enqueue (default: queue enqueuetimeout ms> 2147483647) --queue-size <Integer: queue_size> If set and the producer is running in asynchronous mode, this gives the maximum amount of messages will queue awaiting sufficient batch size. (default: 10000) --request-required-acks <String: The required acks of the producer request required acks> requests (default: 1) --request-timeout-ms <Integer: request The ack timeout of the producer timeout ms> requests. Value must be non-negative and non-zero (default: 1500) --retry-backoff-ms <Integer> Before each retry, the producer refreshes the metadata of relevant topics. Since leader election takes a bit of time, this property specifies the amount of time that the producer waits before refreshing the metadata. (default: 100) --socket-buffer-size <Integer: size> The size of the tcp RECV size. (default: 102400) --sync If set message send requests to the brokers are synchronously, one at a time as they arrive. --timeout <Integer: timeout_ms> If set and the producer is running in asynchronous mode, this gives the maximum amount of time a message will queue awaiting sufficient batch size. The value is given in ms. (default: 1000) --topic <String: topic> REQUIRED: The topic id to produce messages to. --value-serializer <String: The class name of the message encoder encoder_class> implementation to use for serializing values. (default: kafka. serializer.DefaultEncoder) 注意:REQUIRED必填参数生产者链接kafka服务kafka-console-producer.sh --broker-list localhost:9092 --topic topic_1说明:--broker-list:指定broker,如果有很多太kafka服务器,只需要指定2个地址接口,这里只有一台kafka服务器,只指定一个。--topic:指定要发送消息到那个topic主题。此时生产者窗口也像卡住了,说明进入了发送消息界面。生产者API使用参数配置说明消息发送接收测试注意:提示如下信息检查主题名称是否错误WARN [Producer clientId=console-producer] Error while fetching metadata with correlation id 8可查看可用主题:明确消费主题和生产者是否是使用的一个主题。kafka-topics.sh --zookeeper localhost:2181/mykafka --list消息的发送与接受测试结果:注意:当关闭消费者后,生产者继续发送消息,当生产者重新链接后,只能接受到后面生产者重新发送的消息。消费历史消息如果要消费以前的消息可以指定参数--from-beginningkafka-console-consumer.sh --bootstrap-server localhost:9092 --topic topic_1 --from-beginning查看持久化数据ca /var/kafka/kafka-logs可以看到很多偏移量的文件。服务端参数配置主要是服务器kafka配置文件server.properties的配置zookeeper.connect该参数用于配置kafka要链接的Zookeeper/集群地址。它的值是一个字符串,使用都好分割zookeeper的多个地址。Zookeeper的单个地址是host:port形式的,可以在最后添加kafka在zookeeper中的根节点路径。例如: zookeeper.connect=192.1681.1:2181,192.1681.2:2181,192.1681.3:2181,192.1681.4:2181/mykafka最好服务器地址数量过半,后面zookeeper存放路径/mykafka写一个就好了。listeners用于指定当前Broker向外发布服务的地址和端口。与advertised.listeners配合,用于做内外网隔离。注意:端口号也是可以修改的。内外网隔离配置listeners用于配置broker监听的URL以及监听器名称列表,使用逗号隔开多个URL及监听器名称。例如:服务器有2个ip,ip如下则配置如下:listeners配置:注意监听器名称不能相同,端口不能相同。PLAINTEXT代表了都使用PLAINTEXT协议,也代表了监听器的名称,但是名称又不能相同,因此使用映射配置参数listner.sercurity.protocol.map。加上上面配置后,启动还是会报错,因此必须加上如下配置:整体说明:注意kafka是使用的PLAINTEXT协议listener.security.protocol.map=INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT listeners=INTERNAL://10.0.2.15:9000,EXTERNAL://192.168.56.30:9001 advertised.listeners=EXTERNAL://192.168.56.30:9001 inter.broker.listener.name=EXTERNALlistener.security.protocol.map:解决监听协议、监听器名称一样问题。listeners:集群多台服务地址advertised.listeners:暴露给消费者生产者,以及节点间通讯使用的地址和端口(需要将该地址发布到zookeeper供客户端使用,如果客户端使用的地址与listeners配置不同),而另一个地址端口INTERNAL://10.0.2.15:9000则可用于内部管理kafka。inter.broker.listener.name:暴力给消费者生产者使用监听的监听器名称,如果要暴露多个直接可以逗号隔开多加几个,前提是listeners里面有的。listener.security.protocol.map用于内外网隔离配置,监听器名称和安全协议的映射配置。例如:将内外网隔离,即使他们都使用SSL,上面的配置问题就可以加下面参数解决。listener.security.protocol.map=INTERNAL:SSL,EXTERNAL:SSL说明:INTERNAL,EXTERNAL:代表监听器名称SSL:代表都是使用SSL协议。加上这个参数配置,就可以解决上面的监听器名称和协议冲突的问题了。注意:每个监听器的名称只能在map中出现一次。如果监听器名称代表的不是安全协议,必须配置listener.security.protocol.map。每个监听器必须使用不同的网络端口。查看zoopeeper信息:客户端脚本链接zookeeper:zkCli.sh查看kafka信息get /mykafka/brokers/ids/0查看可用主题:kafka-topics.sh --zookeeper localhost:2181/mykafka --listbroker.id该属性用于唯一标记一个kafka的Broker,它的值是一个任意integer值。当kafka以分布式集群部署使用时,非常重要。最好该值只跟该Broker所在的物理主机有关的,如主机名为host1.yanxizhu.com,则broker.id=1,如果主机名为192.168.56.30,则broker.id=30.log.dir通过该属性的值,指定kafka在磁盘上保存消息的日志片段的目录。它时一组用逗号分隔的本地文件系统路径。如果指定了多个路径,那么broker会根据”最少使用“原则,把同一个分区的日志片段保存到同一个路径下。broker会往拥有最少数目分区的路径新增分区,而不是往拥有最小磁盘空间的路径新增分区。
2023年08月13日
142 阅读
0 评论
1 点赞
2023-07-29
CentOS安装hugo
CentOS安装hugo1、yum无法直接安装hugo,首先添加repo[daftaupe-hugo] name=Copr repo for hugo owned by daftaupe baseurl=https://copr-be.cloud.fedoraproject.org/results/daftaupe/hugo/epel-7-$basearch/ type=rpm-md skip_if_unavailable=True gpgcheck=1 gpgkey=https://copr-be.cloud.fedoraproject.org/results/daftaupe/hugo/pubkey.gpg repo_gpgcheck=0 enabled=12、安装hugoyum -y install hugo3、创建博客hugo new site blog
2023年07月29日
95 阅读
1 评论
2 点赞
2023-07-03
[ERR] 1067 - Invalid default value for 'created_date_' [ERR]
[ERR] 1067 - Invalid default value for 'created_date_'[ERR]set global sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
2023年07月03日
75 阅读
0 评论
1 点赞
2023-07-02
Git代理配置与取消
Git代理配置与取消代理查看是否配置代理git config --global http.proxy配置代理git config --global http.proxy http://127.0.0.1:10809 git config --global https.proxy http://127.0.0.1:10809 取消代理$ git config --global --unset http.proxy $ git config --global --unset https.proxy注意:http://127.0.0.1:10809为自己代理地址,根据自己情况修改。
2023年07月02日
70 阅读
0 评论
2 点赞
2023-05-10
Docker数据存储
Docker数据存储默认情况下,在运行中的容器里创建的文件,被保存在一个可写的容器层:如果容器被删除了,则数据也没有了这个可写的容器层是和特定的容器绑定的,也就是这些数据无法方便的和其它容器共享Docker主要提供了两种方式做数据的持久化Data Volume, 由Docker管理,(/var/lib/docker/volumes/ Linux), 持久化数据的最好方式Bind Mount,由用户指定存储的数据具体mount在系统什么位置一、Data Volume环境准备准备一个Dockerfile 和一个 my-cron的文件$ ls Dockerfile my-cron $ more Dockerfile FROM alpine:latest RUN apk update RUN apk --no-cache add curl ENV SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/v0.1.12/supercronic-linux-amd64 \ SUPERCRONIC=supercronic-linux-amd64 \ SUPERCRONIC_SHA1SUM=048b95b48b708983effb2e5c935a1ef8483d9e3e RUN curl -fsSLO "$SUPERCRONIC_URL" \ && echo "${SUPERCRONIC_SHA1SUM} ${SUPERCRONIC}" | sha1sum -c - \ && chmod +x "$SUPERCRONIC" \ && mv "$SUPERCRONIC" "/usr/local/bin/${SUPERCRONIC}" \ && ln -s "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic COPY my-cron /app/my-cron WORKDIR /app VOLUME ["/app"] # RUN cron job CMD ["/usr/local/bin/supercronic", "/app/my-cron"] $ $ more my-cron */1 * * * * date >> /app/test.txt构建镜像$ docker image build -t my-cron . $ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE my-cron latest e9fbd9a562c9 4 seconds ago 24.7MB创建容器(不指定-v参数)此时Docker会自动创建一个随机名字的volume,去存储我们在Dockerfile定义的volume VOLUME ["/app"]$ docker run -d my-cron 9a8fa93f03c42427a498b21ac520660752122e20bcdbf939661646f71d277f8f $ docker volume ls DRIVER VOLUME NAME local 043a196c21202c484c69f2098b6b9ec22b9a9e4e4bb8d4f55a4c3dce13c15264 $ docker volume inspect 043a196c21202c484c69f2098b6b9ec22b9a9e4e4bb8d4f55a4c3dce13c15264 [ { "CreatedAt": "2021-06-22T23:06:13+02:00", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/043a196c21202c484c69f2098b6b9ec22b9a9e4e4bb8d4f55a4c3dce13c15264/_data", "Name": "043a196c21202c484c69f2098b6b9ec22b9a9e4e4bb8d4f55a4c3dce13c15264", "Options": null, "Scope": "local" } ]在这个Volume的mountpoint可以发现容器创建的文件。创建容器(指定-v参数)在创建容器的时候通过 -v 参数我们可以手动的指定需要创建Volume的名字,以及对应于容器内的路径,这个路径是可以任意的,不必需要在Dockerfile里通过VOLUME定义。比如我们把上面的Dockerfile里的VOLUME删除FROM alpine:latest RUN apk update RUN apk --no-cache add curl ENV SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/v0.1.12/supercronic-linux-amd64 \ SUPERCRONIC=supercronic-linux-amd64 \ SUPERCRONIC_SHA1SUM=048b95b48b708983effb2e5c935a1ef8483d9e3e RUN curl -fsSLO "$SUPERCRONIC_URL" \ && echo "${SUPERCRONIC_SHA1SUM} ${SUPERCRONIC}" | sha1sum -c - \ && chmod +x "$SUPERCRONIC" \ && mv "$SUPERCRONIC" "/usr/local/bin/${SUPERCRONIC}" \ && ln -s "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic COPY my-cron /app/my-cron WORKDIR /app # RUN cron job CMD ["/usr/local/bin/supercronic", "/app/my-cron"]重新build镜像,然后创建容器,加-v参数$ docker image build -t my-cron . $ docker container run -d -v cron-data:/app my-cron 43c6d0357b0893861092a752c61ab01bdfa62ea766d01d2fcb8b3ecb6c88b3de $ docker volume ls DRIVER VOLUME NAME local cron-data $ docker volume inspect cron-data [ { "CreatedAt": "2021-06-22T23:25:02+02:00", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/cron-data/_data", "Name": "cron-data", "Options": null, "Scope": "local" } ] $ ls /var/lib/docker/volumes/cron-data/_data my-cron $ ls /var/lib/docker/volumes/cron-data/_data my-cron test.txt环境清理强制删除所有容器,系统清理和volume清理$ docker rm -f $(docker container ps -aq) $ docker system prune -f $ docker volume prune -f二、Bind Mount只需要将-v的data volume换成指定路径即可。windows下的linux就可以直接挂载到磁盘,linx的可以直接查看。例如mysqldocker run -p 3306:3306 --name mysql \ -v /mydata/mysql/log:/var/log/mysql \ -v /mydata/mysql/data:/var/lib/mysql \ -v /mydata/mysql/conf:/etc/mysql \ -e MYSQL_ROOT_PASSWORD=密码 \ -d mysql:5.7-v /mydata/mysql/log:/var/log/mysql这里就是将容器中/var/log/mysql日志,通过Bind Mount持久化到linux主机的/mydata/mysql/log目录。多个机器之间的容器共享数据官方参考链接 https://docs.docker.com/storage/volumes/#share-data-among-machinesDocker的volume支持多种driver。默认创建的volume driver都是local$ docker volume inspect vscode [ { "CreatedAt": "2021-06-23T21:33:57Z", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/vscode/_data", "Name": "vscode", "Options": null, "Scope": "local" } ]这一节我们看看一个叫sshfs的driver,如何让docker使用不在同一台机器上的文件系统做volume环境准备准备三台Linux机器,之间可以通过SSH相互通信。hostnameipssh usernamessh passworddocker-host1192.168.200.10vagrantvagrantdocker-host2192.168.200.11vagrantvagrantdocker-host3192.168.200.12vagrantvagrant安装plugin在其中两台机器上安装一个plugin vieux/sshfs[vagrant@docker-host1 ~]$ docker plugin install --grant-all-permissions vieux/sshfs latest: Pulling from vieux/sshfs Digest: sha256:1d3c3e42c12138da5ef7873b97f7f32cf99fb6edde75fa4f0bcf9ed277855811 52d435ada6a4: Complete Installed plugin vieux/sshfs[vagrant@docker-host2 ~]$ docker plugin install --grant-all-permissions vieux/sshfs latest: Pulling from vieux/sshfs Digest: sha256:1d3c3e42c12138da5ef7873b97f7f32cf99fb6edde75fa4f0bcf9ed277855811 52d435ada6a4: Complete Installed plugin vieux/sshfs创建volume[vagrant@docker-host1 ~]$ docker volume create --driver vieux/sshfs \ -o sshcmd=vagrant@192.168.200.12:/home/vagrant \ -o password=vagrant \ sshvolume查看[vagrant@docker-host1 ~]$ docker volume ls DRIVER VOLUME NAME vieux/sshfs:latest sshvolume [vagrant@docker-host1 ~]$ docker volume inspect sshvolume [ { "CreatedAt": "0001-01-01T00:00:00Z", "Driver": "vieux/sshfs:latest", "Labels": {}, "Mountpoint": "/mnt/volumes/f59e848643f73d73a21b881486d55b33", "Name": "sshvolume", "Options": { "password": "vagrant", "sshcmd": "vagrant@192.168.200.12:/home/vagrant" }, "Scope": "local" } ]创建容器挂载Volume创建容器,挂载sshvolume到/app目录,然后进入容器的shell,在/app目录创建一个test.txt文件[vagrant@docker-host1 ~]$ docker run -it -v sshvolume:/app busybox sh Unable to find image 'busybox:latest' locally latest: Pulling from library/busybox b71f96345d44: Pull complete Digest: sha256:930490f97e5b921535c153e0e7110d251134cc4b72bbb8133c6a5065cc68580d Status: Downloaded newer image for busybox:latest / # / # ls app bin dev etc home proc root sys tmp usr var / # cd /app /app # ls /app # echo "this is ssh volume"> test.txt /app # ls test.txt /app # more test.txt this is ssh volume /app # /app #这个文件我们可以在docker-host3上看到[vagrant@docker-host3 ~]$ pwd /home/vagrant [vagrant@docker-host3 ~]$ ls test.txt [vagrant@docker-host3 ~]$ more test.txt this is ssh volume
2023年05月10日
94 阅读
1 评论
1 点赞
2023-04-25
Dockerfile使用技巧
Dockerfile技巧一、Docker build缓存当build镜像时,如果Docker build文件发生变化或者build镜像分层某一层发生变化就不会使用cache缓存。技巧:将Dockerfile中经常发生改变的放到后面,不发生改变的发前面。这样就算最后发生改变的不能使用cache缓存,但前面没变化也会加快build的速度。Docker build contextDocker是client-server架构,理论上Client和Server可以不在一台机器上。在构建docker镜像的时候,需要把所需要的文件由CLI(client)发给Server,这些文件实际上就是build context。$ dockerfile-demo more Dockerfile FROM python:3.9.5-slim RUN pip install flask WORKDIR /src ENV FLASK_APP=app.py COPY app.py /src/app.py EXPOSE 5000 CMD ["flask", "run", "-h", "0.0.0.0"] $ dockerfile-demo more app.py from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello, world!'执行镜像构建$ docker image build -t demo . Sending build context to Docker daemon 11.13MB Step 1/7 : FROM python:3.9.5-slim ---> 609da079b03a Step 2/7 : RUN pip install flask ---> Using cache ---> 955ce495635e Step 3/7 : WORKDIR /src ---> Using cache ---> 1c2f968e9f9b Step 4/7 : ENV FLASK_APP=app.py ---> Using cache ---> dceb15b338cf Step 5/7 : COPY app.py /src/app.py ---> Using cache ---> 0d4dfef28b5f Step 6/7 : EXPOSE 5000 ---> Using cache ---> 203e9865f0d9 Step 7/7 : CMD ["flask", "run", "-h", "0.0.0.0"] ---> Using cache ---> 35b5efae1293 Successfully built 35b5efae1293 Successfully tagged demo:latest. 这个参数就是代表了build context所指向的目录。第2行:Sending build context to Docker daemon 11.13MB,实际就是docker build context将.所指向文件夹里面所有的文件发送到Docker Server。因此当文件里面文件很多时,发送就比较大比较慢,所以进行保证指向的文件夹里面文件少一点。二、.dockerignore 文件配置需要忽略的文件,类似git里面.ignore文件一样。1、可以使image变小一点。2、加快build。3、忽略一些私密配置文件,如密码配置等。.vscode/ env/$ docker image build -t demo . Sending build context to Docker daemon 4.096kB Step 1/7 : FROM python:3.9.5-slim ---> 609da079b03a Step 2/7 : RUN pip install flask ---> Using cache ---> 955ce495635e Step 3/7 : WORKDIR /src ---> Using cache ---> 1c2f968e9f9b Step 4/7 : ENV FLASK_APP=app.py ---> Using cache ---> dceb15b338cf Step 5/7 : COPY . /src/ ---> a9a8f888fef3 Step 6/7 : EXPOSE 5000 ---> Running in c71f34d32009 Removing intermediate container c71f34d32009 ---> fed6995d5a83 Step 7/7 : CMD ["flask", "run", "-h", "0.0.0.0"] ---> Running in 7ea669f59d5e Removing intermediate container 7ea669f59d5e ---> 079bae887a47 Successfully built 079bae887a47 Successfully tagged demo:latest上面可以看到Sending build context to Docker daemon 4.096kB,从这里可以看到Docker build context忽略文件后,发送到docker server的文件变小了很多。三、镜像的多阶段构建适用于需要环境进行编译时。例如要将C语言程序build成一个镜像,然后通过docker容器执行。#include <stdio.h> void main(int argc, char *argv[]) { printf("hello %s\n", argv[argc - 1]); }docker build:因为需要C语言环境,因此选择一个gcc基础镜像,可以看到gcc基础环境比较到,c文件其实很小。FROM gcc:9.4 COPY hello.c /src/hello.c WORKDIR /src RUN gcc --static -o hello hello.c ENTRYPOINT [ "/src/hello" ] CMD []build和测试$ docker build -t hello . Sending build context to Docker daemon 5.12kB Step 1/6 : FROM gcc:9.4 ---> be1d0d9ce039 Step 2/6 : COPY hello.c /src/hello.c ---> Using cache ---> 70a624e3749b Step 3/6 : WORKDIR /src ---> Using cache ---> 24e248c6b27c Step 4/6 : RUN gcc --static -o hello hello.c ---> Using cache ---> db8ae7b42aff Step 5/6 : ENTRYPOINT [ "/src/hello" ] ---> Using cache ---> 7f307354ee45 Step 6/6 : CMD [] ---> Using cache ---> 7cfa0cbe4e2a Successfully built 7cfa0cbe4e2a Successfully tagged hello:latest $ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE hello latest 7cfa0cbe4e2a 2 hours ago 1.14GB gcc 9.4 be1d0d9ce039 9 days ago 1.14GB $ docker run --rm -it hello docker hello docker $ docker run --rm -it hello world hello world $ docker run --rm -it hello friends hello friends $gcc 9.4 be1d0d9ce039 9 days ago 1.14GB实际上当我们把hello.c编译完以后,并不需要这样一个大的GCC环境,一个小的alpine镜像就可以了。因此就可以使用多阶段构建。FROM gcc:9.4 AS builder COPY hello.c /src/hello.c WORKDIR /src RUN gcc --static -o hello hello.c FROM alpine:3.13.5 COPY --from=builder /src/hello /src/hello ENTRYPOINT [ "/src/hello" ] CMD []说明:AS 给gcc取一个名称builder,第2阶段COPY --from=builder /src/hello /src/hello,将编译好的c程序,放到新基础镜像alpine中,重新build成镜像。测试$ docker build -t hello-apline -f Dockerfile-new . Sending build context to Docker daemon 5.12kB Step 1/8 : FROM gcc:9.4 AS builder ---> be1d0d9ce039 Step 2/8 : COPY hello.c /src/hello.c ---> Using cache ---> 70a624e3749b Step 3/8 : WORKDIR /src ---> Using cache ---> 24e248c6b27c Step 4/8 : RUN gcc --static -o hello hello.c ---> Using cache ---> db8ae7b42aff Step 5/8 : FROM alpine:3.13.5 ---> 6dbb9cc54074 Step 6/8 : COPY --from=builder /src/hello /src/hello ---> Using cache ---> 18c2bce629fb Step 7/8 : ENTRYPOINT [ "/src/hello" ] ---> Using cache ---> 8dfb9d9d6010 Step 8/8 : CMD [] ---> Using cache ---> 446baf852214 Successfully built 446baf852214 Successfully tagged hello-apline:latest $ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE hello-alpine latest 446baf852214 2 hours ago 6.55MB hello latest 7cfa0cbe4e2a 2 hours ago 1.14GB demo latest 079bae887a47 2 hours ago 125MB gcc 9.4 be1d0d9ce039 9 days ago 1.14GB $ docker run --rm -it hello-alpine docker hello docker $ docker run --rm -it hello-alpine world hello world $ docker run --rm -it hello-alpine friends hello friends $Sending build context to Docker daemon 5.12kB 可以看到这个镜像非常小,只有6.55MB。四、尽量使用非root用户Root的危险性假如我们有一个用户,叫demo,它本身不具有sudo的权限,所以就有很多文件无法进行读写操作,比如/root目录它是无法查看的。但是有执行docker容器的权限,可以映射root文件路径,查看root文件。[demo@docker-host ~]$ sudo ls /root [sudo] password for demo: demo is not in the sudoers file. This incident will be reported. [demo@docker-host ~]$但是这个用户有执行docker的权限,也就是它在docker这个group里。[demo@docker-host ~]$ groups demo docker [demo@docker-host ~]$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE busybox latest a9d583973f65 2 days ago 1.23MB [demo@docker-host ~]$这时,我们就可以通过Docker做很多越权的事情了,比如,我们可以把这个无法查看的/root目录映射到docker container里,你就可以自由进行查看了。[demo@docker-host vagrant]$ docker run -it -v /root/:/root/tmp busybox sh / # cd /root/tmp ~/tmp # ls anaconda-ks.cfg original-ks.cfg ~/tmp # ls -l total 16 -rw------- 1 root root 5570 Apr 30 2020 anaconda-ks.cfg -rw------- 1 root root 5300 Apr 30 2020 original-ks.cfg ~/tmp #更甚至我们可以给我们自己加sudo权限。我们现在没有sudo权限。[demo@docker-host ~]$ sudo vim /etc/sudoers [sudo] password for demo: demo is not in the sudoers file. This incident will be reported. [demo@docker-host ~]$但是我可以给自己添加。[demo@docker-host ~]$ docker run -it -v /etc/sudoers:/root/sudoers busybox sh / # echo "demo ALL=(ALL) ALL" >> /root/sudoers / # more /root/sudoers | grep demo demo ALL=(ALL) ALL然后退出container,bingo,我们有sudo权限了。[demo@docker-host ~]$ sudo more /etc/sudoers | grep demo demo ALL=(ALL) ALL [demo@docker-host ~]$如何使用非root用户我们准备两个Dockerfile,第一个Dockerfile如下,其中app.py文件源码:FROM python:3.9.5-slim RUN pip install flask COPY app.py /src/app.py WORKDIR /src ENV FLASK_APP=app.py EXPOSE 5000 CMD ["flask", "run", "-h", "0.0.0.0"]假设构建的镜像名字为 flask-demo第二个Dockerfile,使用非root用户来构建这个镜像,名字叫 flask-no-root Dockerfile如下:通过groupadd和useradd创建一个flask的组和用户通过USER指定后面的命令要以flask这个用户的身份运行FROM python:3.9.5-slim RUN pip install flask && \ groupadd -r flask && useradd -r -g flask flask && \ mkdir /src && \ chown -R flask:flask /src USER flask COPY app.py /src/app.py WORKDIR /src ENV FLASK_APP=app.py EXPOSE 5000 CMD ["flask", "run", "-h", "0.0.0.0"]$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE flask-no-root latest 80996843356e 41 minutes ago 126MB flask-demo latest 2696c68b51ce 49 minutes ago 125MB python 3.9.5-slim 609da079b03a 2 weeks ago 115MB分别使用这两个镜像创建两个容器$ docker run -d --name flask-root flask-demo b31588bae216951e7981ce14290d74d377eef477f71e1506b17ee505d7994774 $ docker run -d --name flask-no-root flask-no-root 83aaa4a116608ec98afff2a142392119b7efe53617db213e8c7276ab0ae0aaa0 $ docker container ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 83aaa4a11660 flask-no-root "flask run -h 0.0.0.0" 4 seconds ago Up 3 seconds 5000/tcp flask-no-root b31588bae216 flask-demo "flask run -h 0.0.0.0" 16 seconds ago Up 15 seconds 5000/tcp flask-root
2023年04月25日
87 阅读
0 评论
0 点赞
2023-04-16
Dockerfile
基础镜像的选择 (FROM)官方镜像优于非官方的镜像,如果没有官方镜像,则尽量选择Dockerfile开源的固定版本tag而不是每次都使用latest尽量选择体积小的镜像空镜像:scratch最小镜像:alpine通过 RUN 执行指令RUN 主要用于在Image里执行指令,比如安装软件,下载文件等。FROM ubuntu:20.04 RUN apt-get update RUN apt-get install -y wget RUN wget https://github.com/ipinfo/cli/releases/download/ipinfo-2.0.1/ipinfo_2.0.1_linux_amd64.tar.gz RUN tar zxf ipinfo_2.0.1_linux_amd64.tar.gz RUN mv ipinfo_2.0.1_linux_amd64 /usr/bin/ipinfo RUN rm -rf ipinfo_2.0.1_linux_amd64.tar.gz每执行一次RUN执行,就会新产生一个分层。一般使用,优化后的执行命令:FROM ubuntu:20.04 RUN apt-get update && \ apt-get install -y wget && \ wget https://github.com/ipinfo/cli/releases/download/ipinfo-2.0.1/ipinfo_2.0.1_linux_amd64.tar.gz && \ tar zxf ipinfo_2.0.1_linux_amd64.tar.gz && \ mv ipinfo_2.0.1_linux_amd64 /usr/bin/ipinfo && \ rm -rf ipinfo_2.0.1_linux_amd64.tar.gz&&:指令拼接\:命令换行。只执行了一次RUN,则只会产生一个分层。文件复制和目录操作(ADD,COPY,WORKDIR)往镜像里复制文件有两种方式,COPY 和 ADD , 我们来看一下两者的不同。复制普通文件COPY 和 ADD 都可以把local的一个文件复制到镜像里,如果目标目录不存在,则会自动创建。FROM python:3.9.5-alpine3.13 COPY hello.py /app/hello.py比如把本地的 hello.py 复制到 /app 目录下。 /app这个folder不存在,则会自动创建。复制压缩文件ADD 比 COPY高级一点的地方就是,如果复制的是一个gzip等压缩文件时,ADD会帮助我们自动去解压缩文件。FROM python:3.9.5-alpine3.13 ADD hello.tar.gz /app/所有的文件复制均使用 COPY 指令,仅在需要自动解压缩的场合使用 ADD。注意:对应文件的权限复制到基础镜像里面后权限一样。目录切换WORKDIR:目录切换,类似cd的操作。比cd好的是,没有目录时,会帮自动创建。FROM python:3.9.5-alpine3.13 WORKDIR /app COPY hello.py hello.pyWORKDIR切换目录后,copy默认copy到切换后的app目录下。构建参数和环境变量 (ARG vs ENV)ARG 和 ENV 是经常容易被混淆的两个Dockerfile的语法,都可以用来设置一个“变量”。 但实际上两者有很多的不同。例子:安装某个特定版本软件时,需要对版本进行升级,就可以定义参数变量,方便后续升级,直接改版本号即可。FROM ubuntu:20.04 RUN apt-get update && \ apt-get install -y wget && \ wget https://github.com/ipinfo/cli/releases/download/ipinfo-2.0.1/ipinfo_2.0.1_linux_amd64.tar.gz && \ tar zxf ipinfo_2.0.1_linux_amd64.tar.gz && \ mv ipinfo_2.0.1_linux_amd64 /usr/bin/ipinfo && \ rm -rf ipinfo_2.0.1_linux_amd64.tar.gz上面是没有使用变量时,每次升级就需要改版本号2.0.1,这样会修改很多地方,这时就可以定义参数变量,之后升级改一个地方就可以了。ENV变量FROM ubuntu:20.04 ENV VERSION=2.0.1 RUN apt-get update && \ apt-get install -y wget && \ wget https://github.com/ipinfo/cli/releases/download/ipinfo-${VERSION}/ipinfo_${VERSION}_linux_amd64.tar.gz && \ tar zxf ipinfo_${VERSION}_linux_amd64.tar.gz && \ mv ipinfo_${VERSION}_linux_amd64 /usr/bin/ipinfo && \ rm -rf ipinfo_${VERSION}_linux_amd64.tar.gzARG变量FROM ubuntu:20.04 ARG VERSION=2.0.1 RUN apt-get update && \ apt-get install -y wget && \ wget https://github.com/ipinfo/cli/releases/download/ipinfo-${VERSION}/ipinfo_${VERSION}_linux_amd64.tar.gz && \ tar zxf ipinfo_${VERSION}_linux_amd64.tar.gz && \ mv ipinfo_${VERSION}_linux_amd64 /usr/bin/ipinfo && \ rm -rf ipinfo_${VERSION}_linux_amd64.tar.gz使用时,都是${变量名}这样使用。如果要改版本,这样直接改VERSION=新版本号就可以了。ENV与ARG区别ARG:只作用域镜像构建过程中,镜像环境中是没有该参数的,后续容器中不能使用改参数变量。build镜像时可以使用参数--build-arg动态改变参数值。例如:docker image build -f .\Dockerfile-arg -t ipinfo-arg-2.0.0 --build-arg VERSION=2.0.0 .ENV:会将参数设置到镜像中,通过env可以看到环境变量中有对应的参数,后续容器中也可以使用这些参数变量。不能动态改值。使用场景ARG主要用于关注build镜像的过程。ENV主要用于后续容器中使用。容器启动时默认执行的命令 CMDCMD可以用来设置容器启动时默认会执行的命令。容器启动时默认执行的命令如果docker container run启动容器时指定了其它命令,则CMD命令会被忽略如果定义了多个CMD,只有最后一个会被执行。1、清理后台已经停止的全部容器:docker system prune -f也可以一个一个清理docekr container rm 容器名称2、删除没有用到的全部镜像docker image prune -a当没有定义CMD命令时,会默认进入到shell是因为在ubuntu的基础镜像里有定义CMD。如果想一次行运行容器,运行完后自动删除容器:只需要在运行容器时加参数--rm即可。容器启动命令 ENTRYPOINTENTRYPOINT 也可以设置容器启动时要执行的命令,但是和CMD是有区别的。CMD 设置的命令,可以在docker container run 时传入其它命令,覆盖掉 CMD 的命令,但是 ENTRYPOINT 所设置的命令是一定会被执行的。ENTRYPOINT 和 CMD 可以联合使用,ENTRYPOINT 设置执行的命令,CMD传递参数。1、CMD命令的Dockerfile,build成一个叫 demo-cmd 的镜象。FROM ubuntu:20.04 CMD ["echo", "hello docker"]2、ENTRYPOINT命令的Dockerfile,build成一个叫 demo-entrypoint 的镜象。FROM ubuntu:20.04 ENTRYPOINT ["echo", "hello docker"]比较:CMD的镜像,如果执行创建容器,不指定运行时的命令,则会默认执行CMD所定义的命令,打印出hello docker$ docker container run -it --rm demo-cmd hello docker如果我们docker container run的时候指定命令,则该命令会覆盖掉CMD的命令:$ docker container run -it --rm demo-cmd echo "hello world" hello worldENTRYPOINT的容器里ENTRYPOINT所定义的命令则无法覆盖,一定会执行:$ docker container run -it --rm demo-entrypoint hello docker $ docker container run -it --rm demo-entrypoint echo "hello world" hello docker echo hello world会将echo "hello world"当作参数传入。3、CMD作为参数参数传入ENTRYPOINT,Dockerfile如下:FROM ubuntu:21.04 ENTRYPOINT ["echo"] CMD []将3编译成叫demoboth的镜像。docker run --rm -it demoboth不加cmd执行:执行echo打印了空行[root@10 ~]# docker run --rm -it demoboth:1.0 加cmd传入作为echo的参数打出:[root@10 ~]# docker run --rm -it demoboth:1.0 echo "hi docker" echo hi dockerShell 格式和 Exec 格式Shell格式CMD echo "hello docker"ENTRYPOINT echo "hello docker"Exec格式以可执行命令的方式ENTRYPOINT ["echo", "hello docker"]CMD ["echo", "hello docker"]注意shell脚本的问题FROM ubuntu:20.04 ENV NAME=docker CMD echo "hello $NAME"假如我们要把上面的CMD改成Exec格式,下面这样改是不行的。FROM ubuntu:20.04 ENV NAME=docker CMD ["echo", "hello $NAME"]它会打印出 hello $NAME , 而不是 hello docker ,那么需要怎么写呢? 我们需要以shell脚本的方式去执行:FROM ubuntu:20.04 ENV NAME=docker CMD ["sh", "-c", "echo hello $NAME"]"sh":执行sh命令“-c”: 执行的命令
2023年04月16日
85 阅读
0 评论
4 点赞
1
2
...
21