It was inconvenient to use Docker-compose, so I made it.
https://github.com/pistatium/dj_database_waiter
A Python command that just waits for a Database connection to be established.
dj_database_waiter myproject.settings
Just pass the Django configuration module as an argument and it will work. (Strictly stop)
When you launch DB and Django with docker-compose, Docker will wait for the Django side container to launch until the minimum network communication is possible (?), But until initialization such as initial SQL input. Will not wait firmly. It starts without permission and the container ends without permission. Hard Even if you look up the solution with StackOverflow, it is written that you have to wait until it is prepared with a shell script, which is quite painful. I don't want to install the DB Client on Python's Docker just to check communication ...
So it's better to write a script to check communication in Python. However, I thought it would be troublesome to copy the script for each project and pass the connection information separately from Django, so I made it a command and entered it with pip.
At first, I implemented it as a Django command so that it can be called from admin.py, but I noticed that the subcommand startup itself failed before the DB started, and rewrote it as a normal command that cries.
docker-compose.yml
version: '3'
services:
web:
build: .
command: python3 myproject/manage.py runserver 0.0.0.0:8000
volumes:
- .:/src
ports:
- 8000:8000
depends_on:
- db
db:
image: mysql
volumes:
- ./docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
- db-volume:/var/lib/mysql
volumes:
db-volume:
If this kind of docker-compose is up and it doesn't start up at once, install dj_database_waiter at build time.
docker-compose.yml
command: /bin/sh dj_database_waiter myproject.settings && python3 myproject/manage.py runserver 0.0.0.0:8000
If you replace command like this, you will be able to start it once.
dj_database_waiter
wants to use from typing.NamedTuple
, so ** only ** requires Python 3.6.1 or higher. Please understand it.
dj_database_waiter/cmd.py
class DbStatus(NamedTuple):
ok: bool
reason: str = None
def check_status(db_group_name: str) -> DbStatus:
try:
...
except Exception as e: # NOQA
return DbStatus(ok=False, reason=str(e))
return DbStatus(ok=True)
Since there are two arguments, there is almost no need to use NamedTuple, but it can be written in an easy-to-understand manner like this. It's similar to CaseClass in Scala. I also write type information, so if I write it using an IDE like IntelliJ, it will perform crunchy interpolation and error checking, so it is very good for mental health. (By the way, the runtime type is not checked, so even if you enter the wrong type, it will work.)
Recommended Posts