0

I'm building a FastAPI app with MySQL, SQLAlchemy, Gunicorn and Docker. I keep getting the Error 111 Connection refused when I FIRST TIME run docker-compose build and docker-compose up in the service app container.

Following the previous instructions on SO I have

  1. Corrected the host in the connection string to be the same as the service name (mysql)
  2. Set my variables under environment in docker-compose.yml

It worked BUT the catch is only after I run my app container for the SECOND TIME ONWARD.

For some unknown reason I always got Error 111 on the first time running docker-compose up

Below is my docker-compose.yml

version: '3.8'
services:
  mysql:
      image: mysql:8.0
      restart: always
      environment:
        MYSQL_ROOT_PASSWORD: password
        MYSQL_PASSWORD: password
        MYSQL_DATABASE: database
  app:
    image: first-production-image
    build: 
      context: ${APP_HOME}
      dockerfile: Dockerfile
      target: dev
      args:
        - APP_HOME=${APP_HOME}
    environment:
      - PORT=8000
      - DB_CONN=${DB_CONN}
    volumes:
      - mysql_volume:/var/lib/mysql
    ports:
      - "80:8000"
    depends_on:
      - mysql
volumes:
  mysql_volume:

My .env file containing the connection string:

APP_HOME=/backend/app
DB_CONN="mysql+pymysql://root:password@mysql:3306/database"

and where I make the connection to the database with SQLAlchemy:

from sqlalchemy import create_engine

SQLALCHEMY_DATABASE_URL = os.getenv("DB_CONN")
engine = create_engine(SQLALCHEMY_DATABASE_URL)
models.Base.metadata.create_all(bind=engine)

Below is my Dockefile:

FROM python:3.10-slim-bullseye as base

ARG APP_HOME
WORKDIR ${APP_HOME}
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
COPY ./requirements.txt ./
RUN pip install --no-cache-dir --upgrade pip -r ./requirements.txt
COPY . .

FROM base as dev
EXPOSE 8000
CMD exec gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app --bind 0.0.0.0:8000 --preload

FROM base as prod
CMD exec gunicorn --bind :$PORT --workers 4 --worker-class uvicorn.workers.UvicornWorker --threads 8 main:app

I don't understand why I have to restart my app container to get my app running properly. Could you enlighten me on this? Thank you!

William Le
  • 825
  • 1
  • 9
  • 16
  • 1
    Purely a guess based on earlier experience: you assume MySql is functional and ready because you added "depends on" in your APP image definition. Depends on only checks for the container to have started, not for it to be ready and accepting connections. I made this mistake earlier as well. My guess therefore is that MySql is not ready before the app demands it and consequently app errors out. This would explain why your second run is effective, since MySql will then be ready to serve. Try running them manually with a delay and see if it changes. – JustLudo Sep 05 '22 at 08:24
  • 1
    [Docker Compose wait for container X before starting Y](https://stackoverflow.com/questions/31746182/docker-compose-wait-for-container-x-before-starting-y) covers this case more fully. – David Maze Sep 05 '22 at 11:24
  • @DavidMaze thank you your answer is very enlightening – William Le Sep 05 '22 at 14:45

0 Answers0