docker-compose可以方便组合多个 docker 容器服务, 但是, 当容器服务之间存在依赖关系时, docker-compose 并不能保证服务的启动顺序。docker-compose 中的 depends_on 配置是容器的启动顺序, 并不是容器中服务的启动顺序。本章将详细叙述如何解决 docker-compose 顺序启动微服务的问题。
1.用restart:always机制
docker-compose.yml
version:"3"
services:
# 指定服务名称
#服务注册与发现中心
simonEureka:
image: simon/eureka-server:2.0.1-SNAPSHOT
hostname: simonEureka
ports:
- "8100:8100"
#配置中心
simonConfig:
image: simon/config-server:2.0.1-SNAPSHOT
hostname: simonConfig
ports:
- "8101:8101"
depends_on:
- simonEureka
restart: always
#路由网关
apigateway:
image: simon/apigateway:2.0.1-SNAPSHOT
ports:
- "8102:8102"
depends_on:
- simonEureka
- simonConfig
restart: always
#监控平台
admin:
image: simon/admin:2.0.1-SNAPSHOT
ports:
- "8103:8103"
depends_on:
- simonEureka
- simonConfig
restart: always
2.用shell脚本阻止当前服务启动,直到所需依赖的服务全部启动之后再启动当前服务。
部署的微服务如下图所示
(1)shell脚本 :entrypoint.sh (镜像中必须安装netcat要么通过maven配置要么在dockefile安装netcat)
#!/bin/bash
: ${SLEEP_SECOND:=2}
wait_for() {
echo Waiting for $1 to listen on $2...
while ! nc -z $1 $2; do echo waiting...; sleep $SLEEP_SECOND; done
}
declare DEPENDSdeclare CMD
while getopts "d:c:" argdo
case $arg in
d)
DEPENDS=$OPTARG
;;
c)
CMD=$OPTARG
;;
?)
echo "unkonw argument"
exit 1
;;
esacdone
for var in ${DEPENDS//,/}do
host=${var%:*}
port=${var#*:}
wait_for $host $portdone
eval $CMD#避免执行完命令之后退出容器
tail -f /dev/null
这个脚本有2 个参数:
-d: 需要等待的服务和端口,例如:simonEureka:8080
-c: 等待的服务和端口启动之后, 自己的启动命令,例如:java -jar eureka.jar
(2)编写docker-compose.yml
version: '2'
services:
pig-eureka:
build:
context: ./
dockerfile: Dockerfile-eureka
restart: always
ports:
- 1025:1025
pig-config:
links:
- pig-eureka:eureka
build:
context: ./
dockerfile: Dockerfile-config
restart: always
ports:
- 4001:4001
volumes:
- ./entrypoint.sh:/entrypoint.sh
environment:
SLEEP_SECOND: 4
tty: true
entrypoint: /entrypoint.sh -d pig-eureka:1025 -c 'java -jar /app/pig-config.jar';
pig-auth:
links:
- pig-config:config
build:
context: ./
dockerfile: Dockerfile-auth
restart: always
ports:
- 3000:3000
volumes:
- ./entrypoint.sh:/entrypoint.sh
environment:
SLEEP_SECOND: 25
tty: true
entrypoint: /entrypoint.sh -d pig-config:4001 -c 'java -jar /app/pig-auth.jar';
pig-gateway:
links:
- pig-eureka:eureka
- pig-auth:auth
build:
context: ./
dockerfile: Dockerfile-gateway
restart: always
ports:
- 9999:9999
volumes:
- ./entrypoint.sh:/entrypoint.sh
environment:
SLEEP_SECOND: 26
tty: true
entrypoint: /entrypoint.sh -d pig-auth:3000 -c 'java -jar /app/pig-gateway.jar';
(3)编写每个jar包的Dockerfile文件
Dockerfile-eureka:
FROM java:8-jre
ADD ./jar/pig-eureka.jar /app/
CMD ["java", "-Xmx200m", "-jar", "/app/pig-eureka.jar"]
EXPOSE 1025
Dockerfile-config(其他的类似):
FROM java:8-jre
ADD ./netcat.tar.gz /opt/ #netcat的压缩包必须放在同级目录下
ENV NETCAT_HOME /opt/netcat
ENV PATH $PATH:$NETCAT_HOME/bin #在容器里安装netcat命令
ADD ./jar/pig-config.jar /app/
CMD ["java", "-Xmx200m", "-jar", "/app/pig-config.jar"]
EXPOSE 4001
netcat放在同级目录下
(4)启动服务
$ docker-compose up
其他程序都在等待eureka启动这样就实现了顺序启动的功能
注意问题:
1. Shell脚本权限问题(不能执行shell脚本):
docker: Error response from daemon: OCI runtime create failed: container_linux.go:348: starting container process caused "exec: \"docker-entrypoint.sh\": executable file not found in $PATH": unknown.
解决方法(添加权限)
chmod +x docker-entrypoint.sh
2. Shell脚本报错"start.sh /bin/bash^M: 坏的解释器:没有那个文件或目录”,因为 .sh文件是从windows拷贝过来的,所以多了\r
解决办法
sed -i 's/\r$//' start.sh
3. 出现网关不能no host to root
先关闭防火墙看是否能解决
4. 关闭防火墙后会出现NO chain需要重启docker
网友评论