简体   繁体   中英

Delay starting a Docker service until MongoDB is running without modification of Dockerfile

There are two services in my docker-compose.yml . A mail service which uses MailHog and a MongoDB for storage.

The problem is that the MongoDB service needs to be up and running before MailHog. Otherwise, MailHog will do a fallback and use its in-memory storage.

A simple depends_on is not sufficient because the MongoDB service takes some time to start.

I'm aware of scripts like wait-for-it etc. but they all require modifying the Dockerfile where in my case I'm using the unmodified Docker image of MailHog.

Is there any "built-in" mechanism or workaround how I can delay the mail service until MongoDB is ready?

mail:
  image: mailhog/mailhog:v1.0.0
  deploy:
    restart_policy:
      condition: on-failure
      delay: 10s
      max_attempts: 3
      window: 60s

mail-db:
  image: mongo:4.2.6
  environment:
    MONGO_INITDB_DATABASE: mailhog
    MONGO_INITDB_ROOT_USERNAME: root
    MONGO_INITDB_ROOT_PASSWORD: root
  ports:
    - 27017
  deploy:
    restart_policy:
      condition: on-failure
    resources:
      limits:
        cpus: "0.5"
        memory: 500M

One way is to supply your own entrypoint script, which you can add to the container with volumes . In the script, wait for a successful connection to MongoDB and then exec the original entrypoint.

Stack:

volumes:
  - /path/to/entrypoint.sh:/tmp/entrypoint.sh
entrypoint: /bin/bash
command: /tmp/entrypoint.sh

entrypoint.sh:

# Wait for service or whatever
exec /path/to/original/entrypoint

No, there are not. However, there is no need to modify the original Dockerfile. You can extend it with jwilder/dockerize , a tool developed for this specific purpose (amongst others).

FROM mailhog/mailhog:v1.0.0

# If required, you can change MONGOURL via docker -e [...]
ENV MONGOURL mail-db:27017

# The dockerize version used. You can set a different version with
# docker build --build-arg DOCKERIZE_VERSION=[...]
ARG DOCKERIZE_VERSION=v0.6.1

# Change to root to be able to install dockerize
USER root

# 1: Ensure the image is up to date, while we are at it
RUN apk update && apk upgrade \
# 2: Install curl and its dependencies as the virtual package ".deps"
&& apk add --virtual .deps curl \
# 3: Get dockerize
&& curl -L -O https://github.com/jwilder/dockerize/releases/download/${DOCKERIZE_VERSION}/dockerize-linux-amd64-${DOCKERIZE_VERSION}.tar.gz \
# 4: Unpack it and put it to the appropriate location as per FHS
&& tar -C /usr/local/bin -xzvf dockerize-linux-amd64-${DOCKERIZE_VERSION}.tar.gz \
# 5: Remove the tarball
&& rm dockerize-linux-amd64-${DOCKERIZE_VERSION}.tar.gz \
# 6: Cleanup
&& rm -rf /var/cache/apk/* \
# 7: Remove the virtual package ".deps"
&& apk del .deps

# Switch back to the user mailhog is supposed to run under
USER mailhog

# Run dockerize, which will start mailhog as soon as it was able to connect to $MONGOURL
ENTRYPOINT ["/bin/sh","-c","/usr/local/bin/dockerize -wait tcp://$MONGOURL MailHog"]

Note: the syntax highlighting does not work properly on the Dockerfile, for whatever reason

Tested with the following docker-compose.yaml (the deploy parts are obviously ignored by docker-compose):

version: "3"
services:
  mail:
    image: robertstauch/mailhog:v1.0.0-dockerized-v0.6.1
    build: .
    ports:
      - "8025:8025"
      - "1025:1025"
    deploy:
      restart_policy:
        condition: on-failure
        delay: 10s
        max_attempts: 3
        window: 60s

  mail-db:
    image: mongo:4.2.6
    environment:
      MONGO_INITDB_DATABASE: mailhog
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: root
    deploy:
      restart_policy:
        condition: on-failure
      resources:
        limits:
          cpus: "0.5"
          memory: 500M

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM