如何在docker-compose文件中使用wait-for-it?

25

我需要先克隆wait-for-it代码库并编辑wait-for-it.sh文件吗?

https://github.com/vishnubob/wait-for-it/blob/master/wait-for-it.sh

我想在客服连接并启动服务器后的5秒内使我的主文件开始运行。(或每当客服连接服务器正常工作时)。

我知道在Dockerfile中,我们需要添加这些命令(将文件复制到工作目录,并将shell脚本作为可执行文件运行)。

...
COPY wait-for-it.sh . 
RUN chmod +x /wait-for-it.sh
...

这是我的当前 Docker-Compose 文件

version: '3'
services:
  books:
    build: './books'
    container_name: "horus-books"
    ports:
      - "30043:30043"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"

  customers:
    depends_on:
      - books
    build: './customers'
    container_name: "horus-customers"
    ports:
      - "6000:6000"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"

  main:
    depends_on: 
      - customers
    build: './main'
    container_name: "horus-main"
    ports:
      - "4555:4555"
    command: ["./wait-for-it.sh", "customers:6000", "--", "node", "main.js"]
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
    

主要服务Dockerfile

FROM node:12.14.0
WORKDIR /usr/src/app
COPY package*.json ./
COPY . /usr/src/app
COPY wait-for-it.sh . 
RUN chmod +x /wait-for-it.sh
RUN npm install
EXPOSE 4555
CMD ["node", "main.js"]

你想要在构建容器时等待还是在运行容器时等待? - tadman
@tadman 我想要等待客户端服务器运行时(也就是容器正在运行时)。 - TheRoadLessTaken
1
RUN 命令在构建阶段只执行一次,不会影响运行中的容器。您需要更改 CMDENTRYPOINT - tadman
1个回答

23

通常情况下,你不应该把这个脚本放在你的docker-compose.yml文件中。这个脚本需要构建到镜像中,并且启动容器时需要运行标准的启动序列。

有一个相当普遍的模式,使用入口脚本进行一些初始设置,然后使用exec "$@"来作为主进程运行容器命令。这使你可以使用wait-for-it.sh脚本等待后端就绪,然后运行任何主命令。例如,一个 docker-entrypoint.sh 脚本可能如下所示:

#!/bin/sh

# Abort on any error (including if wait-for-it fails).
set -e

# Wait for the backend to be up, if we know where it is.
if [ -n "$CUSTOMERS_HOST" ]; then
  /usr/src/app/wait-for-it.sh "$CUSTOMERS_HOST:${CUSTOMERS_PORT:-6000}"
fi

# Run the main container command.
exec "$@"

你需要确保这个脚本是可执行的,并将它设为图像的ENTRYPOINT,但除此之外,你可以基本保持Dockerfile不变。

FROM node:12.14.0
WORKDIR /usr/src/app
COPY package*.json ./
# Do this _before_ copying the entire application in
# to avoid repeating it on rebuild
RUN npm install
# Includes wait-for-it.sh and docker-entrypoint.sh
COPY . ./
RUN chmod +x ./wait-for-it.sh ./docker-entrypoint.sh
EXPOSE 4555
# Add this line
# It _must_ use the JSON-array syntax
ENTRYPOINT ["./docker-entrypoint.sh"]
CMD ["node", "main.js"]

在你的docker-compose.yml文件中,你需要添加配置来指定后端在哪里,但不需要覆盖command:

main:
  depends_on: 
    - customers
  build: './main'
  ports:
    - "4555:4555"
  environment:
    - CUSTOMERS_HOST=customers

这太棒了,谢谢David!有几个问题:对于CUSTOMERS_PORT,我需要创建它还是将其添加到docker-compose的“环境”字典中并将其等于正确的端口?此外,您提供了wait-for-it脚本的示例,但我想知道./docker-entrypoint.sh脚本会是什么样子(抱歉,我以前从未使用过shell脚本!) - TheRoadLessTaken
1
第一个脚本是入口点。Bourne shell结构${CUSTOMERS_PORT:-6000}使用$CUSTOMERS_PORT的值,如果它在环境中设置了,则使用该值,否则使用6000,因此您不需要手动设置它。 - David Maze
“# 运行主容器命令”是什么意思?在我的情况下,我有一个.jar文件,我想在等待另一个服务之后执行它。它位于容器内的/app.jar路径下。 - nonNumericalFloat
没关系,我刚刚在 docker-entrypoint.sh 中执行了 exec java -jar ./app.jar,完全没有问题! - nonNumericalFloat
在您的Dockerfile中,您应该设置CMD java -jar ./app.jar,这将是exec "$@"行运行时的“主容器命令”。 - David Maze

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接