docker部署微服务项目

上次有人说部署单个springboot项目和ssm写的非常的简单可以写一篇docker部署微服务的结构的文章的吗

安排

什么是微服务?

微服务架构是一种将单个应用程序作为一套小型服务开发的方法,每种应用程序


都在自己的进程中运行,采用一组服务的方式来构建一个应用,服务独立部署


在不同的进程中,不同服务通过一些轻量级交互机制来通信的架构思路。

独立性

在开发层面,每个微服务基本上都是各自独立的项目(project),而对


应各自独立项目的研发团队基本上也是独立对应,这样的结构保证了微服务



的并行研发,并且各自快速迭代,不会因为所有研发都投入一个近乎

单点的项目,从而造成开发阶段的瓶颈。开发阶段的独立,保证了微

服务的研发可以高效进行。

可扩展性

我们可以快速地添加服务集群的实例,提升整个微服务集群的服务


能力,而在传统 Monolith 模式下,为了能够提升服务能力,

很多时候必须强化和扩展单一结点的服务能力来达成。如果单结点

服务能力已经扩展到了极限,再寻求扩展的话,就得从软件到硬件整体进行重构。

隔离性

隔离性实际上是可扩展性的基础,当我们将每个微服务都隔离为


独立的运行单元之后,任何一个或者多个微服务的失败都将只影

响自己或者少量其他微服务,而不会大面积地波及整个服务运行体系。

在架构设计上有一种实践模式,即隔板模式(Bulkhead Pattern),


这种架构设计模式的首要目的就是为了隔离系统中的各个功能

单元和实体,使得系统不会因为一个单元或者服务的失败而导致整体失败。

服务独立维护,分工明确

每个微服务都可以交由一个小团队进行开发,测试维护部

署,并对整个生命周期负责,当我们将每个微服务都隔离为

独立的运行单元之后,任何一个或者多个微服务的失败

都将只影响自己或者少量其他微服务,而不会大面积地波及整个服务。

当然,没有完美无瑕的技术,微服务也有自身的不足:

微服务应用是分布式系统,由此会带来固有的复杂性。开发者
需要在RPC或者消息传递之间选择并完成进程间通讯机制。

他们必须写代码来处理消息传递中速度过慢或者不可用等

局部失效问题。当然这并不是什么难事,但相对于单体

式应用中通过语言层级的方法或者进程调用,微服务下这种技术显得
更复杂一些。

简单介绍一下 springcloud


Spring Cloud 5大组件
 
服务发现——Netflix Eureka

客服端负载均衡——Netflix Ribbon

断路器——Netflix Hystrix

服务网关——Netflix Zuul

分布式配置——Spring Cloud Config

以以简单业务介绍springcloud的关系

单体项目

微服务项目

上一篇单体项目的docker部署已经写了,出现问题不会都可以问我

 
 http://mp.weixin.qq.com/s?__biz=MzA4MTAwMzA1Mw==&mid=2247484371&idx=1&sn=f320a2968d7b023c5356af32af354e6e&chksm=9f9ad491a8ed5d873e1d3f1573e0a332c9d46d1bfbade37be174e00e3c5f23e508eeaf76628a&token=1572617989&lang=zh_CN#rd
 

随便找一个项目进行部署

项目的地址

https://gitee.com/moxi159753/mogu_blog_v2/blob/Nacos/mogu_utils/pom.xml

简单的部署。我没有进行全面部署这个项目 教大家搭springcloud项目先搭主项目

记得加 
   <packaging>pom</packaging>
 <modules>
        <module>mogu_utils</module>
        <module>mogu_base</module>
        <module>mogu_xo</module>
        <module>mogu_admin</module>
        <module>mogu_web</module>
        <module>mogu_picture</module>
        <module>mogu_sms</module>
        <module>mogu_search</module>
        <module>mogu_monitor</module>
        <module>mogu_gateway</module>
        <module>mogu_zipkin</module>
        <module>mogu_spider</module>
        <module>mogu_commons</module>
    </modules>
   <spring-cloud.version>2020.0.0-M6</spring-cloud.version>
   
   <dependencyManagement>
          <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

子项目都是springboot项目 Eureka配置

  <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
springboot启动类
@EnableEurekaServer
配置yml
eureka:
  instance:
    hostname: localhost  #EUReka服务端的名字
  client:
    register-with-eureka: false  #是不是向注册中心注册自己
    fetch-registry: false # 自己这个是注册中心
    service-url:     #监听页面
      defaultZone: ${defaultZone:http://127.0.0.1:7002/eureka/}  # 访问这个进入 客服端http://localhost:7001/
server:
  port: ${post:7002}
子eureka
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:7001/eureka/,http://127.0.0.1:7002/eureka/
  instance:
    instance-id: http://localhost:8001
启动类
@EnableDiscoveryClient  // 服务发现
@EnableEurekaClient  //服务发现 自动注册里面

客户端

RestTemplate 是从 Spring3.0 开始支持的一个 HTTP 
请求工具,它提供了常见的REST请求方案的模版,
例如 GET 请求、POST 请求、PUT 请求、DELETE
请求以及一些通用的请求执行方法 exchange 以及 
execute。RestTemplate 继承自 
InterceptingHttpAccessor 
并且实现了 RestOperations 接口,
其中 RestOperations 接口定义了基本的 RESTful 操作,
这些操作在 RestTemplate 中都得到了实现。接下来我们就
来看看这些操作方法的使用

@Configuration
public class ConfigBean {
    @Bean
    @LoadBalanced
    public RestTemplate getrestTemplate(){
        return new RestTemplate();
    }
}
@Controllerpublic class Restcccc {   
@Autowired  
private RestTemplate restTemplate;  
@Autowired   
private DiscoveryClient discoveryClient;
@ResponseBody 
@RequestMapping("/bbbb"
public String  fff(){//      
String  url="http://localhost:8080/user";   
//获取euraka 里面的实例     
List<ServiceInstance> serviceregistration = discoveryClient.getInstances("serviceregistration");     
ServiceInstance serviceInstance = serviceregistration.get(0);//获取注册索引为0 的服务   客户端可以看到  
String url="http://"+serviceInstance.getHost()+":"+serviceInstance.getPort()+"/user";   
String forObject = restTemplate.getForObject(url, String.class);         
http://localhost:8090/user<List><item><commodityid>1</commodityid><commodityname>衣服</commodityname><number>50</number><price>12.0</price></item><item><commodityid>2</commodityid><commodityname>不知道</commodityname><number>30</number><price>12.0</price></item></List>    
return forObject; 
}
}
omponent
@FeignClient(value = "SPRINGBOOT-PROVIDER-DEPYT",fallbackFactory = DeptclientServiceFallbackbanckfactory.class)
public interface DeptClientService {
    @PostMapping("/dept/add")
    public boolean addDEpt(Dept dept);
    @GetMapping("/dpty/{deptno}")
    public Dept queryBy(long deptno);
    @GetMapping("/LIST")
    public List<Dept> queryAll();
}
获取请求

客服端负载均衡——Netflix Ribbon

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-ribbon</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>
启动类加入
@EnableDiscoveryClient  // 服务发现
@EnableEurekaClient  //服务发现 自动注册里面
      //第一个参数  请求的地址  第2个参数   传递的参数   第3个参数   返回的类型    post请求
           return restTemplate.postForObject(REST_URL_PREFTX+"/dept/add",dept,boolean.class);
}
}
           

有工具类的话(弄一个maven项目进行注入到springboot项目中)

hystrlx

分布式系统环境下,服务间类似依赖非常常见,
一个业务调用通常依赖多个基础服务。如下图,
对于同步调用,当库存服务不可用时,
商品服务请求线程被阻塞,当有大批量请求调
用库存服务时,最终可能导致整个商品服务
资源耗尽,无法继续对外提供服务。并且
这种不可用可能沿请求调用链向上传递,这种现象被称为雪崩效应。
<dependency> 
  <groupId>org.springframework.cloud</groupId>  
  <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>    
  <version>1.4.7.RELEASE</version></dependency>
  Hystrix整个工作流如下:

构造一个 HystrixCommand或HystrixObservableCommand对象,
用于封装请求,并在构造方法配置请求被执行需要的参数; 
执行命令,Hystrix提供了4种执行命令的方法,后面详述; 
判断是否使用缓存响应请求,若启用了缓存,且缓存可用,直接使用缓存响应请求。Hystrix支持请求缓存,但需要用户自定义启动; 
判断熔断器是否打开,如果打开,跳到第8步; 
判断线程池/队列/信号量是否已满,已满则跳到第8步; 
执行HystrixObservableCommand.construct()或HystrixCommand.run(),如果执行失败或者超时,跳到第8步;否则,跳到第9步; 
统计熔断器监控指标; 
走Fallback备用逻辑 
返回请求响应
启动类
@EnableEurekaClient
//添加对熔断的支持
@EnableCircuitBreaker
yml
spring:
        application:
        name: springboot-provider-depyt
        datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        username: root
        password: 123456
        url: jdbc:mysql://127.0.0.1:3306/datt?serverTimezone=GMT&useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8
        mybatis:
        mapper-locations: classpath:mapper/*.xml
server:
  port: 8001
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:7001/eureka/,http://127.0.0.1:7002/eureka/
  instance:
    instance-id: springboot-provider-depyt-hystix-8001
    prefer-ip-address: true #可以显示服务的ip地址
info:
  app.name: zhudongdong1
  company.name: kkkkkk1
#开启服务降级
feign:
  hystrix:
    enabled: true
  @GetMapping("/dpty/{deptno}")   
@HystrixCommand(fallbackMethod = "hydtrix_get"
//出现问题进行熔断进入hydtrix_get()方法   
 public Dept GETdeptby(@PathVariable("deptno") long deptno){
    Dept dept = deptService.queryBy((int) deptno);    
    if (dept==null){       
        throw new RuntimeException("这个id不存在 或信息找不到");  
    }  
    return dept;   
}  
@GetMapping("/LIST"
public List<Dept>  GETHHH(){    
    return deptService.queryAll();       
  //  备选择方案  出现错误进行熔断      */
    public Dept hydtrix_get(@PathVariable("deptno") long deptno){  
        
return new Dept().setDeptno(deptno).setDname("id=======>没有对应的信息,").setDb_source("熔断方法  意思就是出现错误就熔断");  
    } 
    
    //Feign服务降级
@Component
public class DeptclientServiceFallbackbanckfactory implements FallbackFactory {
    @Override
    public Object create(Throwable throwable) {
        return new DeptClientService() {
            @Override
            public boolean addDEpt(Dept dept) {
                return false;
            }

            @Override
            public Dept queryBy(long deptno) {
                return new Dept().setDb_source("降级 服务").setDname("11111111111");
            }

            @Override
            public List<Dept> queryAll() {
                return null;
            }
        };
    }
}

服务网关——Netflix Zuul

  <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            <version>1.4.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zuul</artifactId>
            <version>1.4.7.RELEASE</version>
        </dependency>
yml配置
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:7001/eureka/,http://127.0.0.1:7002/eureka/
  instance:
    instance-id: zuul1927
    prefer-ip-address: true
info:
  app.name: 监听你



zuul:
  host:
    connect-timeout-millis: 3000
    socket-timeout-millis: 3000
  routes:
    mydept.serverid: springboot-provider-depyt
    mydept.path: /mydeptcc/**
ribbon:
  ReadTimeout: 3000
  ConnectTimeout: 3000
hystrix:
    command:
      default:
        execution:
          isolation:
            thread:
              timeoutInMilliseconds: 60000
@Component
public class LoginFilter extends ZuulFilter {
    /*
    网关过滤器
     */
    /*

     * filterType:返回字符串,代表过滤器的类型。包含以下4种:
     * -- pre:请求在被路由之前执行
     * -- route:在路由请求时调用
     * -- post:在route和errror过滤器之后调用
     * -- error:处理请求时发生错误调用
     * @return 返回以上四个类型的名称
     */

    @Override
    public String filterType() {
        return "pre";
    }
    /**
     * filterOrder:通过返回的int值来定义过滤器的执行顺序,数字越小优先级越高。
     * @return
     */

    @Override
    public int filterOrder() {
        return 10;
    }
    /**
     * shouldFilter:返回一个Boolean值,判断该过滤器是否需要执行。返回true执行,返回false不执行。
     * @return
     */

    @Override
    public boolean shouldFilter() {
        return true;
    }
    /**
     * run:编写过滤器的具体业务逻辑。
     * @return
     * @throws ZuulException
     */

    @SneakyThrows
    @Override
    public Object run() throws ZuulException {
        System.out.println("执行");
        //获取zuul提供的上下文对象
        RequestContext context = RequestContext.getCurrentContext();
        //获取request对象
        HttpServletRequest request = context.getRequest();
        HttpServletResponse response = context.getResponse();
        System.out.println(request);
        String deptno = request.getParameter("deptno");
        System.out.println(deptno);
        Integer d=Integer.parseInt(deptno);
        if (d==1){

            System.out.println("============>我是网关过滤器<============");
            //过滤该请求,不对其进行路由
            context.setSendZuulResponse(false);
            //设置响应码401
            context.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);
            //设置响应体
            response.setContentType("text/html;charset=UTF-8");
            PrintWriter writer = response.getWriter();
            writer.println("以前可以访问  现在老子给过滤了 就是不要你访问 打我");


//
            /*    context.setResponseBody("以前可以访问  现在老子给过滤了 就是不要你访问 打我");
            执行
org.springframework.cloud.netflix.zuul.filters.pre.Servlet30RequestWrapper@5df6e8ef
1
============>我是网关过滤器<============
页面输出 以前可以访问 现在老子给过滤了 就是不要你访问 打我
             */
        }
        return null;
    }
}
启动类
@EnableZuulProxy
@EnableEurekaClient

分布式配置——Spring Cloud Config

配置
spring.cloud.config.server.git.uri=https://gitee.com/zhu_dongdong/springcloud-config.git
#2021-01-18 19:05:48.903  INFO 4432 --- [nio-8080-exec-8] o.s.c.c.s.e.NativeEnvironmentRepository  : Adding property source: file:/C:/Users/lenovo/AppData/Local/Temp/config-repo-2610732798174323820/config-server.ym
server.port=3344
spring.application.name=config-demo
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka/
 启动类
@EnableConfigServer //客户端
@EnableEurekaClien     

总结

Eureka:各个服务启动时,Eureka Client都会将服务注册到Eureka Server,并且Eureka Client还可以反过来从Eureka Server拉取注册表,从而知道其他服务在哪里
Ribbon:服务间发起请求的时候,基于Ribbon做负载均衡,从一个服务的多台机器中选择一台
Feign:基于Feign的动态代理机制,根据注解和选择的机器,拼接请求URL地址,发起请求
Hystrix:发起请求是通过Hystrix的线程池来走的,不同的服务走不同的线程池,实现了不同服务调用的隔离,避免了服务雪崩的问题
Zuul:如果前端、移动端要调用后端系统,统一从Zuul网关进入,由Zuul网关转发请求给对应的服务

部署 配置docker

 <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <!-- docker的maven插件,官网:https://github.com/spotify/docker-maven-plugin -->
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>0.4.13</version>
                <configuration>
                    <!-- 注意imageName一定要是符合正则[a-z0-9-_.]的,否则构建不会成功 -->
                    <!-- 详见:https://github.com/spotify/docker-maven-plugin    Invalid repository name ... only [a-z0-9-_.] are allowed-->
                    <imageName>article</imageName>
                    <baseImage>jdk1.8</baseImage>
                    <entryPoint>["java""-jar""/${project.build.finalName}.jar"]</entryPoint>
                    <resources>
                        <resource>
                            <targetPath>/</targetPath>
                            <directory>${project.build.directory}</directory>
                            <include>${project.build.finalName}.jar</include>
                        </resource>
                    </resources>
                    <dockerHost>http://192.168.66.138:2375</dockerHost>
                </configuration>
            </plugin>
        </plugins>

第2中

<!--spring boot打包的话需要指定一个唯一的入门-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <!-- 指定该Main Class为全局的唯一入口 -->
                    <mainClass>com.moxi.mogublog.admin.AdminApplication</mainClass>
                    <layout>ZIP</layout>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal><!--可以把依赖的包都打包到生成的Jar包中-->
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <!--docker镜像build插件-->
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>1.2.0</version>
                <configuration>
                    <!-- 注意imageName一定要是符合正则[a-z0-9-_.]的,否则构建不会成功 -->
                    <imageName>registry.cn-shenzhen.aliyuncs.com/mogublog/${project.artifactId}</imageName>
                    <dockerDirectory>${project.basedir}/src/main/resources</dockerDirectory>
                    <rm>true</rm>
                    <resources>
                        <resource>
                            <targetPath>/</targetPath>
                            <directory>${project.build.directory}</directory>
                            <include>${project.build.finalName}.jar</include>
                        </resource>
                    </resources>
                </configuration>
            </plugin>
        </plugins>
    </build>

进行配置先去编写dockerfile

FROM java:alpine
VOLUME /tmp
ADD mogu_admin-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java","-Xms256m","-Xmx256m","-jar","/app.jar"]

前端的话

FROM registry.cn-shenzhen.aliyuncs.com/mogublog/nginx:latest
ADD ./dist/ /usr/share/nginx/html
RUN sed -i 's/\r$//' /usr/share/nginx/html/env.sh
RUN chmod +x /usr/share/nginx/html/env.sh
ENTRYPOINT ["/usr/share/nginx/html/env.sh"]
CMD ["nginx""-g""daemon off;"]
自动生成nginx镜像 没有配置端口但是启动了

先去idea插件去安装docker

在run进行配置 docker没有2379可以去百度开启 博客

https://blog.youkuaiyun.com/qq_28796037/article/details/115002327?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_title~default-0.control&spm=1001.2101.3001.4242

后端 前端 记得root的maven进行install进行整体打包(全打成jar包) 启动jar的话 进行点击启动进行生成镜像 点击docker ps 启动的话记得连接docker的mysql

docker 挂载的mysql启动

docker run --name mysql -d -it -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root mysql:5.7.27

密码root

账号root

不加--name

docker run -d -it -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root mysql:5.7.27

redis

docker run -d -p 6378:6379 --name port-redis redis

docker run -p 6379:6379 --name redis -v /root/redis/redis.conf:/etc/redis/redis.conf 
 -v /root/redis/data:/data -d redis:latest redis-server /etc/redis/redis.conf --appendonly yes
-p 6379:6379:把容器内的6379端口映射到宿主机
6379端口-v /root/redis/redis.conf:/etc/redis/redis.conf
:把宿主机配置好的redis.conf放到容器内的这个位置中-v 
/root/redis/data:/data:
把redis持久化的数据在宿主机内显示,
做数据备份redis-server /etc/redis/redis.conf:
这个是关键配置,让redis不是无配置启动,
而是按照这个redis.conf的配置启动–appendonly yes:
redis启动后数据持久化

nginx

 docker run --name nginx-test -p 8080:80 -d nginx

启动jar和前端

启动是容器要想删除 停止在删除
sudo  docker run -p 7001:7001 客户端的名字(镜像名字):0.01
docker run -p 本机映射端口:镜像映射端口 -d 
--name 启动镜像名称 -e 镜像启动参数  镜像名称:镜像版本号
参数释义:

     -p   本机端口和容器启动端口映射 
     -d   后台运行 
    --name   容器名称 
    -e    镜像启动参数 
去一个一个启动jar
docker  images  出来都是镜像
docker  images  出来都是镜像
出现的问题 删除镜像
删除镜像
docker image rm 镜像名称/镜像ID
删除容器
sudo  docker rm 18e2afef12b5
docker  stop 容器id  停止容器

最后的方法就是在nginx配置2个前端 一个前台一个后台(配置2个nginx端口,可以配置2个html地址 改变访问路径就可以了)

server {
    listen       80;
    server_name  localhost;
    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;
    #第一种方法  这个直接/访问
 
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
    #根/student 访问 指向地点
 
    location /student {
        alias   /usr/share/nginx/student;
        index  index.html index.htm;
        }
    #error_page  404              /404.html;
    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}
    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}
    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

docker的nginx挂载 宿机路径:容器的内的路径 模板

sudo docker run -d -p 3310:3306 -v 
/home/qq3175449063/conf:/etc/mysql/conf.d -v
/home/qq3175449063/data:/var/lib/mysql -e MYSQL_ROOR_PASSWORD=123456 --name mysql01 daocloud.io/library/mysql:5.7

docker run --name mynginx2 -p 2222:80 -v /data/nginx/html:/usr/share/nginx/html -v /data/nginx/conf/nginx.conf:/etc/nginx/nginx.conf  -v /data/nginx/logs:/var/log/nginx -v /data/nginx/conf.d:/etc/nginx/conf.d -d --restart=always nginx:latest
其中-v 就表示挂载目录,也就是说当容器中的nginx配置的访问路径是/usr/share/nginx/html时,实际上访问的是linux中的/data/nginx/html。

进入nginx容器  容器的id
通过docker exec命令进入容器:docker exec -it d554669f2616 /bin/bash
exit退出
记得

遇到的问题

但在 nginx 配置中,如果没有配置任何一个 443 的 https 服务的话,默认服务器是不响应 443 接口的,但是如果一旦配置了一个 443 服务,那么所有的 443 接口都会默认使用这个配置(源于 nginx 的服务搜索策略),所以一旦在私有仓库的 nginx 上配置了其它 443 服务,就需要屏蔽一下仓库域名下 443 接口返回的内容。

解决方案:配置 nginx 的 default_server,默认不进行返回,另外注意默认的 443 虽然不需要返回内容,但仍然需要配置 ssl 证书,否则 nginx 会报错,证书随意。通过 return 444 来中止响应。

复制代码
server {
     listen 443 default_server;
     server_name _ ;
     ssl on;
     ssl_certificate             随便设置一个ssl证书;                
     ssl_certificate_key     随便设置一个ssl证书的key;
     return 444;
}

昨天说挂载后端的项目,现在说挂载前端的2个vue项目,这里先安装2个nginx进行挂载

进行配置挂载的nginx

已经将2个vue的项目拉进去了 进行挂载 2个挂载的nginx.conf是一样的

worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    server {
        listen       80;
        server_name  localhost;
        location / {
            root   /usr/share/nginx/html;
        try_files $uri $uri/ /index.html last; # 别忘了这个哈
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

进行run

docker run --name ngin -d -p 8080:80  -v /home/qq3175449063/nginx1/html:/usr/share/nginx/html -v /home/qq3175449063/nginx1/nginx.conf:/etc/nginx/nginx.conf  -d nginx
docker run --name nginx1  -d  -p 8000:80 -d   registry.cn-shenzhen.aliyuncs.com/mogublog/nginx
docker run --name nginx6 -d -p 8000:80  -v /home/qq3175449063/nginx2/html:/usr/share/nginx/html -v /home/qq3175449063/nginx2/nginx.conf:/etc/nginx/nginx.conf  -d registry.cn-shenzhen.aliyuncs.com/mogublog/nginx

看结果

一个端口号是8000 一个端口号是8080 昨天前端不是写了dockerfile

我们启动看看
sudo  docker run -p 9528:9528    registry.cn-shenzhen.aliyuncs.com/mogublog/vue_mogu_admin

这里少写1个脚本 看

FROM registry.cn-shenzhen.aliyuncs.com/mogublog/nginx:latest
ADD ./dist/ /usr/share/nginx/html
RUN sed -i 's/\r$//' /usr/share/nginx/html/env.sh
RUN chmod +x /usr/share/nginx/html/env.sh
ENTRYPOINT ["/usr/share/nginx/html/env.sh"]
CMD ["nginx""-g""daemon off;"]

脚本(移除启动容器时出现的日志显示)

#!/bin/bash
# set -x
set -e

# Recreate config file
absolute_path=$(cd `dirname $0`; pwd)
env_config=${absolute_path}/env-config.js

rm -rf ${env_config}
touch ${env_config}

# Add assignment
echo "window._env_ = {" >> ${env_config}

# Read each line in .env file
# Each line represents key=value pairs

sed -i '/^[[:space:]]*$/d' ${absolute_path}/.env
while read -r line || [[ -n "$line" ]];
do
  # Split env variables by character `=`
  if printf '%s\n' "$line" | grep -q -e '='then
    varname=$(printf '%s\n' "$line" | sed -e 's/=.*//')
    varvalue=$(printf '%s\n' "$line" | sed -e 's/^[^=]*=//')
  fi

  # Read value of current variable if exists as Environment variable
  value=$(printf '%s\n' "${!varname}")
  # Otherwise use value from .env file
  [[ -z $value ]] && value=${varvalue}

  # Append configuration property to JS file
  echo "  $varname: \"$value\"," >> ${env_config}
done < ${absolute_path}/.env
sed -i '/^[[:space:]]*$/d' ${absolute_path}/.default.env
while read -r line || [[ -n "$line" ]];
do
  # Split env variables by character `=`
  if printf '%s\n' "$line" | grep -q -e '='then
    varname=$(printf '%s\n' "$line" | sed -e 's/=.*//')
    varvalue=$(printf '%s\n' "$line" | sed -e 's/^[^=]*=//')
  fi

  # Read value of current variable if exists as Environment variable
  value=$(printf '%s\n' "${!varname}")
  # Otherwise use value from .env file
  [[ -z $value ]] && value=${varvalue}

  # Append configuration property to JS file
  echo "  $varname: \"$value\"," >> ${env_config}
done < ${absolute_path}/.default.env

echo "}" >> ${env_config}
sed -e "s/\//\\\/g" ${env_config}
STR=`echo $(cat ${env_config}) | sed 's#\/#\\\/#g'`
mv ${absolute_path}/index.html ${absolute_path}/index.html.bak
#sed -e "s/window\.\_env\_.*\}\;/${STR}/g" ${absolute_path}/index.html.bak > ${absolute_path}/index.html
sed -e "s#<script id=env>window._env_.*\};</script>#<script id=env>${STR};</script>#g" ${absolute_path}/index.html.bak > ${absolute_path}/index.html
cat ${env_config}

exec "$@"

我们需要准备两个配置文件 config/vue_mogu_web.env 和 config/vue_mogu_admin.env ,这两个配置文件将在下面Docker compose 脚本中使用到 vue_mogu_web.env

NODE_ENV=production
VUE_MOGU_WEB=http://192.168.1.101:9527
PICTURE_API=http://192.168.1.101:8602
WEB_API=http://192.168.1.101:8603
ELASTICSEARCH=http://192.168.1.101:8605

vue_mogu_admin.env

WEB_API=http://192.168.1.101:8603
FILE_API=http://192.168.1.101:8600/
RABBIT_MQ_ADMIN=http://192.168.1.101:15672
SENTINEL_ADMIN=http://192.168.1.101:8070/sentinel/
EUREKA_API=http://192.168.1.101:8761
Search_API=http://192.168.1.101:8605
ADMIN_API=http://192.168.1.101:8601
Zipkin_Admin=http://192.168.1.101:9411/zipkin/
DRUID_ADMIN=http://192.168.1.101:8601/druid/login.html
SPRING_BOOT_ADMIN=http://192.168.1.101:8606/wallboard
BLOG_WEB_URL=http://192.168.1.101:9527
ELASTIC_SEARCH=http://192.168.1.101:5601
PICTURE_API=http://192.168.1.101:8602
SOLR_API=http://192.168.1.101:8080/solr

vue_mogu_admin.yml

version: '3'
services:
  #授权服务
  vue_mogu_admin:
    image: registry.cn-shenzhen.aliyuncs.com/mogublog/vue_mogu_admin:latest
    container_name: vue_mogu_admin
    restart: always
    ports:
      - 9528:80
    networks:
      - mogu
    env_file:
      - ../config/vue_mogu_admin.env
    environment:
      - COMPOSE_PROJECT_NAME=vue_mogu_admin

networks:
  mogu:
    external: true

vue_mogu_web.yml 的内容如下

version: '3'
services:
  #授权服务
  vue_mogu_admin:
    image: registry.cn-shenzhen.aliyuncs.com/mogublog/vue_mogu_admin:latest
    container_name: vue_mogu_admin
    restart: always
    ports:
      - 9528:80
    networks:
      - mogu
    env_file:
      - ../config/vue_mogu_admin.env
    environment:
      - COMPOSE_PROJECT_NAME=vue_mogu_admin

networks:
  mogu:
    external: true

vue_mogu_web.yml 的内容如下

version: '3'
services:
  #授权服务
  vue_mogu_web:
    image: registry.cn-shenzhen.aliyuncs.com/mogublog/vue_mogu_web:latest
    container_name: vue_mogu_web
    restart: always
    ports:
      - 9527:80
    networks:
      - mogu
    env_file:
      - ../config/vue_mogu_web.env
    environment:
      - COMPOSE_PROJECT_NAME=vue_mogu_web
networks:
  mogu:
    external: true

vue_run.sh


#!/usr/bin/env bash

echo '=====开始运行前台====='

cd docker-compose

echo '=====开始运行mogu_gateway====='

docker-compose -f vue_mogu_admin.yml up -d

echo '=====开始运行mogu_admin====='

docker-compose -f vue_mogu_web.yml up -d

然后开始运行前端的脚本

sh vue_run.sh 其实,制作的镜像里面就包含nginx,然后暴露80端口,映射到我们前端项目上 其实docker的 compose 都是脚本 所有我建议还是使用2个nginx进行部署微服务的前端项目

docker-compose.yml 属性

version:指定 docker-compose.yml 文件的写法格式
services:多个容器集合
build:配置构建时,Compose 会利用它自动构建镜像,该值可以是一个路径,也可以是一个对象,用于指定 Dockerfile 参数
build: ./dir
---------------
build:
    context: ./dir
    dockerfile: Dockerfile
    args:
        buildno: 1
command:覆盖容器启动后默认执行的命令
command: bundle exec thin -p 3000
----------------------------------
command: [bundle,exec,thin,-p,3000]
dns:配置 dns 服务器,可以是一个值或列表
dns: 8.8.8.8
------------
dns:
    - 8.8.8.8
    - 9.9.9.9
dns_search:配置 DNS 搜索域,可以是一个值或列表
dns_search: example.com
------------------------
dns_search:
    - dc1.example.com
    - dc2.example.com
environment:环境变量配置,可以用数组或字典两种方式
environment:
    RACK_ENV: development
    SHOW: 'ture'
-------------------------
environment:
    - RACK_ENV=development
    - SHOW=ture
env_file:从文件中获取环境变量,可以指定一个文件路径或路径列表,其优先级低于 environment 指定的环境变量
env_file: .env
---------------
env_file:
    - ./common.env
expose:暴露端口,只将端口暴露给连接的服务,而不暴露给主机
expose:
    - "3000"
    - "8000"
image:指定服务所使用的镜像
image: java
network_mode:设置网络模式
network_mode: "bridge"
network_mode: "host"
network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"
ports:对外暴露的端口定义,和 expose 对应
ports:   # 暴露端口信息  - "宿主机端口:容器暴露端口"
"8763:8763"
"8763:8763"
links:将指定容器连接到当前连接,可以设置别名,避免ip方式导致的容器重启动态改变的无法连接情况
links:    # 指定服务名称:别名 
    - docker-compose-eureka-server:compose-eureka
volumes:卷挂载路径
volumes:
  - /lib
  - /var
logs:日志输出信息

--no-color          单色输出,不显示其他颜.
-f, --follow        跟踪日志输出,就是可以实时查看日志
-t, --timestamps    显示时间戳
--tail              从日志的结尾显示,--tail=200
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值