docker-compose解决容器依赖问题
背景
做了个简单的程序,需要依赖mysql、redis、nginx等组件。
后续可能需要发布到其他地方做一下简单的展示,一想到要在一台新电脑上装jdk、mysql这些杂七杂八的环境就头疼,于是想试试docker来打包。
因为仅是展示,数据不太重要,所以打算用docker-compose来启动包括数据库在内的环境并且进行服务编排。
问题
项目需要依赖mysql,一开始以为在docker-compose.yml
中配置depends_on
属性就可以了,毕竟字面意思就是依赖于其他容器。但是编写完后启动项目报错,连接不上数据库。
经过一番测试才发现depends_on
属性,只是让mysql比程序先启动,而非等mysql完全启动好了再启动程序。
虽然mysql先启动了,但因为初始化比较慢,程序启动较快,就出现了程序启动好而mysql还没启动完成的尴尬场面,所以程序连不上数据库。
解决方案
问题既然是因为程序比mysql先启动,那就让程序停下来等待mysql启动完成再执行就好啦,找了一下发现了个脚本,可以用来解决这个问题。
Github:wait-for-it
这个脚本会循环检测指定的主机端口是否准备完成,所以只需要在启动程序前去不断检测mysql的状态即可。
脚本用法:
wait-for-it.sh host:port [-s] [-t timeout] [-- command args]
-h HOST | --host=HOST Host or IP under test
-p PORT | --port=PORT TCP port under test
Alternatively, you specify the host and port as host:port
-s | --strict Only execute subcommand if the test succeeds
-q | --quiet Don't output any status messages
-t TIMEOUT | --timeout=TIMEOUT
Timeout in seconds, zero for no timeout
-- COMMAND ARGS Execute command with args after the test finishes
将脚本放到Dockerfile同目录下,Dockerfile改为如下:
# 从JDK8启动容器
FROM java:8
# 设置工作目录
WORKDIR /usr/local/server/java
# 复制jar包到容器内
COPY *.jar /usr/local/server/java/app.jar
COPY wait-for-it.sh /usr/local/server/java/wait-for-it.sh
EXPOSE 8080 9090
CMD mkdir html
RUN chmod +x /usr/local/server/java/wait-for-it.sh
ENTRYPOINT ["/usr/local/server/java/wait-for-it.sh", "mysql:3306", "--", "java", "-jar", "/usr/local/server/java/app.jar"]
由于docker-compose会帮我们生成一个网络,所以直接用mysql:3306即可连接到mysql。
最后的docker-compose.yml文件放一下:
version: "3.9"
services:
java:
build: .
image: java:0.1
ports:
- 8080:8080
depends_on:
- mysql
- redis
mysql:
image: mysql:5.7
restart: always
ports:
- 3306:3306
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_DATABASE: java
volumes:
- ./sql-init/:/docker-entrypoint-initdb.d/
redis:
image: redis:6.2.5
restart: always
ports:
- 6379:6379
nginx:
image: nginx:1.21.1
restart: always
ports:
- 80:80
volumes:
- ./html:/usr/share/nginx/html
还没有评论,来说两句吧...