docker-compose解决容器依赖问题
in 默认分类 with 0 comment 25 views

docker-compose解决容器依赖问题

in 默认分类 with 0 comment 25 views

背景

做了个简单的程序,需要依赖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
Responses