Ansible剧本playbooks详解

一、playbook简介

playbook是ansible用于配置,部署和管理托管主机剧本,通过playbook的详细描述,执行其中一系列tasks,playbook字面意思是剧本,现实中由演员按剧本表演,在ansible中由计算机进行安装,部署应用,提供对外服务,以及组织计算机处理各种各样的事情。

ansible使用playbook来管理自动化task,playbook是yaml格式的文件,其基本内容可以认为是多条ansible的ad-hoc的语句组成。我们完成一个任务,例如安装部署一个httpd服务,我们需要多个模块(一个模块也可以称之为task)提供功能来完成。而playbook就是组织多个task的容器,他的实质就是一个文件,是用yaml(Yet Another Markup Language)语言编写的文件,有着特定的组织格式。YAML 是专门用来写配置文件的语言,非常简洁和强大,远比 JSON 格式方便,YAML语法能够简单的表示散列表,字典等数据结构。

playbook命令根据自上而下的顺序依次执行。同时,playbook开创了很多特性,它可以允许你传输某个命令的状态到后面的指令,如你可以从一台机器的文件中抓取内容并附为变量,然后在另一台机器中使用,这使得你可以实现一些复杂的部署机制,这是ansible命令无法实现的。

二、Playbook核心元素 

模块名

注释

Hosts

执行的远程主机列表

Tasks

任务集,即通过 task 调用 ansible 的模板将多个操作组织在一个 playbook 中运行

Variables

内置变量或自定义变量在playbook中调用

Templates

模板,使用模板语法的文件,比如配置文件等

Handlers

处理器,当changed状态条件满足时,(notify)触发执行的操作,和notity结合使用

tags

标签,指定某条任务执行,用于选择运行playbook中的部分代码

Roles

角色

 三、Playbook语法

playbook使用yaml语法格式,后缀可以是yaml,也可以是yml,文件中有多个play,一个play中只能有一个tasks,一个tasks中可以有多个name任务。

  • 在一个playbook文件中,可以连续三个连子号(---)区分多个play。还有选择性的连续三个点好(...)用来表示play的结尾,也可省略
  • 次行开始正常写playbook的内容,一般都会写上描述该playbook的功能
  • 使用#号注释代码
  • 缩进必须统一,不能空格和tab混用
  • 缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行实现的
  • YAML文件内容和Linux系统大小写判断方式保持一致,是区分大小写的,k/v的值均需大小写敏感
  • k/v的值可同行写也可以换行写。同行使用:分隔
  • v可以是个字符串,也可以是一个列表
  • 一个完整的代码块功能需要最少元素包括 name: task

四、playbook 运行方式

ansible-playbook <filename.yml> ... [options]#检测文件配置
ansible-playbook test.yaml  --syntax-check
#执行文件
ansible-playbook test.yaml
ansible-playbook filename.yml [options]# ssh 连接的用户名
-u REMOTE_USER, --user=REMOTE_USER# ssh登录认证密码
-k, --ask-pass    # sudo 到root用户,相当于Linux系统下的sudo命令
-s, --sudo       # sudo 到对应的用户
-U SUDO_USER, --sudo-user=SUDO_USER   # 用户的密码(—sudo时使用)
-K, --ask-sudo-pass     # ssh 连接超时,默认 10 秒
-T TIMEOUT, --timeout=TIMEOUT# 指定该参数后,执行 playbook 文件不会真正去执行,而是模拟执行一遍,然后输出本次执行会对远程主机造成的修改
-C, --check      # 设置额外的变量如:key=value 形式 或者 YAML or JSON,以空格分隔变量,或用多个-e
-e EXTRA_VARS, --extra-vars=EXTRA_VARS    # 进程并发处理,默认 5
-f FORKS, --forks=FORKS    # 指定 hosts 文件路径,默认 default=/etc/ansible/hosts
-i INVENTORY, --inventory-file=INVENTORY   # 指定一个 pattern,对- hosts:匹配到的主机再过滤一次
-l SUBSET, --limit=SUBSET    # 只打印有哪些主机会执行这个 playbook 文件,不是实际执行该 playbook
--list-hosts  # 列出该 playbook 中会被执行的 task
--list-tasks   # 私钥路径
--private-key=PRIVATE_KEY_FILE   # 同一时间只执行一个 task,每个 task 执行前都会提示确认一遍
--step    # 只检测 playbook 文件语法是否有问题,不会执行该 playbook
--syntax-check  # 当 play 和 task 的 tag 为该参数指定的值时才执行,多个 tag 以逗号分隔
-t TAGS, --tags=TAGS   # 当 play 和 task 的 tag 不匹配该参数指定的值时,才执行
--skip-tags=SKIP_TAGS   # 输出更详细的执行过程信息,-vvv可得到所有执行过程信息。
-v, --verbose 

检查文件是否有误:

ansible-playbook test.yaml --syntax-check

执行文件:

ansible-playbook test1.yaml

 六、变量

- name: testhosts: testremote_user: rootvars:                 #定义变量- groupname: testgroup   - username: testusertasks:- name: create groupgroup: name={{groupname}} system=yes gid=600    #使用 {{key}} 引用变量的值- name: create useruser: name={{username}} uid=600 group={{groupname}} - name: copy filecopy: content="{{ansible_default_ipv4}}" dest=/opt/vars.txt    #在setup模块中可以获取facts变量信息

七、常用模块

1、when 模块

在Ansible中,提供的唯一一个通用的条件判断是when指令,当when指令的值为true时,则该任务执行,否则不执行该任务。

when一个比较常见的应用场景是实现跳过某个主机不执行任务或者只有满足条件的主机执行任务

---
- hosts: allremote_user: roottasks:- name: test when  service: name=httpd state=stoppedwhen: ansible_default_ipv4.address == "192.168.0.1"      #when指令中的变量名不需要手动加上 {{}}
# 或 when: inventory_hostname == "<主机名>"

当主机 IP 是 192.168.0.1 才会启动 httpd ,否则不启动

2、with_items 模块

Ansible提供了很多种循环结构,一般都命名为with_items,作用等同于 loop 循环;案例中with_item 相当于提供了2个变量,循环被调用执行任务

---
- name: playhosts: testgather_facts: falsetasks:- name: create directoriesfile:path: "{{item}}"state: directorywith_items:- /tmp/test1- /tmp/test2- name: add usersuser: name={{item.name}} state=present groups={{item.groups}}with_items:- name: test1groups: wheel- name: test2groups: root
或with_items:- {name:'test1', groups:'wheel'}- {name:'test2', groups:'root'}

3、template(模板)

Ansible 模板是一种强大的工具,可用于在自动化任务中以动态方式生成配置、文件和其他工件。模板使用 Jinja2 模板语言,这是一种功能强大的模板语言,可用于创建复杂的模板。

Jinja2 模板语言:使用字面量,有下面形式。

字符串:使用单引号或者双引号

数字:整数、浮点数

列表:[item1、item2、......]

元组:[item1、item2、......]

字典:[key1:value1,key2:value2,......]

布尔型:true/false

算数运算:+ ,-, *, /,/ /,%,**

比较操作:==, !=, >, >=, <, <=

逻辑运算:and、or、not

流表达式:If For When

template功能:根据模块文件动态生成对应的配置文件

template文件必须存放于templates目录下,且命名为 .j2 结尾 yaml/yml 文件需和templates目录平级,目录结构如下:

./

├── temnginx.yml

└── templates

        └── nginx.conf.j2

---
- hosts: 10.0.0.1remote_user: roottasks:- name: install packageyum: nginx- name: copy templatetemplate: src: nginx.conf.j2dest: /etc/nginx/nginx.conf- name: service startservice: name=nginx state=started enabled=yes

4、Playbooks中tasks语法使用

4.1、tags

如果写了一个很长的playbook,其中有很多的任务,这并没有什么问题,不过在实际使用这个剧本时,可能只是想要执行其中的一部分任务而已,或者,你只想要执行其中一类任务而已,而并非想要执行整个剧本中的全部任务,这个时候我们就可以借助 tags 标签实现这个需求。

tags可以帮助我们对任务进行’打标签’的操作,与模块名同级,当任务存在标签以后,我们就可以在执行playbook时,借助标签,指定执行哪些任务,或者指定不执行哪些任务了。

为playbook 添加标签的方式有如下几种:

  • 对一个 task 打一个标签
  • 对一个 task 打多个标签
  • 对多个 task 打一个标签

使用标签的方式:

  • -t 执行指定tag标签对用的任务
  • --skip-tags 执行除 --skip-tags 标签之外的所有任务
---
- hosts: webremote_user: roottasks:- name: test1file:path: /tmp/abc1.txtstate: touchtags: t1,t4- name: test2file:path: /tmp/abc2.txtstate: touchtags: t2- name: test3file:path: /tmp/abc3.txtstate: touchtags: t3,t4

借助标签,除了能够指定“需要执行的任务”,还能够指定“不执行的任务” 使用--skip-tags 选项

ansible-playbook --skip-tags=t2 tags-test1.yaml

其实,ansible预置了5个特殊的标签,分别是

always :总是会被执行

never :总是不执行

tagged :表示只执行有标签的任务,没有标签的任务不会被执行。

untagged :只执行没有标签的任务,但是如果某些任务包含always标签,那么这些任务也会被执行。

all :特殊标签all表示所有任务会被执行,不用指定,默认情况下就是使用这个标签。

---
- hosts: webremote_user: roottasks:- name: test1file:path: /tmp/abc1.txtstate: absenttags: t1- name: test2file:path: /tmp/abc2.txtstate: absenttags: t2- name: test3file:path: /tmp/abc3.txtstate: absenttags: t3,always# task3的标签有两个,t3和always,在执行剧本时候,不指定t3,但是也会被执行,这就是always的作用。
如果不想执行标签中包含always的任务,可以使用--skip-tags=always 跳过他们。

4.2、file

file模块主要用于远程主机上的文件操作,file模块包含如下选项:

force

需要在两种情况下强制创建软链接,一种是源文件不存在但之后会建立的情况下;另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,选项:yes/no

group

定义文件/目录的属组

mode

定义文件/目录的权限

owner

定义文件/目录的属主

path

必选项,定义文件/目录的路径

recurse

递归的设置文件的属性,只对目录有效

src

要被链接的源文件的路径,只应用于state=link的情况

dest

被链接到的目标路径,只应用于state=link的情况

state

directory:表示目录,如果目录不存在,则创建目录。

link:创建软链接

hard:创建硬链接

touch:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间

absent:删除目录、文件或者取消链接文件。

举例:

- hosts: 192.168.0.1remote_user: tomcattasks:- name: mkdir data directoryfile: path=/opt/data state=directory mode=0755- name: chmod binfile: dest=/opt/bigdata/jdk/bin mode=0755 recurse=yes- name: link filesfile: src=/etc/ssh/sshd_config dest=/mnt/sshd_config  owner=sshd state=link- name: delete filesfile: path=/tmp/tomcat.tar.gz state=absent- name: chown filesfile: path=/mnt/test.txt owner=nobody  group=nobody mode=0644

4.3、lineinfile

修改文件某一行文本

常用参数:

path

必须参数,指定要操作的文件

regexp

使用正则表达式匹配对应的行,当替换文本时,如果有多行文本都能被匹配,则只有最后面被匹配到的那行文本才会被替换,当删除文本时,如果有多行文本都能被匹配,这么这些行都会被删除。

line

指定修改后的文本内容

state

当想要删除对应的文本时,需要将state参数的值设置为absent,absent为缺席之意,表示删除,state的默认值为present

backrefs

默认情况下,当根据正则替换文本时,即使regexp参数中的正则存在分组,在line参数中也不能对正则中的分组进行引用,除非将backrefs参数的值设置为yes,backrefs=yes表示开启后向引用,这样,line参数中就能对regexp参数中的分组进行后向引用了,这样说不太容易明白,参考下面的示例命令比较直观一点,backrefs=yes除了能够开启后向引用功能,还有另一个作用,默认情况下,当使用正则表达式替换对应行时,如果正则没有匹配到任何的行,那么line对应的内容会被插入到文本的末尾,不过,如果使用了backrefs=yes,情况就不一样了,当使用正则表达式替换对应行时,同时设置了backrefs=yes,那么当正则没有匹配到任何的行时,则不会对文件进行任何操作,相当于保持原文件不变,如果没有理解,就按照下面的示例命令,动手操作一下吧,那样更加直观

insertafter

借助insertafter参数可以将文本插入到“指定的行”之后,insertafter参数的值可以设置为EOF或者正则表达式,EOF为End Of File之意,表示插入到文档的末尾,默认情况下insertafter的值为EOF,如果将insertafter的值设置为正则表达式,表示将文本插入到匹配到正则的行之后,如果正则没有匹配到任何行,则插入到文件末尾,当使用backrefs参数时,此参数会被忽略

insertbefore

借助insertbefore参数可以将文本插入到“指定的行”之前,insertbefore参数的值可以设置为BOF或者正则表达式,BOF为Begin Of File之意,表示插入到文档的开头,如果将insertbefore的值设置为正则表达式,表示将文本插入到匹配到正则的行之前,如果正则没有匹配到任何行,则插入到文件末尾,当使用backrefs参数时,此参数会被忽略

backup

是否在修改文件之前对文件进行备份

create

操作的文件不存在时是否创建

示例:

1、替换文件中匹配到得最后一个 SELINUX=,替换成 SELINUX=enforcing

   - name: seline modify enforcinglineinfile:dest: /etc/selinux/configregexp: '^SELINUX='line: 'SELINUX=enforcing'

2、 insertbefore匹配内容在前面添加

- name: httpd.conf modify 8080lineinfile:dest: /opt/playbook/test/http.confregexp: '^Listen'insertbefore: '^#Port'   line: 'Listen 8080'tags:- http8080

3、修改文件内容以及权限

 - name: modify hostslineinfile:dest: /opt/playbook/test/hostsregexp: '^127\.0\.0\.1'line: '127.0.0.1 localhosts'owner: rootgroup: rootmode: 0644tags:- hosts

4、删除一行内容

- name: delete 192.168.0.1lineinfile:dest:  /opt/playbook/test/hostsstate: absentregexp: '^192\.'tags:- delete192

4.4、replace

replace 模块根据指定得正则表达式替换文件中得字符串,文件中所有被正则匹配到得字符串都会被替换

- name: 替换配置文件中的文本hosts: servicetasks:- name: 替换单个文本replace:path: /etc/test/config.confregexp: 'old_text'replace: 'new_text'- name: 替换多个文本replace:path: /etc/test/config.confregexp: '(old_text1|old_text2)'replace: 'new_text'- name: 使用正则表达式替换replace:path: /etc/test/config.confregexp: 'pattern(.*)'replace: 'replacement\1'backrefs: yes

使用正则表达式替换:通过regexp参数指定一个正则表达式,使用括号捕获匹配的内容。通过replace参数指定替换的文本,并使用\1表示捕获的内容。replace模块会在文件中查找匹配的文本并进行替换。

4.5、shell

执行命令

- shell: mkdir /tmp/mytest
- shell: echo "export JAVA_HOME=/opt/jdk" >> /etc/profile

4.6、pause

暂停一定时间

常用参数:

  • minutes:暂停多少分钟
  • seconds:暂停多少秒
  • prompt:打印一串信息提示用户操作
- name: 等待用户30s用于输入pause: seconds=30 prompt="ENTER to continue CTRL-C a to quit"

4.7、local_action

本地操作功能,在运行ansible命令机器上执行操作

4.8、ignore_errors

忽略错误,通常情况执行失败时 ansible 会停止运行,有时候需要继续执行,则需要添加次参数

- name: 删除临时目录shell: rm /tmp/dataignore_errors:yes

4.9、user/group

用户组管理

常用参数:

  • name:指定组名称
  • gid:指定GID
  • state:动作参数

present:增加
absent:删除

4.10、yum

软件包管理

常用参数:

name:指定需要管理的软件包名

state:参数非常灵活,可以包含的值及含义如下

present:确保软件包已经安装了

installed:安装

latest:安装最新的软件包

removed/absent:删除对应的软件包

disable_gpg_check:用于禁用对rpm包公钥验证,默认值no表示不禁用验证,yes表示禁用验证

---
- name: install packagehosts: alltasks:- name: install php and mariaDByum:name:- php- mariadbstate: presentwhen: ansible_hostname in groups['dev']  - name: install the 'Development tools' package groupyum:name: "@Development tools"state: presentwhen: ansible_hostname in groups['dev']- name: upgrade all packagesyum:name: "*"state: latest
- name:安装httpd服务yum: name=httpd state=latest- name: 删除旧版gccyum: name = {{ item }} state=removedwith_items:- gcc- httpd- php

4.11、cron

定时任务,相当于crontab

常用参数:

name:任务名称
minute:分, hour:时,day:天,month:月,weekday:周
job:指定要执行的命令或者脚本
state:当设置为absent代表删除任务

- name: 新增一个定时查看路径任务cron: name=check minute=5 job='pwd'

5、wars 变量

- name: second playhosts: dbserversremote_user: rootvars:                 #定义变量- groupname: testgroup   #格式为 key: value- username: testusertasks:- name: create groupgroup: name={{groupname}} system=yes gid=308    #使用 {{key}} 引用变量的值- name: create useruser: name={{username}} uid=309 group={{groupname}} - name: copy filecopy: content="{{ansible_default_ipv4}}" dest=/opt/vars.txt    #在setup模块中可以获取facts变量信息

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/773375.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

nginx负载均衡模式

轮询 (Round Robin) 用法&#xff1a;这是Nginx默认的负载均衡策略。每个请求会按顺序分配给upstream中的后端服务器&#xff0c;即按照配置的服务器列表顺序依次分配。 upstream backend {server backend1.example.com;server backend2.example.com;server backend3.example.c…

【Java】LinkedList vs. ArrayList:Java中的数据结构选择

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

docker日志大小设置(doker logs)

参考文章docker logs日志上限&#xff08;日志容量上限、日志大小上限&#xff09;&#xff08;默认大小、默认日志大小&#xff09;_docker 日志限制-CSDN博客 如果想要更改 Docker daemon 的全局默认设置&#xff0c;可以修改 Docker daemon 的配置文件 /etc/docker/daemon…

zookeeper--Znode类型详解---面试宝典

一、Znode分类 1、persistent_node 持久化节点 是默认类型&#xff0c;该类型节点&#xff0c;并不会随着客户端断开就会自动删除&#xff1b;zookeeper服务重启该节点也不会被删除&#xff0c;只有手动删除的时候才会删除&#xff1b;可以创建子节点&#xff1b; # create …

uniapp开发小程序遇到的问题,持续更新中

一、uniapp引入全局scss 在App.vue中引入uni.scss <style lang"scss">/* #ifndef APP-NVUE */import "uni.scss";/* #endif */ </style>注意&#xff1a;nvue页面的样式在编译时&#xff0c;有很多样式写法被限制了&#xff0c;容易报错。所…

【C++ leetcode】双指针(专题完结)

15. 三数之和 题目 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请 你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以包含重复的…

驱动器的工艺结构原理及选型参数总结

🏡《总目录》 目录 1,概述2,工作原理2.1,信号转换2.2,电流放大2.3,电压级转换2.4,控制输出3,结构特点3.1,高集成度3.2,多功能性3.3,高性能3.4,省电节能3.5,稳定可靠4,工艺流程<

面试经典150题【101-110】

文章目录 面试经典150题【101-110】9.回文数61.加一172.阶乘后的069.x的平方根50.Pow(x,n)149.直线上最多的点数52.N皇后II120.三角形最小路径和64.最小路径和63.不同路径II 面试经典150题【101-110】 6道偏数学的题和4道二维dp 9.回文数 一开始想转为字符串再判断。后来发现…

信号处理--基于混合CNN和transfomer自注意力的多通道脑电信号的情绪分类的简单应用

目录 关于 工具 数据集 数据集简述 方法实现 数据读取 ​编辑数据预处理 传统机器学习模型(逻辑回归&#xff0c;支持向量机&#xff0c;随机森林) 多层感知机模型 CNNtransfomer模型 代码获取 关于 本实验利用结合了卷积神经网络 (CNN) 和 Transformer 组件的混合…

五-容量管理之容量预案

容量预案(Capacity Plan)是容量管理的一个重要组成部分。 容量预警条件和措施&#xff1a; 类型预警条件措施应用服务器Load95分位值大于CPU核数的2倍 前一天CPU 95分位值大于90% 内存使用率95分位值大于90%增加应用服务器数据库数据库连接超过200扩容DB服务规格/ 优化SQL查询…

windows下powershell与linux下bash美化教程(使用starship)

starship美化教程 Win11 Powershell 安装 在命令行使用下面命令安装 # 安装starship winget install starship将以下内容添加到 Microsoft.PowerShell_profile.ps1&#xff0c;可以在 PowerShell 通过 $PROFILE 变量来查询文件的位置 Invoke-Expression (&starship i…

【HBZ分享】Kafka为什么性能非常高

Kafka性能高的原因 磁盘顺序读写&#xff1a;磁盘顺序读写的性能可以和内存相媲美&#xff0c;顺序读写不需要寻道时间&#xff0c;也不需要大幅旋转磁头找扇区&#xff0c;所以性能极高 零拷贝&#xff1a; 大幅降低了用户态与内核态之间的切换&#xff0c;从而减少了数据来回…

Chrome安装Vue插件vue-devtools

安装Vue.js开发者工具&#xff08;Vue DevTools&#xff09;到Google Chrome浏览器的步骤可能会随着Vue DevTools更新和Chrome政策变化而有所调整。 1.从GitHub获取源代码&#xff1a; 访问Vue DevTools的GitHub仓库&#xff1a;https://github.com/vuejs/vue-devtools 根据仓…

web学习笔记(四十五)Node.js

目录 1. Node.js 1.1 什么是Node.js 1.2 为什么要学node.js 1.3 node.js的使用场景 1.4 Node.js 环境的安装 1.5 如何查看自己安装的node.js的版本 1.6 常用终端命令 2. fs 文件系统模块 2.1引入fs核心模块 2.2 读取指定文件的内容 2.3 向文件写入指定内容 2.4 创…

sql oracle 获取当前日期的最后一天

语法 LAST_DAY 传入一个日期类型的变量&#xff0c;但会给你一个当月的最后一天的变量 LAST_DAY(TO_DATE(year || - || SUBSTR(month, -2) || -01, YYYY-MM-DD)) < ?应用实例 AssetValueSingleQT.spl 一个表中只存储的年和月&#xff0c;需要更具年月筛选小于指定日期&…

yarn按包的时候报错 ../../../package.json: No license field

运行 yarn config list 然后运行 yarn config set strict-ssl false 之后yarn就成功了

基于SpringBoot“网上选课系统”设计和实现(源码定制以及咨询!!)

博主介绍&#xff1a;✌全网粉丝10W,B站项目阿龙、csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、华为云获奖者&#xff0c;“程序员阿龙”✌ 主要内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python&#xff0c;MYSQL、Hodpoo…

网络工程师软考中级考试大纲

考试要求&#xff1a; &#xff08;1&#xff09;熟悉计算机系统的基础知识&#xff1b;&#xff08;2&#xff09;熟悉网络操作系统的基础知识&#xff1b;&#xff08;3&#xff09;理解计算机应用系统的设计和开发方法&#xff1b;&#xff08;4&#xff09;熟悉数据通信的基…

SpringBoot2.6.3 + knife4j-openapi3

1.引入项目依赖&#xff1a; <dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi3-spring-boot-starter</artifactId><version>4.5.0</version> </dependency> 2.新增配置文件 import io.swag…

Docker搭建LNMP环境实战(05):CentOS环境安装Docker-CE

前面几篇文章讲了那么多似乎和Docker无关的实战操作&#xff0c;本篇总算开始说到Docker了。 1、关于Docker 1.1、什么是Docker Docker概念就是大概了解一下就可以&#xff0c;还是引用一下百度百科吧&#xff1a; Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以…