2

I'm trying run django with mysql in docker containers:

version: '2'
services:

  db:
    image: mysql:latest
    volumes:
      - ./db:/var/lib/mysql
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: mypassword
      MYSQL_USER: root
      MYSQL_PASSWORD: mypassword
      MYSQL_DATABASE: django
    expose:
      - "3306"

  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    depends_on:
     - db

but after docker-compose up --build I got error:

django.db.utils.OperationalError: (2005, "Unknown MySQL server host 'db' (-2)")

Most likely, the container with mysql did not have time to start. But I did specify depends_on: - db in theweb

Who understands what might be the matter?

Narnik Gamarnik
  • 1,049
  • 1
  • 16
  • 35

4 Answers4

4

According to the official docker-compose documentation, depends_on means that this service depends on another one and it cannot run without it, but this doesn't mean the other service is ready to process requests.

So, when you launch your deployment, docker-compose assures that when launching you web service, db is running too (if you try to kill the db container, you'll notice in the docker compose logs that web gets killed too). Since MySQL image needs some time to boot up the first time, this results in the database not being instantly able to process queries.

To solve this problem, docker-compose has a keyword, restart, that specify your container behaviour when something goes wrong and your process dies (such as not having the db ready to process requests).

To wrap up, your docker-compose.yaml file should be:

version: '2'
services:

  db:
    image: mysql:latest
    volumes:
      - ./db:/var/lib/mysql
    restart: always
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: mypassword
      MYSQL_USER: root
      MYSQL_PASSWORD: mypassword
      MYSQL_DATABASE: django
    expose:
      - "3306"

  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/code
    restart: always
    ports:
      - "8000:8000"
    depends_on:
     - db

You can find more about the restart keyword in the official documentation

Polpetta
  • 495
  • 1
  • 3
  • 13
  • Thnaks for you reply, but `restart: always` don't resolve my issue. – Narnik Gamarnik Aug 26 '18 at 10:39
  • Is the mysql version a constraint? Can you try again with `mysql:5.7` instead (clean your `./db` folder before that you do that or you'll end up having unexpected behaviour)? Remember that it takes some time for the database to initialize (it really depends on the hardware you're running). Usually, you should wait 20-30 seconds before mysql becomes available. – Polpetta Aug 26 '18 at 10:53
1

depends_on in docker-compose means that a service depends on another and it cannot run without it, but this doesn't mean the other service is ready and listening for requests.

What I like to do is add a wait-for-it in my command to the container needing another service to be up and ready to process request.

In your case involving the db and web, after dropping in the wait-for-it.sh in my code dir, I'd modify the command to the web container to:

./wait-for-it.sh -t 300 db:3306 && python manage.py runserver 0.0.0.0:8000

This will simply tell web to wait on the availability of host db on port 3306 thus synchronizing the spin-up of the two interdependent services

k.wahome
  • 962
  • 5
  • 14
1

In my case (downgrading) I had some dangling named volumes declared in the volumes section of the Compose file and anonymous volumes attached to containers. Executing

docker-compose down -v

resolved the issue. Beware that this actually removes named volumes declared in the volumes.

Dharman
  • 30,962
  • 25
  • 85
  • 135
user42488
  • 1,140
  • 14
  • 26
-1

In my case I did not have the VPN connection ready to reach the external network. I was not aware that the "Network Settings" under Linux switch the VPN connection to off after every computer restart.

And then I got this similar error:

$docker-compose up
Recreating MYCONTAINER ... done
Attaching to MYCONTAINER
MYDOCKERCOMPOSESERVICE_1  | 2022-01-14 10:56:30,045 [INFO]: Connecting to DB ...
MYDOCKERCOMPOSESERVICE_1  | Traceback (most recent call last):
MYDOCKERCOMPOSESERVICE_1  |   File "/usr/lib/python3.9/runpy.py", line 197, in _run_module_as_main
MYDOCKERCOMPOSESERVICE_1  |     return _run_code(code, main_globals, None,
MYDOCKERCOMPOSESERVICE_1  |   File "/usr/lib/python3.9/runpy.py", line 87, in _run_code
MYDOCKERCOMPOSESERVICE_1  |     exec(code, run_globals)
MYDOCKERCOMPOSESERVICE_1  |   File "/MYDOCKERCOMPOSESERVICE/main.py", line 265, in <module>
MYDOCKERCOMPOSESERVICE_1  |     main()
MYDOCKERCOMPOSESERVICE_1  |   File "/MYDOCKERCOMPOSESERVICE/main.py", line 244, in main
MYDOCKERCOMPOSESERVICE_1  |     MYSERVER_conn = create_connection(MYSERVER_CONNECTION)
MYDOCKERCOMPOSESERVICE_1  |   File "/MYDOCKERCOMPOSESERVICE/main.py", line 65, in create_connection
MYDOCKERCOMPOSESERVICE_1  |     conn = MySQLdb.connect(cursorclass=cursors.DictCursor, charset="utf8",
MYDOCKERCOMPOSESERVICE_1  |   File "/usr/local/lib/python3.9/dist-packages/MySQLdb/__init__.py", line 123, in Connect
MYDOCKERCOMPOSESERVICE_1  |     return Connection(*args, **kwargs)
MYDOCKERCOMPOSESERVICE_1  |   File "/usr/local/lib/python3.9/dist-packages/MySQLdb/connections.py", line 185, in __init__
MYDOCKERCOMPOSESERVICE_1  |     super().__init__(*args, **kwargs2)
MYDOCKERCOMPOSESERVICE_1  | MySQLdb._exceptions.OperationalError: (2005, "Unknown MySQL server host 'MYSERVER' (-3)")
MYDOCKERCOMPOSESERVICE_1  | (2005, "Unknown MySQL server host 'MYSERVER' (-3)")
MYCONTAINER exited with code 1

Here -3, in the question -2, I guess these are just positions in the arguments of the connection object. In my case, a connection with the db was impossible, I tested it in the bash of the container again, using mysql on the command line.

Solution: Just switch VPN on again, then the connection can be created:

enter image description here

If the above does not help, you might also check whether your port 3306 is already in use by another container (docker ps -a). If so, try ports: -"3307:3306" or another port as well. This is just a step that I also made before it ran through, though I do not think that it is related to the error in question. I still cannot say for sure whether this might not have solved something as well.

questionto42
  • 7,175
  • 4
  • 57
  • 90