pythondockerflask

Whats the best approach to execute a bash script inside a Docker Container?


My problem is...

I have a Flask API inside a Docker container, the purpose of this project is to scrapp my schools' system, and get all the class schedules in order to generate all the possible combinations of schedules for a student. Everything runs just fine. However, I have an endpoint that serves for the purpose of scrapping my schools' webpage (I have to do it manually and it's VITAL in order to run the other functions that consume that information).

My questions is:

I created a bash script that sends a GET request to that endpoint that I mentioned previously:

#!/bin/bash

URL="http://localhost:5555/FetchGroupDataUPSite"
max_retries=3
retries=0
delay=5

echo "Sending GET request to scrapper endpoint..."

while [ $retries -lt $max_retries ]
do
  response=$(curl -s -o /dev/null -w "%{http_code}" -X GET $URL)
  if [ $response -eq 200 ]
  then
    echo "Scrapper script completed."
    break
  else
    echo "Request failed with status code $response. Retrying in $delay seconds..."
    retries=$((retries+1))
    sleep $delay
  fi
done

if [ $retries -eq $max_retries ]
then
  echo "Maximum number of retries reached. Scrapper script failed."
fi

Is it possible to run that bash script every time I build the docker container after all the services started?

I'm also open to hear suggestions to different approaches to solve this problem (My approach could be completely wrong)

Here is my docker-compose and Dockerfile files in case it's necessary:

docker-compose.yml:

version: '3.8'
networks:
  app-tier:
    driver: bridge
services:
  db:
    image: mysql:5.7
    container_name: UP_DB
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: ***
      MYSQL_PASSWORD: ***
      MYSQL_DATABASE: ***
      MYSQL_USER: ***
    command: --default-authentication-plugin=mysql_native_password --bind-address=0.0.0.0 --explicit_defaults_for_timestamp
    volumes:
      - ./sql:/docker-entrypoint-initdb.d
    ports:
      - 3306:3306
    networks:
      - app-tier
  adminer:
    image: adminer
    container_name: UP_Adminer
    restart: always
    ports:
      - 8080:8080
    networks:
      - app-tier
  api:
    container_name: UP_API
    stdin_open: true
    tty: true
    restart: always
    build: .
    ports:
      - 5555:5555
    volumes:
      - ./App:/SmartUP/App
    networks:
      - app-tier


Dockerfile

FROM python:3.10.7-buster
WORKDIR /SmartUP
COPY . .
ENV FLASK_ENV development
ENV DEBUG true
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN apt-get install -y wget
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
RUN sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list'
RUN apt-get -y update
RUN apt-get install -y google-chrome-stable
RUN apt-get install -yqq unzip
RUN wget -O /tmp/chromedriver.zip http://chromedriver.storage.googleapis.com/`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE`/chromedriver_linux64.zip
# Unzip the Chrome Driver into /usr/local/bin directory
RUN unzip /tmp/chromedriver.zip chromedriver -d /usr/local/bin/
# Set display port as an environment variable
ENV DISPLAY=:99

RUN pip install --upgrade pip && pip3 install -r requirements.txt
CMD ["python", "App/run.py"]

# Makes the file executable
EXPOSE 5555

Thank you in advance for taking the time to answer my question 😁.


Solution

  • Just run the script as required. You don't need to do anything Docker-specific for it. If you're running it on the same host as the containers, then when it curl http://localhost:5555/..., it will reach the container via its published ports:.

    If you want this to be triggered every time you restart the container stack, then you could package this into a script

    #!/bin/sh
    docker-compose up --build -d
    ./trigger-scraper
    

    The script already contains a retry loop. Even if you run the script before the container stack is fully functional, you'll go into that retry loop and it might work the second or third time as things start up. (You may need to wait longer than 15 seconds for the database container to be fully usable.)