传统的Vue项目部署:
对应的配置文件为
server {
listen 80;
server_name localhost;
charset utf-8;
access_log /var/log/nginx/host.access.log main;
absolute_redirect off;
location /{
proxy_pass http://localhost:8080;
}
location /manage {
alias /unisign-manage-control;
index index.html index.htm;
}
}
在单web应用的场景中缺失已经能够满足我们的需求。
上面部署的一定问题:
有两种方案:
起一个SpringBoot项目,将webpack打包好的vue项目作为静态资源放到resources/static
目录中,然后将该项目注册到eureka注册中心,通过在网关上配置指定的路由访问该服务即可。
这种做法实际上也就是使用到tomcat的静态资源代理服务,然后在增加上服务发现,实现起来比较简单
Spring Cloud的Sidecar方案提供对非JVM的微服务提供注册发现和服务治理的功能。
通过上面的方式就可以不用每次更新前端项目之后,重新编译整个jar包,并且对于前端的开发人员来说部署方式和原来一直,只是nginx不在负责代理后端服务,前端项目需要稍作该做增加一个静态资源用于健康检查,这样由于sidecar部分提供了服务的注册功能,这样网关服务就可以服务发现前端的项目并做代理。
Demo源码: github . https://github.com/Trisia/static-resource/tree/master/dist
示例静态html文件 index.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hellotitle>
head>
<body>
<h1>This is Main pageh1>
body>
html>
除了静态文件之外为了支持健康检查,还需要返还一个jsonhealth.json
{
"status": "UP"
}
Demo源码: github . https://github.com/Trisia/static-proxy
pom.xml 引入依赖
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
配置application.yaml
文件
spring:
application:
name: static-proxy
resources:
static-locations: file:${PROXY_PATH:/www/html}
server:
port: 777
eureka:
instance:
prefer-ip-address: true
instance-id: ${spring.cloud.client.ip-address}:${server.port}
client:
service-url:
defaultZone: ${REGISTER_SERVER_URL:http://172.22.203.11:8761/eureka/}
上面配置重点关注spring.resources.static-locations
这个就是制定外部静态资源的位置,此处使用了一个环境变量PROXY_PATH
如果系统中没有设置该环境变量,那么将使用/www/html
作为静态资源的目录。该目录下的所有文件将会被映射到/**
路径下。此处使用环境变量是为容器化做准备。
注意:在windows环境中开发时,
/www/html
中的/
是项目所处磁盘的根目录,如果项目在D盘的某个文件夹中,那/www/html
就是D:\www\html
。
我们将准备过程中的文件放置到/www/html
目录下,启动项目,访问接口就可以获取页面。
可以在微服务的网关中加入下面配置
zuul:
routes:
static-proxy: /ui/**
通过微服务中的网关服务加上这个服务的名称也能够访问到这个页面
由于这个代理服务的功能:提供静态资源代理服务的注册和发现、代理静态资源。
对于代理服务来说变动较少可以作为基础镜像,然后在前端项目中使用基础镜像构建
首先在项目根目录创建docker目录,然后编写Dockerfile
FROM openjdk:8-jre
RUN mkdir -p /www/html && \
echo "OK" > /www/html/index.html
ADD target/static-proxy-1.0.0-SNAPSHOT.jar /app.jar
ENTRYPOINT ["java", "-jar", "-Duser.timezone=GMT+8", "/app.jar"]
到项目根目录构建基础镜像
docker build -f docker/Dockerfile -t static-proxy:1.0.0-SNAPSHOT .
运行测试基础镜像
docker run -it -p 777:777 static-proxy:1.0.0-SNAPSHOT
static-proxy:1.0.0-SNAPSHOT
基础镜像功能 符合预期
我们在我们静态文件的目录下创建一个Dockerfile
这里还是使用准备阶段生成的那个静态页面来模拟vue项目webpack最终打包完成的结果
Demo 源码: github . https://github.com/Trisia/static-resource
Dockerfile 需要使用到上一步构建的基础镜像
FROM static-proxy:1.0.0-SNAPSHOT
ENV PROXY_PATH=/www/html REGISTER_SERVER_URL=http://172.22.203.11:8761/eureka/
COPY dist/* /www/html/
设置一些必要的环境变量,然后复制静态文件,启动指令将会从基础镜像中继承得到。
构建镜像
docker build -f docker/Dockerfile -t static-proxy:1.0.0-SNAPSHOT .
运行项目
docker run -it -p 777:777 app:v1
测试结果如下
符合预期,你还可以从通过网关服务的代理进行访问,结果也是一样的。
Demo代码: github
结合操作系统安装 nginx Nginx instal http://nginx.org/en/linux_packages.html
然后 nginx的代理配置为frontend.conf
,放置于/etc/nginx/conf.d/
目录下
server {
listen 7776;
server_name localhost;
location / {
root /home/static-resource;
index index.html index.htm;
}
}
重新启动nginx
systemctl restart nginx
# 或
service nginx restart
新建一个springboot项目
版本说明:
pom.xml 引入依赖
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-netflix-sidecarartifactId>
dependency>
eureka-client
是用于注册发现的,sidecar
是sidecar的代理。
在启动类上增加上@EnableSidecar
@EnableSidecar
@SpringBootApplication
public class StaticSidecarApplication {
public static void main(String[] args) {
SpringApplication.run(StaticSidecarApplication.class, args);
}
}
配置 resources/application.yaml
server:
port: 7777
spring:
application:
name: static-sidecar
eureka:
client:
service-url:
defaultZone: http://172.22.203.11:8761/eureka
sidecar:
port: 7776 # 本地的 nginx 服务端口
health-uri: http://localhost:7776/health.json # 健康检查
Eureka 注册中心需要自己准备哦。
除了上面springboot和springcloud的常规配置之外,主要是sidecar
的配置
health.json
,所需要手动指明健康检查的路径。启动sidecar服务,就可以完成对本地7776端口的代理并且能够从注册中心中发现该服务。
sidecar就是一个zuul,我们从启动的日志打印和
spring-cloud-netflix-sidecar
都可以看出来。
好了现在可以通过网关加上服务名称,访问到我们静态index.html页面。
网关服务需要自己准备。
我们可以在网关部分对该服务做个映射
zuul:
routes:
STATIC-SIDECAR: /ui/**
分析:
静态资源的镜像制作分为:
修改后的的yaml 为
server:
port: 7777
spring:
application:
name: static-sidecar
eureka:
instance:
prefer-ip-address: true
instance-id: ${spring.cloud.client.ip-address}:${server.port}
client:
service-url:
defaultZone: ${REGISTER_SERVER_URL:http://172.22.203.11:8761/eureka/}
sidecar:
port: 7776 # 本地的 nginx 服务端口
health-uri: http://localhost:7776/health.json # 健康检查
使用IP和端口注册服务。
在sidecar项目的目录创建一个docker文件夹,用于存放构建docker所需要的相关文件。
首先放入之前提到的index.html
和health.json
到test-resource目录下
然后是 nginx的文件代理如下 default.conf
server {
listen 7776;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
然后是Dockerfile
FROM nginx:1.17.3-alpine
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories && \
apk add openjdk8-jre-base && \
rm -rf /var/cache/apk/*
COPY docker/test-resource/* /usr/share/nginx/html/
COPY docker/default.conf /etc/nginx/conf.d/default.conf
ADD target/static-sidecar-1.0.0-SNAPSHOT.jar /app.jar
ENTRYPOINT sh -c 'nginx && java -jar /app.jar'
首先选择一个nginx镜像作为基础镜像,然后安装jre运行环境,接下来将测试代理用的静态文件复制到nginx代理的默认位置,然后使用自定义的代理配置覆盖默认配置文件。
接下来加入sidecar文件。
使用后台运行nginx并启动sidecar jar包。这样项目就启动起来了。
容器其中尽可能不要启动两个进程,因为容器的模型的推荐使用单进程,如果要多进程如上述场景推荐还是使用 supervisor,此处为了简单使用
&&
一同运行。
如何构建镜像
切换目录到sidecar项目的根目录,然后运行docker build命令构建镜像
docker build -f docker/Dockerfile -t static-sidecar:1.0.0-SNAPSHOT .
测试,以主机网络模式运行并映射端口
docker run -it -p 7777:7777 --network host static-sidecar:1.0.0-SNAPSHOT
项目启动后通过网关我们可以得到相同的结果
这样基础镜像就已经制作完成
制作镜像的过程也就是把类似于vue项目中webpack打包出来的dist复制到指定位置然后运行就可以。(把Dockfile放置于vue项目根目录)
注意一定要在项目中放置一个返还值为
{"statue":"UP"}
的json静态文件并可以访问,他将会用于健康检查,否则项目运行可能会报错,检查不通过。
FROM static-sidecar:1.0.0-SNAPSHOT
COPY dist/* /usr/share/nginx/html/
ENTRYPOINT sh -c 'nginx && java -jar /app.jar'
在vue项目根目录运行构建
docker build -t your_app_name:version .
your_app_name:version
替换为应用名称和版本
和上一步一样可以打完包之后测试一下。
[1]. doc . spring clould netifix . https://cloud.spring.io/spring-cloud-netflix/multi/multi__polyglot_support_with_sidecar.html
[2]. docker(11):alpinelinux安装openjre . freewebsys . csdn . https://blog.csdn.net/freewebsys/article/details/53744348
[3]. Run multiple services in a container . docker . doc . https://docs.docker.com/config/containers/multi-service_container/
[4]. Spring Boot静态资源访问和配置全解析小 .洋人最happy . csdn . https://blog.csdn.net/u010358168/article/details/81205116
[5]. Docker running nginx plus jar. stackoverflow . answered objectuser . https://stackoverflow.com/questions/30270779/docker-running-nginx-plus-jar
[6]. How do I use Spring Boot to serve static content located in Dropbox folder?. Dave Syer . stackoverflow