Elasticsearch的基本使用
官网:https://www.elastic.co/cn
官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html
官方中文:https://www.elastic.co/guide/cn/elasticsearch/guide/current/foreword_id.html
社区中文:
https://es.xiaoleilu.com/index.html
http://doc.codingdict.com/elasticsearch/0/
1、什么是Elasticsearch
Elasticsearch 是一个分布式的免费开源搜索和分析引擎,适用于包括文本、数字、地理空间、结构化和非结构化数据等在内的所有类型的数据。Elasticsearch 在 Apache Lucene 的基础上开发而成,由 Elasticsearch N.V.(即现在的 Elastic)于 2010 年首次发布。Elasticsearch 以其简单的 REST 风格 API、分布式特性、速度和可扩展性而闻名,是 Elastic Stack 的核心组件;Elastic Stack 是一套适用于数据采集、扩充、存储、分析和可视化的免费开源工具。人们通常将 Elastic Stack 称为 ELK Stack(代指 Elasticsearch、Logstash 和 Kibana),目前 Elastic Stack 包括一系列丰富的轻量型数据采集代理,这些代理统称为 Beats,可用来向 Elasticsearch 发送数据。
2、Elasticsearch 的用途
应用程序搜索
网站搜索
企业搜索
日志处理和分析
基础设施指标和容器监测
应用程序性能监测
地理空间数据分析和可视化
安全分析
业务分析
3、基本概念
6.0以后不建议设置类型
1、Index(索引)相当mysql中的数据库
动词,相当于 MySQL 中的 insert;
名词,相当于 MySQL 中的 Database
2、Type(类型) 相当于mysql中表
在 Index(索引)中,可以定义一个或多个类型。
类似于 MySQL 中的 Table;每一种类型的数据放在一起;
3、Document(文档)相当于mysql中的一条数据
保存在某个索引(Index)下,某种类型(Type)的一个数据(Document),文档是 JSON 格
式的,Document 就像是 MySQL 中的某个 Table 里面的内容;
在es中所有的数据都是一个json的文档
4、Docker安装elasticsearch
##redis安装#########################################################end####
##elasticsearch安装#########################################################start####
## 存储和检索数据
docker pull elasticsearch:7.4.2
## 可视化检索数据
docker pull kibana:7.4.2
## 获取最高权限
su root
vagrant
## 创建config文件夹
mkdir -p /mydata/elasticsearch/config
## 创建数据文件夹
mkdir -p /mydata/elasticsearch/data
## 配置文件,容许所有的ip访问elasticsearch
echo "http.host: 0.0.0.0" >> /mydata/elasticsearch/config/elasticsearch.yml
## 保证权限,将任何用户在/mydata/elasticsearch/ 下都有可读可写可执行的权限 -R递归
chmod -R 777 /mydata/elasticsearch/
## --name 为容器起一个名字叫 elasticsearch
## -p 9200:9200 -p 9300:9300 暴漏两个端口
## \ 换行
## -e 设置参数 ES_JAVA_OPTS="-Xms64m -Xmx256m" \ 测试环境下,设置 ES 的初始内存和最大内存,否则导
##致过大启动不了 ES
## -v 挂在以后在linux下的目录中就可以修改和获取到mysql内部的数据。
## -d 启动容器用的哪个镜像
docker run --name elasticsearch -p 9200:9200 -p 9300:9300 \
-e "discovery.type=single-node" \-e ES_JAVA_OPTS="-Xms64m -Xmx512m" \
-v /mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /mydata/elasticsearch/data:/usr/share/elasticsearch/data \
-v /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
-d elasticsearch:7.4.2
## 查看日志
docker logs elasticsearch
## 可视化界面Kibana 的安装
## http://192.168.56.10:9200 一定改为自己虚拟机的地址
docker run --name kibana -e ELASTICSEARCH_HOSTS=http://192.168.56.10:9200 -p 5601:5601 \
-d kibana:7.4.2
##elasticsearch安装#########################################################end######
查看当前IP地址:ip addr
4.1 测试elasticsearch是否启动成功:http://192.168.56.10:9200/
4.2 测试可视化工具kibana是否启动成功:http://192.168.56.10:5601
5、初步检索
查看版本:http://192.168.56.10:9200/
带“_”的都表示元数据
5.1 _cat
GET /_cat/nodes:查看所有节点
GET /_cat/health:查看 es 健康状况
GET /_cat/master:查看主节点
GET /_cat/indices:查看所有索引 show databases;
5.2 索引一个文档(保存)
保存文档有两种方式,1 put, 2 post
PUT customer/external/1
{ "name": "John Doe"
}
POST customer/external/2
注意事项
PUT 和 POST 都可以保存,
POST 新增。如果不指定 id,会自动生成 id。指定 id 就会修改这个数据,并新增版本号
PUT 可以新增可以修改。PUT 必须指定 id;由于 PUT 需要指定 id,我们一般都用来做修改
操作,不指定 id 会报错。
5.3 查询文档
GET customer/external/1
结果:
{ "_index": "customer", //在哪个索引
"_type": "external", //在哪个类型
"_id": "1", //记录 id
"_version": 2, //版本号
"_seq_no": 1, //并发控制字段,每次更新就会+1,用来做乐观锁
"_primary_term": 1, //同上,主分片重新分配,如重启,就会变化
"found": true, "_source": { //真正的内容
"name": "John Doe"
}
}
5.4 乐观锁的使用
“_seq_no”: 1, //并发控制字段,每次更新就会+1,用来做乐观锁
“_primary_term”: 1, //同上,主分片重新分配,如重启,就会变化
更新携带 ?if_seq_no=0&if_primary_term=1
例:
http://192.168.56.10:9200/customer/external/1?if_seq_no=1&if_primary_term=1
5.5 更新文档
方式1:post + _update
http://192.168.56.10:9200/customer/external/2/_update
{"doc":{
"name": "John Doe111"
}}
方式2:put或post
http://192.168.56.10:9200/customer/external/2
{
"name": "John Doe"
}
不同:
POST 操作会对比源文档数据,如果相同不会有什么操作,文档 version 不增加
PUT 操作总会将数据重新保存并增加 version 版本;
带_update 对比元数据如果一样就不进行任何操作。
看场景;
对于大并发更新,不带 update;
对于大并发查询偶尔更新,带 update;对比更新,重新计算分配规则。
更新同时增加属性
POST customer/external/1/_update
{ "doc": { "name": "Jane Doe", "age": 20 }
}
PUT 和 POST 不带_update 也可以
5.6 删除
## 删除文档
delete http://192.168.56.10:9200/customer/external/1
## 把索引删除
delete http://192.168.56.10:9200/customer
## 不能只删除类型
5.7 bulk 批量 API
POST customer/external/_bulk
{"index":{"_id":"1"}}
{"name": "John Doe" }
{"index":{"_id":"2"}}
{"name": "Jane Doe" }
语法格式:
{ action: { metadata }}\n
{ request body }\n
{ action: { metadata }}\n
{ request body }\n
简单实例:
POST customer/external/_bulk
{"index":{"_id":"1"}}
{"name": "John Doe" }
{"index":{"_id":"2"}}
{"name": "Jane Doe" }
复杂实力
POST customer/external/_bulk
{ "delete": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "create": { "_index": "website", "_type": "blog", "_id": "123" }}{ "title": "My first blog post" }
{ "index": { "_index": "website", "_type": "blog" }}{ "title": "My second blog post" }
{ "update": { "_index": "website", "_type": "blog", "_id": "123"} }
{ "doc" : {"title" : "My updated blog post"} }
5.8 样本测试数据
我准备了一份顾客银行账户信息的虚构的 JSON 文档样本。每个文档都有下列的 schema
(模式):
{ "account_number": 0, "balance": 16623, "firstname": "Bradshaw", "lastname": "Mckenzie", "age": 29, "gender": "F", "address": "244 Columbus Place", "employer": "Euron", "email": "bradshawmckenzie@euron.com", "city": "Hobucken", "state": "CO"
}
https://github.com/elastic/elasticsearch/blob/master/docs/src/test/resources/accounts.json?raw
=true
POST bank/account/_bulk
测试数据
进阶检索
6、SearchAPI
ES 支持两种基本方式检索 :
- 一个是通过使用 REST request URI 发送搜索参数(uri+检索参数)
- 另一个是通过使用 REST request body 来发送它们(uri+请求体),推荐使用第二种
GET bank/_search?q=*&sort=account_number:desc
GET bank/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"account_number": {
"order": "desc"
},
"balance":{
"order": "asc"
}
}
]
}
6.1 match ,match_all,multi_match ,must_not, should 的使用
match 分词配置
match_all 匹配所有
must_not 不配置
multi_match 多字段匹配
should 此条件如果成立会增加max_score的值
## 全文检索会按照评分进行排序,会对检索条件进行分词匹配
GET bank/_search
{
"query": {
"match": {
"address": "mill road"
}
}
}
## 短语匹配
GET bank/_search
{
"query": {
"match_phrase": {
"address": "mill road"
}
}
}
## 多字段配置
GET bank/_search
{
"query": {
"multi_match": {
"query": "mill movico",
"fields": ["address","city"]
}
}
}
6.2 filter的使用
## 复合查询
GET bank/_search
{
"query": {
"bool": {
"must": [
{"match": {
"gender": "m"
}}
],
"must_not": [
{"match": {
"age": "32"
}}
],
"should": [
{"match": {
"lastname": "Bond"
}}
],
"filter": {
"range": {
"age": {
"gte": 18,
"lte": 30
}
}
}
}
}
}
6.2 must he should,filter的区别
## must he should 会贡献相关性得分
GET bank/_search
{
"query": {
"bool": {
"must": [
{"range": {
"age": {
"gte": 18,
"lte": 30
}
}}
]
}
}
}
## filter 不会计算相关性得分
GET bank/_search
{
"query": {
"bool": {
"filter": [
{"range": {
"age": {
"gte": 18,
"lte": 30
}
}}
]
}
}
}
6.3 term的使用
term 和 match 一样。匹配某个属性的值。全文检索字段用 match,其他非 text 字段匹配用 term。
## term 和 match 一样。匹配某个属性的值。全文检索字段用 match,其他非 text 字段匹配用 term。
GET bank/_search
{
"query": {
"term": {
"age": {
"value": 28
}
}
}
}
6.4 keyword 精确匹配
## 精确匹配
GET bank/_search
{
"query": {
"match": {
"address.keyword": "Rutledge Street"
}
}
}
6.5 符合查询 bool
## 复合查询
## 查询性别为m并且地址中包含 mill的数据
GET bank/_search
{
"query": {
"bool": {
"must": [
{"match": {
"gender": "m"
}},
{
"match": {
"address": "mill"
}
}
]
}
}
}
## 复合查询
## 查询处性别为m并且年龄在18到30之间的病情年龄不能为32的
GET bank/_search
{
"query": {
"bool": {
"must": [
{"match": {
"gender": "m"
}}
],
"must_not": [
{"match": {
"age": "20"
}}
],
"should": [
{"match": {
"lastname": "Bond"
}}
],
"filter": {
"range": {
"age": {
"gte": 18,
"lte": 30
}
}
}
}
}
}
6.6 聚合查询
## 聚合此操作
## 搜索address中包含mill的所有人的年龄分布以及平均年龄
GET bank/_search
{
"query": {
"match": {
"address": "mill"
}
},
"aggs": {
"ageAgg": {
"terms": {
"field": "age",
"size": 10
}
},
"ageAvg":{
"avg": {
"field": "age"
}
},
"balanceAvg":{
"avg": {
"field": "balance"
}
}
},
"size": 0
}
## 聚合操作
## 按照年龄聚合,并且请求这些年龄段的这些人的平局薪资
GET bank/_search
{
"query": {
"match_all": {}
},
"aggs": {
"ageAgg": {
"terms": {
"field": "age",
"size": 100
},
"aggs": {
"ageAvg": {
"avg": {
"field": "balance"
}
}
}
}
},
"size": 0
}
## 聚合操作
## 查出所有年龄分布,并且这些年龄端中性别M,F的平均年薪以及这个年龄段性别的总体平均年薪
GET bank/_search
{
"query": {
"match_all": {}
},
"aggs": {
"ageAgg": {
"terms": {
"field": "age",
"size": 100
},
"aggs": {
"genderAgg": {
"terms": {
"field": "gender.keyword",
"size": 10
},
"aggs": {
"ageAgg": {
"avg": {
"field": "balance"
}
}
}
},
"ageGenderAgg":{
"avg": {
"field": "balance"
}
}
}
}
},
"size": 1
}
6.7 数据迁移
Es7 及以上移除了 type 的概念。
将已存在的索引下的类型数据,全部迁移到指定位置即可。
第一步:创建映射
PUT /my-index
{ "mappings": { "properties": {"age": { "type": "integer" }, "email": { "type": "keyword" }, "name": { "type": "text" }
}
}
}
第二步:添加新的字段映射
PUT /my-index/_mapping
{ "properties": { "employee-id": { "type": "keyword", "index": false
}
}
}
第三步:更新映射
对于已经存在的映射字段,我们不能更新。更新必须创建新的索引进行数据迁移
第四步:数据迁移
先创建出 new_twitter 的正确映射。然后使用如下方式进行数据迁移
POST _reindex [固定写法]
{ "source": { "index": "twitter"
},"dest": { "index": "new_twitter"
}
}
将旧索引的 type 下的数据进行迁移
POST _reindex
{ "source": {"index": "twitter", "type": "tweet"
},"dest": { "index": "tweets"
}
}
7、安装ik中文分词库,以及使用xshell和xftp工具
第一步:修改Vagrant的密码登录功能
vi /etc/ssh/sshd_config
修改:PasswordAuthentication no 为 PasswordAuthentication yes 并保存推出
第二步:重启ssh服务
service sshd restart
第三步:通过xshell连接linux服务器
第四步:通过xft上传文件并解压程序
由于做了挂在,所在在elasticsearch内部的文件夹下也是可以看到的。
第五步:修改ik文件夹的读写可执行权限
chmod -R 777 /mydata/elasticsearch/plugins/ik/
ll
第六步:查看elasticsearch的插件列表
docker exec -it 610d /bin/bash
cd bin
elasticsearch-plugin list
返回ik 表示插件安装成功
第六步: 重启elasticsearch
第七步:测试
重启elasticsearch后,刷新一下kibana页面
## 分词
## 标准分词器,es中默认的分词器支持的时英文的分词,对于中文的分词我们需要额外的安装自己的分词器
## 中文分词器:ik分词器下载地址:https://github.com/medcl/elasticsearch-analysis-ik/releases/tag/v7.4.2
## 注意由于我们的es版本时7.4.2 所以ik分词器的版本也要是7.4.2
POST _analyze
{
"analyzer": "standard",
"text": "尚硅谷电商项目"
}
## 使用ik_smart 分词器
POST _analyze
{
"analyzer": "ik_smart",
"text": "我是中国人"
}
## 使用ik_max_word 分词器
POST _analyze
{
"analyzer": "ik_max_word",
"text": "我是中国人"
}
测试结果:
8、自定义分ik分词库
默认的分词库给我们提供了基本的分词功能,但是对于某些网络热词和一些特殊词,时无法分词,这时候就需要我们自己去定义分词库
第一步:修改/usr/share/elasticsearch/plugins/ik/config/中的 IKAnalyzer.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict"></entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords"></entry>
<!--用户可以在这里配置远程扩展字典 -->
<entry key="remote_ext_dict"><font color="red">http://192.168.128.130/fenci/myword.txt</font></entry>
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
http://192.168.128.130/fenci/myword.txt 这个时nginx的地址 内容如下
第二步:重启es容器
第三步:刷新kibana测试
9、java整合elasticsearch
最终选择:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high.html
第一步:添加依赖
注意:
boot的版本为:2.1.8.RELEASE
由于我们用的es的版本时7.4.2 与springboot为我们维护的版本不同所以需要改一下es的版本。
<elasticsearch.version>7.4.2</elasticsearch.version>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.4.2</version>
</dependency>
完整配置:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.atguigu.gulimall</groupId>
<artifactId>gulimall-search</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>gulimall-search</name>
<description>ElasticSearch检索服务</description>
<properties>
<java.version>1.8</java.version>
<elasticsearch.version>7.4.2</elasticsearch.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 导入ElasticSearch的操作工具类-->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.4.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
第二步:添加es的配置,创建一个RestHighLevelClient 到ioc容器中
192.168.56.10 这个地址是我本地的linux地址
@Configuration
public class GulimallElasticSearchConfig {
/**
* 用于安全校验的配置
*/
public static final RequestOptions COMMON_OPTIONS;
static {
RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
// builder.addHeader("Authorization", "Bearer " + TOKEN);
// builder.setHttpAsyncResponseConsumerFactory(
// new HttpAsyncResponseConsumerFactory
// .HeapBufferedResponseConsumerFactory(30 * 1024 * 1024 * 1024));
COMMON_OPTIONS = builder.build();
}
/**
* 配置ElasticSearch地址,得到操作对象
* @return
*/
@Bean
public RestHighLevelClient esRestClient(){
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(new HttpHost("192.168.56.10", 9200, "http")));
return client;
}
}
第三步:通过api文档调用https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high.html
package com.atguigu.gulimall.search;
import com.alibaba.fastjson.JSON;
import com.atguigu.gulimall.search.config.GulimallElasticSearchConfig;
import lombok.Data;
import lombok.ToString;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.Avg;
import org.elasticsearch.search.aggregations.metrics.AvgAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;
@SpringBootTest
@RunWith(SpringRunner.class)
public class GulimallSearchApplicationTests {
@Resource
private RestHighLevelClient client;
/**
* 复杂的聚合操作
* 查询处地址中带有mill,按照年龄聚合,并且请求这些年龄段的这些人的平局薪资
*/
@Test
public void searchData() throws IOException{
// 1. 创建检索请求
SearchRequest searchRequest = new SearchRequest();
// 2.指定索引
searchRequest.indices("bank");
// 3. 指定DSL ,检索条件
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchRequest.source(searchSourceBuilder);
// 3.1 构造检索条件,所有的跟操作都可以找到
searchSourceBuilder.query(QueryBuilders.matchQuery("address","mill"));
// 3.2 按照年龄聚合
TermsAggregationBuilder ageAgg = AggregationBuilders.terms("ageAgg").field("age").size(10);
searchSourceBuilder.aggregation(ageAgg);
AvgAggregationBuilder banlceAvg = AggregationBuilders.avg("balanceAgg").field("balance");
searchSourceBuilder.aggregation(banlceAvg);
System.out.println("maruis------>" + searchSourceBuilder);
// 4.执行检索
SearchResponse searchResponse = client.search(searchRequest, GulimallElasticSearchConfig.COMMON_OPTIONS);
System.out.println("maruis------>" + searchResponse.toString());
// 5. 结果分析
//Map map = JSON.parseObject(searchResponse.toString(), Map.class);
SearchHits hits = searchResponse.getHits();
SearchHit[] hitses = hits.getHits();
for (SearchHit hit:hitses){
// _index,_type,_id,_score
// hit.getIndex();
// hit.getType();
// hit.getId();
// hit.getScore();
// _source
String sourceAsString = hit.getSourceAsString();
Accout accout = JSON.parseObject(sourceAsString,Accout.class);
System.out.println("maruis------>" + accout.toString());
}
Aggregations aggregations = searchResponse.getAggregations();
// for(Aggregation agg:aggregations.asList()){
// System.out.println("maruis---当前聚合--->" + agg.getName());
// }
Terms ageAgg1 = aggregations.get("ageAgg");
List<? extends Terms.Bucket> buckets = ageAgg1.getBuckets();
for(Terms.Bucket bucket:buckets){
String keyAsString = bucket.getKeyAsString();
System.out.println("maruis----年龄:-->" +keyAsString+" 人数:"+bucket.getDocCount());
}
Avg balanceAgg = aggregations.get("balanceAgg");
System.out.println("maruis----平均薪资:-->" + balanceAgg.getValue());
}
/**
* 验证es客户操作类是否可用
*/
@Test
public void contextLoads() {
System.out.println("maruis------>" + client);
}
/**
* 测试存储数据到es
*/
@Test
public void indexData() throws IOException {
IndexRequest indexRequest = new IndexRequest("users");
// 唯一id
indexRequest.id("1");
//indexRequest.source("userName","张三","gender","男","age",18);
User user = new User();
user.setUserName("张三");
user.setGender("男");
user.setAge(23);
String jsonString= JSON.toJSONString(user);
indexRequest.source(jsonString, XContentType.JSON); // 要保存的数据
// 执行保存操作
IndexResponse index = client.index(indexRequest, GulimallElasticSearchConfig.COMMON_OPTIONS);
System.out.println("maruis------>" + index);
}
@Data
class User{
private String userName;
private String gender;
private Integer age;
}
@Data
@ToString
static class Accout{
private int account_number;
private int balance;
private String firstname;
private String lastname;
private int age;
private String gender;
private String address;
private String employer;
private String email;
private String city;
private String state;
}
}
linux下安装wget和unzip工具
yum install wget -y
yum install unzip -y
nigix安装
随便启动一个 nginx 实例,只是为了复制出配置
docker run -p 80:80 --name nginx -d nginx:1.10
将容器内的配置文件拷贝到当前目录:docker container cp nginx:/etc/nginx . 别忘了后面的点
修改文件名称:mv nginx conf 把这个 conf 移动到/mydata/nginx 下
终止原容器:docker stop nginx
执行命令删除原容器:docker rm $ContainerId
创建新的 nginx;执行以下命令
docker run -p 80:80 --name nginx
-v /mydata/nginx/html:/usr/share/nginx/html
-v /mydata/nginx/logs:/var/log/nginx
-v /mydata/nginx/conf:/etc/nginx
-d nginx:1.10
给 nginx 的 html 下面放的所有资源可以直接访问;