I just started learning docker and lightsail and I am writing a dashboard app on Dash that allows user to make calls to the Interactive Brokers gateway (IB Gateway) container, to get the latest positions, trade history etc.

Description My dash app will contain a simple button that calls a script (ib_app.py) that connects to IB, get some data and store it locally in the dash app. The reason this is called externally is because the Flask framework didn't allow a connection to IB within a dash app itself, and I run into problem if I do that.

subprocess.check_output('python ib_app.py', shell=True)

Problems

  1. I would like to clarify if my way of connecting the two containers are correct.
  2. I have some trouble adding cronjob to call a specific button in the dash app. And I am not sure where should I actually place my cronjob.

In the ib_app.py, I will connect to IB using ib_insync:

IB().connect(host = "host.docker.internal", port = "4001", 5) #5 for clientId

I run my app like this:

app.run_server(host = "0.0.0.0", port = 8050)

After that I dockerize my app and push to dockerhub. I then have a docker compose file that pulls both containerized services from docker on AWS Lightsail:

version: "3.4"

services:
  dashboard:
    image: dashboard:latest
    ports:
      - "8050:8050"
    expose:
      - "8050/tcp"
    extra_hosts:
      - "host.docker.internal:host-gateway"

  ib-gateway:
    image: ghcr.io/unusualalpha/ib-gateway:latest
    restart: always
    environment:
      TWS_USERID: ${TWS_USERID}
      TWS_PASSWORD: ${TWS_PASSWORD}
      TRADING_MODE: ${TRADING_MODE}
      READ_ONLY_API: ${READ_ONLY_API}
     
    ports:
      - "127.0.0.1:4001:4001"
      - "127.0.0.1:4002:4002"
      - "127.0.0.1:5900:5900"

Q1: Is this the right and secure way to approach it? e.g. what potentially could go wrong with this and if the use of host.docker.internal is correct here?

Q2: My second question is, now I would like to add a cronjob (or more in the future) to click that button that runs ib_app.py so the dashboard is updated without needing user to click it everyday, and later I can build some notification systems as well.

How do I actually add this cronjob into the dockerfile? I've tried a few lines I found and it didn't quite work. In the future if more cronjobs are added, how should they be added?

My dockerfile looks something like this:

FROM --platform=linux/amd64 python:3.10.3

RUN apt-get update && apt-get -y install cron vim
WORKDIR /dashboard
COPY requirements.txt .
COPY . .
COPY cron_gettrades /etc/cron.d/cron_gettrades
RUN pip install -r requirements.txt

# give execution rights to cron & sh file
RUN chmod 0644 /etc/cron.d/cron_gettrades 
RUN chmod +x start.sh
# apply cron job
RUN /usr/bin/crontab /etc/cron.d/cron_gettrades

EXPOSE 8050

CMD ["python", "main.py"]

Do let me know if more details are required, I'll happily provide. Also, if you know some resources that could help me understand these topics better, please feel free to recommend them to me too. Thank you!

1

There are 1 best solutions below

0
On

Firstly, I have a Docker Compose file that's quite similar to yours.

Regarding your first question: What about using an environment variable? In my case, it's TBOT_IBKR_IPADDR. Here's my version of the Dockerfile

version: "3.4"

services:
  ib-gateway:
    restart: always
    container_name: tbot-on-tradingboat
    build:
      context: ./stable
    environment:
      TWS_USERID: ${TWS_USERID}
      TWS_PASSWORD: ${TWS_PASSWORD}
      TRADING_MODE: ${TRADING_MODE:-paper}
      READ_ONLY_API: ${READ_ONLY_API:-}
      TVWB_HTTPS_PORT: ${TVWB_HTTPS_PORT:-5000}
     
      TBOT_IBKR_PORT: ${TBOT_IBKR_PORT:-4001}
      TBOT_IBKR_CLIENTID: ${TBOT_IBKR_CLIENTID:-1}
      TBOT_IBKR_IPADDR: ${TBOT_IBKR_IPADDR:-127.0.0.1}
    ports:
      - "127.0.0.1:4001:4001"
      - "127.0.0.1:4002:4002"
      - "127.0.0.1:5900:5900"
      - "127.0.0.1:5000:5000"
    depends_on:
      - redis
      - ngrok

  redis:
    image: redis:7.0.10-alpine
    restart: always
    container_name: redis-on-tradingboat

  ngrok:
    image: wernight/ngrok:latest
    restart: always
    container_name: ngrok-on-tradingboat
    ports:
      - "4040:4040"
    environment:
      NGROK_AUTH: ${NGROK_AUTH:-}
      NGROK_PORT: ${NGROK_PORT:-}

Regarding your second question: If you're aiming to daemonize your program, consider invoking a bash script at the end of your Dockerfile, rather than directly updating the crontab. I've taken a similar strategy in my own Dockerfile

# Start run script
CMD ["/home/tbot/tbot_run.sh"]