上次用 docker-compose
搭建了软件工程的项目后,这次就直接搭建计量的项目了,记录搭建过程中遇到问题。
后台
mysql
和 redis
搭建方法不变,之前 spring-boot 是在容器内编译打包的,感觉这样太费时了也不安全。所以这次直接用 jdk8 的镜像运行打包后的 jar 包。本以为挺简单的,没想到却遇到了不少问题。
首先项目是微服务搭建的,最后生成的 jar 包有三个。本来我想的是直接把 jar 都复制到容器中,用 jdk 环境直接运行所有 jar 包就好了。开始我是这样写的:
FROM openjdk:8-jre-alpine
WORKDIR /app
COPY api .
ENTRYPOINT ["java", "-jar", "*.jar"]
api 下的文件夹:
目的就是运行这个文件下所有 jar 包,没想到一运行时就出错了。
看样子它是把 *.jar
当作运行 jar 包了。但这不是我本意,我的本意是把 *
当做通配符来使用的。
排查问题,原来我在 dockerfile
中直接使用的 java 命令,而 *
通配符是 bash
才有的功能。修改为:ENTRYPOINT ["sh", "-c", "java", "-jar", "*.jar"]
。
本意为这样万无一失,结果又出岔子了。控制台仅仅打印了gateway
的 jar 包日志。进入容器内部查看,也确实只运行了gateway
的 jar 包。这让我百思不得其解,不知道又是那出错了。我在手动运行 jar 包时突然想到,运行 jar 包时,程序并没有终止,会不会是因为运行第一个 jar 包没有结束,所以轮不到后一个 jar 包运行。
写一个脚本后台运行 jar 包,将脚本复制到容器中运行查看效果:
#!/bin/sh
java -jar /app/gateway/*.jar &
java -jar /app/module1/*.jar &
java -jar /app/resource/*.jar
FROM openjdk:8-jre-alpine
WORKDIR /app
COPY api .
COPY api/command.sh command.sh
RUN \["chmod", "+x", "command.sh"\]
RUN apk add --update bash
CMD \["sh","command.sh"\]
这样一来终于成功了,但是这么写太麻烦了。要是能在 sh 中后台运行所有通配符文件就好了,可惜没找到。
前台
前台使用 nginx
构建,也很简单,基于 nginx 镜像,把打包后的 dist 文件复制到容器中,再把自定义的 nginx.conf
复制到容器中,启动 nginx 就行了。
FROM nginx:alpine
RUN rm -rf /usr/share/nginx/html/\*
COPY nginx.conf /etc/nginx/nginx.conf
COPY dist /usr/share/nginx/html
EXPOSE 80
CMD \["nginx", "-g", "daemon off;"\]
user root;
worker_processes 1;
events {worker_connections 1024;}
http {
server {
listen 80;
include /etc/nginx/mime.types;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location /resource/ {
proxy_set_header terminal-type "web";
proxy_pass http://app-server:8084/;
........
}
........
这里需要注意的是要把转发的后台地址改为 docker-compose.yml
中的后台服务名。nginx 转发基于后台,所以在 docker-compose.yml 中也要声明前台服务基于后台depends_on:- app-server
。
数据共享
docker 容器中通过网络和数据卷实现容器的交互。比如在后台中保存的文件储存在后台服务容器中,这时候前台服务容器的 nginx 是获取不到数据的。这时候只能通过数据卷来实现数据共享。
比如后台存储的资源文件路径在 /resources 中,前台需要获取的资源文件在 /app/resources,这时候就可以 通过挂载数据卷来实现数据的 共享。
# docker-compose.yml
volumes:
resources:
app-server:
........
volumes:
-resources:/resources
app-web:
.........
volumes:
- resources:/app/resources
先声明数据卷,之后分别挂载到容器对应路径即可。