Home > Net >  How to run a command in docker-compose after a service run?
How to run a command in docker-compose after a service run?

Time:09-01

I have searched but I couldn't find a solution for my problem. My docker-compose.yml file as below.

#

version: '2.1'

services:

  mongo:
    image: mongo_db
    build: mongo_image
    container_name: my_mongodb
    restart: always
    networks:
      - isolated_network
    ports:
      - "27017"
    environment:
      - MONGO_INITDB_ROOT_USERNAME=root
      - MONGO_INITDB_ROOT_PASSWORD=root_pw
    entrypoint: ["python3", "/tmp/script/get_api_to_mongodb.py", "&"]

networks:
  isolated_network:

So here I use a custom Dockerfile. And my Dockerfile is like below.

FROM mongo:latest
RUN apt-get update -y
RUN apt-get install python3-pip -y
RUN pip3 install requests
RUN pip3 install pymongo
RUN apt-get clean -y
RUN mkdir -p /tmp/script
COPY get_api_to_mongodb.py /tmp/script/get_api_to_mongodb.py
#CMD ["python3","/tmp/script/get_api_to_mongodb.py","&"]

Here I want to create a container which have MongoDB and after create the container I collect a data using an API and send the data to MongoDB. But when I run the python script in that time mongodb is not initialized. So I need to run my script after container is created and right after mongodb initialized. Thanks in advance.

CodePudding user response:

You should run this script as a separate container. It's not "part of the database", like an extension or plugin, but rather an ordinary client process that happens to connect to the database and that you want to run relatively early on. In general, if you're thinking about trying to launch a background process in a container, it's often a better approach to run foreground processes in two separate containers.

This setup means you can use a simpler Dockerfile that starts from an image with Python preinstalled:

FROM python:3.10
RUN pip install requests pymongo
WORKDIR /app
COPY get_api_to_mongodb.py .
CMD ["./get_api_to_mongodb.py"]

Then in your Compose setup, declare this as a second container alongside the first one. Since the script is in its own image, you can use the unmodified mongo image.

version: '2.4'
services:
  mongo:
    image: mongo:latest
    restart: always
    ports:
      - "27017"
    environment:
      - MONGO_INITDB_ROOT_USERNAME=root
      - MONGO_INITDB_ROOT_PASSWORD=root_pw
  loader:
    build: .
    restart: on-failure
    depends_on:
      - mongodb
    # environment:
    #   - MONGO_HOST=mongo
    #   - MONGO_USERNAME=root
    #   - MONGO_PASSWORD=root_pw

Note that the loader will re-run every time you run docker-compose up -d. You also may have to wait for the database to do its initialization before you can run the loader process; see Docker Compose wait for container X before starting Y.

It's likely you have an existing Compose service for your real application

version: '2.4'
services:
  mongo: { ... }
  app:
    build: .
    ...

If that image contains the loader script, then you can docker-compose run it. This launches a new temporary container, using most of the attributes from the Compose service declaration, but you provide an alternate command: and the ports: are ignored.

docker-compose run app ./get_api_to_mongodb.py

One might ideally like a workflow where first the database container starts; then once it's accepting requests, run the loader script as a temporary container; then once that's completed start the main application server. This is mostly beyond Compose's capabilities, though you can probably get close with a combination of extended depends_on: declarations and a healthcheck: for the database.

  • Related