- 部署Java后端服务
这里使用的JDK17镜像为:azul/zulu-openjdk:17
mkdir -p /usr/app
usr/app> vi Dockerfile
Dockerfile内容:
FROM azul/zulu-openjdk:17 #基础镜像
EXPOSE 9090 #指定服务端口
ENV LANG C.UTF-8 #设置环境变量LANG指定系统默认的语言和字符编码
ENV LOG_HOME /app/logs #设置环境变量用于存放日志
ADD webapp.jar app.jar #将文件添加到容器中
HEALTHCHECK --interval=600s --timeout=60s CMD curl --fail --silent http://localhost:9090 || exit 1 #检查容器是否正常运行,interval两次健康检查的间隔时间,timeout每一次检查的超时时间,后面的CMD是检查时执行的指令,--silent(-s)失败时不打印任何信息
ENTRYPOINT ["java","-jar","-Duser.timezone=Asia/Shanghai","/app.jar"] #服务启动执行的命令,ENTRYPOINT 执行docker run时命令不可覆盖但可以在后面追加参数
编辑环境变量文件
vi webapp.env
变量名=变量值
这里涉及到访问其它容器时ip地址用网络别名(即docker run 时配置的–network-alias )
例:system.mysql.master.url=jdbc:mysql://mysql.net:3306/galaxy-pro?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
这里的mysql.net即是mysql容器在网桥中的别名
构建镜像
docker build -f Dockerfile -t webapp .
创建network实现多容器间相互访问具体可参考《docker的安装和简单操作命令》中的容器之间相互访问相关描述
这里定义创建好的network为:chevysky-bridge
启动容器
docker run --privileged=true --name webapp --network chevysky-bridge --network-alias webapp.net \
--env-file webapp.env -v /usr/app/logs:/app/logs -d -p 9080:9090/tcp webapp
--privileged=true #容器能获得更多的操作权限
--name webapp #定义容器名为webapp
--network chevysky-bridge #指定容器加入的network为chevysky-bridge
--network-alias webapp.net #定义在网络中的别名为webapp.net
--env-file webapp.env #指定所使用的环境变量文件
-v /usr/app/logs:/app/logs #将容器中的日志/app/logs(这个日志的位置取决于实际情况)映射到宿主机上/usr/app/logs
-d #表示后台运行
-p 9080:9090/tcp #宿主机的9080端口被映射到容器9090
webapp #最后的webapp是前面创建好的镜像名
这里插入一个java maven多模块项目打包时遇到的问题:
运行时发现缺少主类:no main manifest attribute
#在对应的模块包的pom文件中加入代码
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>3.2.4</version>
<configuration>
<mainClass>com.xxx.xxx.MainApplication</mainClass>
</configuration>
</plugin>
</plugins>
</build>
继续执行打包命令:mvn clean package -Dmaven.test.skip=true
这里检查没有主类的存在可以使用:
java -jar app.jar
或执行:jar xvf app.jar 解压并查看META-INF中的MANIFEST.MF文件中的Main-Class属性和Start-Class属性
检查后发现依然没有主类的存在,排查了:
1.springboot和spring-boot-maven-plugin版本兼容
2.mainClass路径文件名正确
3.是否有在父pon中声明 <pluginManagement> 有则需要在子pom覆盖
4.检查是否有多个spring-boot-maven-plugin的声明导致冲突。
#最终发现问题出现在父pom中声明了spring-boot-maven-plugin,由于前期的开发调试在pom中设置了<skip>true</skip>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
#导致在执行maven命令时任何由spring-boot-maven-plugin定义的目标都会被跳过,打包执行的jar或war为不可用文件,修改为fasle或去掉即可。
容器部署成功查看服务是否正常启动
docker logs --tail 500 webapp
docker logs -f webapp
后续二次发布步骤
- 上传jar包,可以使用相关的远程终端工具如:XTerminal 也可以使用命令:
scp local/path/app.jar root@x.x.x.x :/usr/app/app.jar- 停止容器:docker stop webapp
- 拷贝jar到容器:docker cp /usr/app/webapp.jar webapp:/app.jar
- 启动容器:docker start webapp
- 部署Vue前端服务
打包vue项目:npm run build
将打包的dist文件上传到服务器
Docker查询镜像:docker search nginx
Docker拉取Nginx的镜像:docker pull nginx
docker run --name nginx-galaxy --network galaxy-bridge --network-alias nginx.galaxy.net \
-v /usr/app/nginx.conf:/etc/nginx/conf.d/default.conf -v /usr/app/dist/:/usr/local/nginx/html/ -p 80:80 -p 443:443 -d nginx
定义容器名:–name nginx-galaxy
定义网桥需要与java服务通信:–network galaxy-bridge --network-alias nginx.galaxy.net
nginx配置文件:-v /usr/app/nginx.conf:/etc/nginx/conf.d/default.conf
打包的前端文件映射:-v /usr/app/dist/:/usr/local/nginx/html/
启动容器后注意在云服务器上开放监听的端口80 和 443
通过 -v映射的文件都可以通过 cp 命令将终端文件拷贝到容器中;所以后续再次部署时只需要停止容器,拷贝dist到容器:
docker cp /usr/app/dist nginx-galaxy:/usr/share/nginx/html/
然后重启即可
配置Nginx注意事项:
不了解怎么配置时可以先启动一个nginx容器:docker run --name nginx-temp -d nginx
然后进入容器:docker exec -it nginx-temp /bin/sh
cd到配置文件位置:/etc/nginx/conf.d/default.conf
查看配置文件:cat default.conf
Nginx配置示例:
server {
#监听IPv4地址上的端口
listen 80;
listen 443 ssl; #监听https
#监听IPv6地址上的端口
listen [::]:80;
listen [::]:443 ssl;
#证书地址,docker run时需要-v映射到容器对应的以下位置
ssl_certificate /usr/local/nginx/conf/cert.pem;
ssl_certificate_key /usr/local/nginx/conf/cert.key;
server_name chevysky.cn;
#root指定请求根目录这里-v映射vue打包后的dist文件
#index指定一组索引文件,这里映射之后指定的就是dist下的index.html
#try_files用于指定一系列文件路劲或URL
location / {
root /usr/local/nginx/html;
index index.html index.html;
try_files $uri $uri/ /index.html;
}
location /api/ {
proxy_pass http://webapp.net:9090/;
}
#websocket代理
location /galaxy/stomp/ {
proxy_pass http://webapp:9090/galaxy/stomp/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
SSL证书(这里使用的是阿里云提供的数字证书服务)
在阿里云控制台搜索 SSL 或 数字证书服务
使用个人测试证书