0%

Docker+Nginx部署总结

期末考试后尝试部署CS209A的SpringBoot+Vue前后端分离项目,踩了很多坑,在此总结一下

地址: https://quanquancho.com

IDEA集成Docker

该内容的视频B站上有很多,再此不过多赘述

需要注意的是,IDEA中拉取镜像使用的不是服务器的镜像源

所以即使服务器上已经更换了国内镜像源,IDEA仍然需要再次配置

.image-20220703152709103

红框内的用户名和密码随便填,没有实际作用

配置完成后,拉取镜像的速度明显变快

Maven打jar包

【踩坑1】如果要读取文件,只能使用流来读取,文件放入resources文件夹中,于是自己封装了两个方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static String readFile(String path){
InputStream is = Util.class.getClassLoader().getResourceAsStream(path);
Assert.notNull(is,"The file "+path+" doesn't exist, check the path");
return readInputStream(is);
}

public static String readInputStream(InputStream is){
int c;
StringBuilder sb = new StringBuilder();
try{
while((c= is.read())!=-1){
sb.append((char)c);
}
}catch (IOException e){
e.printStackTrace();
}
return sb.toString();
}
  • 使用JDK11+的Files.readString(Path.of("xxx"))会报FileNotFoundException
  • 使用JDK11+的Files.readString(Path.of(xxx.class.getClassLoader().getResource(path).toURI()))会报FileSystemNotFoundException

以上报错的原因是jar包中的文件系统是独立于操作系统的,需要用更底层的流来读取

Nginx镜像配置https

参考

最终的nginx.conf文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

worker_processes 1;

events {
worker_connections 1024;
}

http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;

# HTTPS server
server {
listen 443 ssl;
server_name quanquancho.com www.quanquancho.com;

# 以nginx根目录为相对路径
ssl_certificate cert/7998226_quanquancho.com.pem;
ssl_certificate_key cert/7998226_quanquancho.com.key;

ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;

ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;

location / {
root /etc/nginx/html;
index index.html index.htm;
}
}

server {
listen 80;
server_name quanquancho.com www.quanquancho.com;
return 301 https://$host$request_uri; #将所有HTTP请求通过rewrite指令重定向到HTTPS
}
}

【踩坑2】使用浏览器调试前端时一定要清空缓存,不然显示的可能是旧页面!

启动后发现前端没有问题,但是后端API的请求会有mixed-content报错

.image-20220705170938675

原因是后端SpringBoot没有升级成https,详细信息参考 https://segmentfault.com/a/1190000040044540

SpringBoot配置https

参考 https://help.aliyun.com/document_detail/365559.html

镜像运行后SpringBoot报错

1
2
3
4
5
6
7
Failed to start bean 'webServerStartStop'; 
nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat server
Caused by: org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat server
Caused by: java.lang.IllegalArgumentException: standardService.connector.startFailed
Caused by: org.apache.catalina.LifecycleException: Protocol handler start failed
Caused by: java.lang.IllegalArgumentException: Alias name [tomcat] does not identify a key entry
Caused by: java.io.IOException: Alias name [tomcat] does not identify a key entry

很明显是因为别名错误,需要找到证书真正的别名,参考 https://blog.csdn.net/wallimn/article/details/84923137

1
2
3
4
5
6
7
8
9
$ keytool -list -keystore xxx.pfx
输入密钥库口令: #这里即为password文件中的密码
密钥库类型: PKCS12
密钥库提供方: SUN

您的密钥库包含 1 个条目

alias, 2022年7月6日, PrivateKeyEntry, #别名即为alias
证书指纹 (SHA-256): xxxxxxxxxxxxxxxxxxxxxxx

修改application.yml重新部署,成功

Docker-Compose

该内容的教程网上也有很多,这里列出一些注意点

  1. 我的IDEA中集成docker-compose有bug,docker-compose up后会一直要我输入密码,所以我直接把文件拖到服务器上用命令行执行了

  2. 如果需要使用多个Dockerfile文件,可以使用以下排布方式

    1
    2
    3
    4
    5
    6
    7
    8
    docker
    ├──.env
    ├──docker-compose.yml
    ├──java
    │ ├──backend-0.0.1-SNAPSHOT.jar
    │ └──Dockerfile
    └──nginx
    └──Dockerfile

    然后docker-compose.yml中采用如下引用方式即可

    1
    2
    3
    4
    5
    6
    7
    8
    version: '3'
    services:
    nginx:
    ...
    build: ./nginx
    backend:
    ...
    build: ./java

    参考 https://qastack.cn/programming/27409761/docker-multiple-dockerfiles-in-project

  3. .env文件可以修改生成的network的名称,本质是定义环境变量

    1
    COMPOSE_PROJECT_NAME=java2-project

    参考 https://blog.csdn.net/wwqcherry/article/details/122118896

  4. docker-compose up之前就要把nginx.conf配置好,否则会构建失败

  5. docker-compose up --build会重新构建镜像

    不加--build即使Dockerfile改变,也不会重新构建,导致错误发生

  6. docker-compose up -d在后台运行服务

    不加-d会前台运行,把输出打印在控制台方便调试

最终的docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
version: '3'
services:
nginx:
image: nginx:latest
container_name: java2-project-nginx
ports:
- "80:80"
- "443:443"
volumes:
- /root/nginx/html:/etc/nginx/html
- /root/nginx/nginx.conf:/etc/nginx/nginx.conf
- /root/nginx/cert:/etc/nginx/cert
privileged: true #必须要有,打开nginx文件调用权限
backend:
image: java2-project-backend
container_name: java2-project-backend
build: ./java
ports:
- "8443:8443"

./javaDockerfile

1
2
3
4
5
6
FROM openjdk:17
EXPOSE 8443
ADD backend-0.0.1-SNAPSHOT.jar app.jar
#通过修改软连接的方式,修改时区为东八区,从而使日志时间正确
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
ENTRYPOINT ["java","-jar","/app.jar"]

最终构建完成如图

.image-20220703155048405

环境信息

  • SpringBoot 2.6.6

生产环境

  • CentOS 7.6
  • Docker 20.10.17
  • Docker-Compose 1.26.2

开发环境

  • Windows 10
  • IntelliJ IDEA Ultimate 2021.2.4