Spring cloud + Nacos configuration center project is published to the server, and nginx is configured

Keywords: Nginx Java Docker Spring

My environment
Windows10
JDK8
SpringCloud: Hoxton.SR1
SpringBoot: 2.2.4.RELEASE
Spring cloud Alibaba dependencies: 2.1.1.RELEASE (Note: package name starts with com.alibaba.cloud)
Nacos-server: NACOS1.1.4

2. Start nacos service (stand-alone mode & embedded database)
0. Premise: configure JAVA_HOME environment variable. If not configured, Nacos will not run
1. Download source code or installation package
Installation package address: https://github.com/alibaba/nacos/releases
2. After decompression, enter the nacos/bin directory
3. Enter the command to start the service
linux: sh startup.sh -m standalone
windows: cmd startup.cmd
4. When the console is started, the "Nacos started successfully in stand alone mode." indicates that the service has been started
5.nacos uses port 8848 by default. You can access the console interface through http://127.0.0.1:8848/nacos/index.html. The default user name / password is nacos/nacos

3. Configure related pom configuration files

<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.1.1.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
       

        <!-- 1. nacos-Service discovery feature dependency -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>0.2.2.RELEASE</version>
        </dependency>

        <!-- 2. nacos-Configuration management function is dependent, which is not available at present -->
        <!--        <dependency>-->
        <!--            <groupId>org.springframework.cloud</groupId>-->
        <!--            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>-->
        <!--            <version>0.2.2.RELEASE</version>-->
        <!--        </dependency>-->

        Note: version 0.2.x.RELEASE The corresponding is Spring Boot 2.x Version, version 0.1.x.RELEASE The corresponding is Spring Boot 1.x Edition.
                  For example: springboot2.2.4.RELEASE Corresponding 0.2.2RELEASE

4. Modify application.properties. Add some configuration about Nacos, and remove the configuration about Eureka
#Specify the ip and port number of nacos and register with nacos
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

5. Modify the notes related to startup class replacement. If @ EnableEurekaClient is added to your application startup class, you need to modify it to @ EnableDiscoveryClient
@SpringBootApplication
//@EnableEurekaClient
@EnableDiscoveryClient
public class ProviderApplication {...}

Just start your application, so far, you have implemented "zero line code replace Eureka with Nacos"!

Appendix 1: differences between dependency management and dependencies
1.dependencies even if the dependency is not written in the child project, the child project will inherit the dependency from the parent project (inherit all)
2. Dependency management only declares dependencies and does not implement the introduction. Therefore, the dependencies required for the declaration of the subproject need to be displayed.
If a dependency is not declared in a child project, it will not be inherited from the parent project; only if the dependency is written in the child project and no specific version is specified, it will be inherited from the parent project,
Both version and scope are read from the parent pom; in addition, if the version number is specified in the subproject, the jar version specified in the subproject will be used

Appendix 2: nacos fails to start in windows, showing that port 8848 is occupied
Plan 1: restart the computer
Scheme 2: modify the port number in the file nacos/conf/application.properties, for example:
server.port=8848 ==> server.port=18848

6. Configure the configuration file of the service gateway to the public name storage space of nacos, because the access key s of other spaces will change with the change of the system when the project is published. The default is the same for public

Configure what you want to access the database, and the service gateway connection path can be searched
Spring cloud gateway configuration

for instance:

{
  "refreshGatewayRoute": true,  //Refresh gateway route to true to refresh by default
  "routeList": [
    {
      "id": "user-service-api02",  //Distinguish id
      "predicates": [
        {
          "name": "Path",
          "args": {
            "_genkey_0": "/usr02/**"  //Access path + ant style expression
          }
        }
      ],
      "filters": [
        {
          "name": "StripPrefix",
          "args": {
            "_genkey_0": "1" 
          }
        }
      ],
      "uri": "lb://User service API ", / / the name of the consumer you are visiting
      "order": 0
    }
  ]
}

7. Configuration of service gateway
The contents are as follows:

package com.zking.gatewayserver.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import com.zking.gatewayserver.entity.FilterEntity;
import com.zking.gatewayserver.entity.PredicateEntity;
import com.zking.gatewayserver.entity.RouteEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Mono;

import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Executor;

/**
 * This class implements the dynamic routing of Spring Cloud Gateway + nacos. It implements an event push interface provided by Spring, ApplicationEventPublisherAware
 */
@Component
public class DynamicRoutingConfig implements ApplicationEventPublisherAware {

    private final Logger logger = LoggerFactory.getLogger(DynamicRoutingConfig.class);

    //private static final String DATA_ID = "zuul-refresh-dev.json";
    //private static final String Group = "DEFAULT_GROUP";

    @Autowired
    private RouteDefinitionWriter routeDefinitionWriter;

    @Autowired
    private GatewayNacosProperties gatewayNacosProperties;

    private ApplicationEventPublisher applicationEventPublisher;


    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }

    /**
     * This method is mainly responsible for listening to the configuration changes of Nacos. First, build a ConfigService with parameters, and then start a listening with ConfigService,
     * And refresh the route information in the listening method.
     *
     * @throws NacosException
     */
    @Bean
    public void refreshRouting() throws NacosException {
        Properties properties = new Properties();
        properties.put(PropertyKeyConst.SERVER_ADDR, gatewayNacosProperties.getServerAddr());
//        properties.put(PropertyKeyConst.NAMESPACE, gatewayNacosProperties.getNamespace());
        ConfigService configService = NacosFactory.createConfigService(properties);

        //To solve the problem that the original configuration of nacos cannot be read and it needs to be updated to read the configuration bug 5000: the maximum waiting time
        String json=configService.getConfig(gatewayNacosProperties.getDataId(),gatewayNacosProperties.getGroup(),5000);
        this.parsejson(json);
        System.out.println("json:"+json);


        configService.addListener(gatewayNacosProperties.getDataId(), gatewayNacosProperties.getGroup(), new Listener() {
            @Override
            public Executor getExecutor() {
                return null;
            }

            @Override
            public void receiveConfigInfo(String configInfo) {
//                parsejson(configInfo);
                logger.info(configInfo);
                boolean refreshGatewayRoute = JSONObject.parseObject(configInfo).getBoolean("refreshGatewayRoute");

                if (refreshGatewayRoute) {
                    List<RouteEntity> list = JSON.parseArray(JSONObject.parseObject(configInfo).getString("routeList")).toJavaList(RouteEntity.class);

                    for (RouteEntity route : list) {
                        update(assembleRouteDefinition(route));
                    }
                } else {
                    logger.info("Route unchanged");
                }

            }
        });
    }

    /**
     *Parsing json to get route information
     * @param json
     */
    public void parsejson(String json){
        logger.info(json);
        boolean refreshGatewayRoute = JSONObject.parseObject(json).getBoolean("refreshGatewayRoute");

        if (refreshGatewayRoute) {
            List<RouteEntity> list = JSON.parseArray(JSONObject.parseObject(json).getString("routeList")).toJavaList(RouteEntity.class);

            for (RouteEntity route : list) {
                update(assembleRouteDefinition(route));
            }
        } else {
            logger.info("Route unchanged");
        }

    }


    /**
     * Routing update
     *
     * @param routeDefinition
     * @return
     */
    public void update(RouteDefinition routeDefinition) {

        try {
            this.routeDefinitionWriter.delete(Mono.just(routeDefinition.getId()));
            logger.info("Route updated successfully");
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }

        try {
            routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
            this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
            logger.info("Route updated successfully");
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
    }

    public RouteDefinition assembleRouteDefinition(RouteEntity routeEntity) {

        RouteDefinition definition = new RouteDefinition();

        // ID
        definition.setId(routeEntity.getId());

        // Predicates
        List<PredicateDefinition> pdList = new ArrayList<>();
        for (PredicateEntity predicateEntity : routeEntity.getPredicates()) {
            PredicateDefinition predicateDefinition = new PredicateDefinition();
            predicateDefinition.setArgs(predicateEntity.getArgs());
            predicateDefinition.setName(predicateEntity.getName());
            pdList.add(predicateDefinition);
        }
        definition.setPredicates(pdList);

        // Filters
        List<FilterDefinition> fdList = new ArrayList<>();
        for (FilterEntity filterEntity : routeEntity.getFilters()) {
            FilterDefinition filterDefinition = new FilterDefinition();
            filterDefinition.setArgs(filterEntity.getArgs());
            filterDefinition.setName(filterEntity.getName());
            fdList.add(filterDefinition);
        }
        definition.setFilters(fdList);

        // URI
        URI uri = UriComponentsBuilder.fromUriString(routeEntity.getUri()).build().toUri();
        definition.setUri(uri);

        return definition;
    }
}
package com.zking.gatewayserver.config;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

/**
 * 1. Save nacos related properties in gateway
 * 2. These are custom configuration properties, which are saved in the configuration file application.yml
 * 3. Read through @ ConfigurationProperties annotation
 */
//@ConfigurationProperties(prefix = "gateway.nacos", ignoreUnknownFields = true)
@Configuration
@Data
public class GatewayNacosProperties {

    @Value("${gateway.nacos.server-addr}")
    private String serverAddr;

//    @Value("${gateway.nacos.namespace}")
//    private String namespace;

    @Value("${gateway.nacos.data-id}")
    private String dataId;

    @Value("${gateway.nacos.group}")
    private String group;

}
package com.zking.gatewayserver.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import reactor.core.publisher.Mono;

/**
 * Request current limiting configuration
 */
@Configuration
public class RequestRateLimiterConfig {

    /**
     * Limit current by IP
     */
    @Bean
    public KeyResolver ipAddrKeyResolver() {//A new feature of JDK8 -- Lambda expression
        return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
    }

    ///**
    // * Current limit by user
    // */
    //@Bean
    //KeyResolver userKeyResolver() {
    //    return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
    //}

    ///**
    // * Flow restriction by URL, that is, the number of requests per second is grouped by URL. All URL requests exceeding the flow restriction will return 429 status
    // *
    // * @return
    // */
    //@Bean
    //@Primary
    //KeyResolver apiKeyResolver() {
    //    return exchange -> Mono.just(exchange.getRequest().getPath().toString());
    //}
}
package com.zking.gatewayserver.entity;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Filter entity class
 */
public class FilterEntity {

    //Name of filter
    private String name;

    //Routing rules
    private Map<String, String> args = new LinkedHashMap<>();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Map<String, String> getArgs() {
        return args;
    }

    public void setArgs(Map<String, String> args) {
        this.args = args;
    }
}
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Route assertion entity class
 */
public class PredicateEntity {

    //Assert the corresponding Name
    private String name;

    //Assertion rule
    private Map<String, String> args = new LinkedHashMap<>();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Map<String, String> getArgs() {
        return args;
    }

    public void setArgs(Map<String, String> args) {
        this.args = args;
    }
}
package com.zking.gatewayserver.entity;

import java.util.ArrayList;
import java.util.List;

/**
 * Routing entity class
 */
public class RouteEntity {

    //Routing id
    private String id;

    //Route assertion collection
    private List<PredicateEntity> predicates = new ArrayList<>();

    //Route filter collection
    private List<FilterEntity> filters = new ArrayList<>();

    //Destination uri of routing and forwarding
    private String uri;

    //Order of route execution
    private int order = 0;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public List<PredicateEntity> getPredicates() {
        return predicates;
    }

    public void setPredicates(List<PredicateEntity> predicates) {
        this.predicates = predicates;
    }

    public List<FilterEntity> getFilters() {
        return filters;
    }

    public void setFilters(List<FilterEntity> filters) {
        this.filters = filters;
    }

    public String getUri() {
        return uri;
    }

    public void setUri(String uri) {
        this.uri = uri;
    }

    public int getOrder() {
        return order;
    }

    public void setOrder(int order) {
        this.order = order;
    }
}

7.1 YML file configuration

server:
  #The 5000 port number here is like the 8080 of the previously external tomcat. Let's access it through a browser
  #But this service only makes a route, it will route the request to other micro services (generally consumers) for processing
  port: 5000

spring:
  application:
    #Micro service name
    name: gateway-server
  cloud:
    nacos:
      discovery:
        #Specify the address of the nacos registry
        server-addr: zz.com:8848    
        //This zz.com is your local domain name 127.0.0.1 open / / C:\Windows\System32\drivers\etc\hosts, add 1 line at the end
  //          127.0.0.1   zz.com
                  
    gateway:
      discovery:
        locator:
          #Whether to combine with the service discovery component and forward to the specific service instance through serviceid (which must be set to uppercase). Default false
          #true means to turn on routing rules based on service discovery.
          #The default rule can't be accessed
          enabled: false
          #serviceId does not need to be capitalized when accessing after configuration
          lower-case-service-id: true
      # routes: a route consisting of a unique ID, a destination service address (uri), a set of predicates, and a set of filters. Filters are not required.)
      routes:
        # http://localhost:5000/usr/hello
        #Routing id (id: id, unique)
        - id: student-router
          #The destination service address (uri: address, address after request forwarding) will automatically obtain the service IP from the registration center, and it does not need to be written down manually
          uri: lb://student-api
          #Priority, the smaller the priority
          #order: 999
          #Route conditions (predicates: assertions)
          predicates:
            # Path matching,
            - Path=/student/**
          filters:
            - name: Hystrix
              args:
                name: fallback
                fallbackUri: forward:/fallback
            - name: RequestRateLimiter
              args:
                #The Bean Name of the object,Use SpEL Expression based on#{@ beanName} get Bean object
                key-resolver: '#{@ipAddrKeyResolver}'
                #Token bucket filling rate, how many requests can the user process per second
                redis-rate-limiter.replenishRate: 20
                #Total capacity of token bucket, the maximum number of requests allowed to complete in one second
                redis-rate-limiter.burstCapacity: 100
            - StripPrefix=1
  redis:
    host: 192.168.68.133
    port: 6379
    password: 123
    database: 0

ribbon:
  eager-load:
    enabled: true
    clients: user-service-api


logging:
  level:
    #The log level of opening spring cloud gateway is debug, which is convenient for debugging
    org.springframework.cloud.gateway: trace
    org.springframework.http.server.reactive: debug
    org.springframework.web.reactive: debug
    reactor.ipc.netty: debug

#springboot monitors the activator, exposing all endpoints
management:
  endpoints:
    web:
      exposure:
        include: '*'


#Custom configuration
gateway:
  nacos:
    server-addr: ${spring.cloud.nacos.discovery.server-addr}
    #namespace: 558dc9bc-a775-41ad-9f26-43ca3aa73e6b / / comment out the default public
    data-id: dynamic-routing.json    //The name of the configuration file in nacos
    group: DEFAULT_GROUP

8. After configuration and testing, it can be published as jar package
8.1

Modify pom of main module
     <version>0.0.1-SNAPSHOT</version>
     <! -- 1. Change to pom instead of jar -- >
     <!--
     <packaging>jar</packaging>
     -->
     <packaging>pom</packaging> 

     <! -- 2. Do not configure plug-ins in the main module -- >
     <build></build>

8.2. Add plug-in dependency in pom.xml file of each sub module module

 <build>
    <plugins>
        <!--Add to maven Plug-in unit-->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <!--Add your own startup class path!-->
                <mainClass>com.imooc.DemoApplication</mainClass>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <!--You can package all the dependent packages into the generated ones Jar In bag-->
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
 </build>

8.3 click view of idea Tool windows maven projects
Double click clean (remove the previously typed package target folder) -, and then create install
First compile the parent module - common module - other modules

8.4. Copy the jar package under the target directory of each sub module of the project to the specified directory, for example: d:\temp\apps directory, and then run it directly through the java command
cmd
d:
cd d:\temp\apps
java -jar *.jar --spring.profiles.active=xxx

  For example:

java -jar student-service-0.0.1-SNAPSHOT.jar / / no parameters
java -jar eureka-server-cluster-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer2 / / with parameters

java -jar student-service-0.0.1-SNAPSHOT.jar
java -jar student-api-0.0.1-SNAPSHOT.jar
java -jar gateway-server-0.0.1-SNAPSHOT.jar

Note: for the configuration of the specified environment (spring.cloud.nacos.config.namespace=83eed625-d166-4619-b923-93df2088883a), do not configure it in the bootstrap.yml of the application.
Instead, in the start command of publishing script, it is more flexible to specify dynamically by adding parameters after the command, for example:
-Dspring.profiles.active=DEV
–spring.cloud.nacos.config.namespace=f1ce84ff-c591-42b8-b441-2f0084863904

java -jar nacos-config-client-0.0.1-SNAPSHOT.jar --spring.cloud.nacos.config.namespace=f1ce84ff-c591-42b8-b441-2f0084863904

9. Turn on your Linux server

docker install nacos
    docker pull nacos/nacos-server
    docker run --env MODE=standalone --restart=always --name nacos -d -p 8848:8848 nacos/nacos-server

    Note 1: both windows and linux systems can access nacos by modifying the host file, because the IP address of starting the nacos container in docker is not fixed
             Modify in window:
                  Open hosts, C:\Windows\System32\drivers\etc\hosts, and add 1 line at the end
                  127.0.0.1   zz.com

             How to modify in linux:
              1. Modify hosts file of host
                 vim /etc/hosts
                 ##Add the domain name to be mapped
                 127.0.0.1   zz.com

1. copy your local nacos file to your server's nacos
2. The host creates the folder apps, and rz uploads the eureka-server-cluster.jar package to apps
##This directory will later serve as a data volume, sharing data between the host and the container
mkdir /apps

3. Use the jre:8 image to start the container and mount the specified directory as the data volume

 --Start producer (7001)
 docker run --restart=always \
   --net=host \
   -d \
   -it \
   --name student-server \
   --mount type=bind,source=/apps,target=/apps \    
   jdk8:v3.0 / / this is your docker image name

 - consumers
 docker run --restart=always \
   --net=host \
   -d \
   -it \
   --name student-api \
   --mount type=bind,source=/apps,target=/apps \
   jdk8:v3.0 / / this is your docker image name

  --Start gateway and host 5000: container 5000 port mapping
 docker run --restart=always \
   --net=host \
   -d \
   -it \
   --name gateway\
   --mount type=bind,source=/apps,target=/apps \
   jdk8:v3.0 / / this is your docker image name



 Note 1: jre:8 is a custom image, and JRE 1.8 is installed
 Note 2: the gateway 5000 is mapped to the 5000 end of the host, and the firewall can only be accessed by modifying the 5000 port
    

4. Enter the docker container and the apps directory using java jar The commands run one by one,
After success, you can configure nginx

10. Start to configure nginx
Nginx is also a server. We often do the work of reverse proxy, load balancing, separation of dynamic and static resources,

 2. Install nginx
    1. Search nginx image
      docker search nginx   
  
    2. Pull image
      docker pull nginx 

    3. Create the mount directory in the host
      mkdir -p /data/nginx/{conf,conf.d,html,log}
 
      Note 1: because the vi or vim editor is not installed in the nginx image (installation is too cumbersome), the nginx configuration file cannot be edited,
           So it's more convenient to mount directly through data volume
      Note 2: upload nginx configuration file nginx.conf to the mount directory "/ data/nginx/conf" of the host

      Note 3: package the vue front-end project and upload it to the mount directory "/ data/nginx/html" of the host computer

      Note 1: refer to Appendix II for related debugging commands of nginx configuration file
    
    4. Create nginx container according to nginx image (test the installation and access of nginx, and do not publish any java or vue projects, and the last one to be deleted)
      docker run \
       --name mynginx0 \
       -d -p 80:80 \
       nginx:latest

    5. Check the local container, and you can see that the nginx container has been created successfully
      docker ps 

    6. Test whether nginx is installed successfully
      Open the browser and input: http://192.168.183.133 (http://host ip:80). Normally, the welcome page of nginx will be displayed

Nginx configuration file nginx.conf
#The number of working processes is generally consistent with the number of cpu cores of the computer
worker_processes 1;

events {
#Maximum number of connections for a single process (maximum number of connections = number of connections * number of processes)
worker_connections 1024;
}

http {
include mime.types; file extension and file type mapping table
Default? Type application / octet stream;? Default file type
sendfile on; ා enable the efficient file transfer mode. The sendfile instruction specifies whether nginx calls the sendfile function to output the file. For ordinary applications, it is set to on. If it is used for downloading and other applications with heavy disk IO load, it can be set to off to balance the disk and network I/O processing speed and reduce the system load. Note: if the image display is abnormal, change this to off.

keepalive_timeout 65; #Long connection timeout in seconds
gzip on;#Enable Gizp compression

#Cluster of servers
upstream  tomcats {  #Server cluster name
        #TODO: 172.17.0.3 is the IP address of the docker container 
	server    172.17.0.3:8080  weight=1;#Server configuration weight means weight. The greater the weight, the greater the probability of allocation. Domain name is your current server domain name + port 80 you configured
	server    172.17.0.4:8080  weight=2;
}  

#Current Nginx configuration
server {
	listen       80;#Listen to port 80, which can be changed to other ports
	server_name  localhost;#The domain name of the current service, no domain name can be filled in freely

	root         /usr/share/nginx/html/dist;#The directory of the web site to be visited

	location / {
		try_files $uri $uri/  /index.html;#This code is to solve the problem that history routing cannot jump. It is introduced on the official website of Vue router
	}

	location  ^~/api/ {
	        #^~/api / indicates that the matching prefix is the request of api. If the end of proxy pass has /, the path following / api / * will be directly spliced to the back, that is, api will be removed
		proxy_pass http://tomcats/;
	}
}

}

3.ningx releases java and vue projects
nginx+tomcat to realize reverse proxy and balance
nginx+html static server

1. Create nginx container
  docker run \
   --name mynginx \
   -d -p 80:80 \
   -v /data/nginx/conf/nginx.conf:/etc/nginx/nginx.conf \
   -v /data/nginx/log:/var/log/nginx \
   -v /data/nginx/html:/usr/share/nginx/html \
   nginx:latest

   Note 1: because the vi or vim editor is not installed in the nginx image (installation is too cumbersome), the nginx configuration file cannot be edited, so all data and configurations are mounted through the data volume
        The first - v: mount the main configuration file of nginx to modify the configuration file of the container directly on the host
        The second - v: mount the nginx logs in the container. After the container is running, you can view the nginx logs directly in this directory of the host
        Third - v: Mount static page directory
        Note line breaks and spaces between commands

   Note 2: if the container creation fails, you can view the startup log in the docker container through the following command
        docker logs -f -t --tail line number container name
        docker logs -f -t --tail 100 mynginx

   Note 3: if you want to enter the container, bash instead of sh should be used according to the actual basic image
        docker exec -it mynginx /bin/bash

Remember to allow the firewall to access the port!!!!!

Published 12 original articles, praised 0, visited 606
Private letter follow

Posted by microbluechip on Mon, 02 Mar 2020 18:41:11 -0800