I’m trying to build a Dockerized Django application with a MySQl database, but am unable to connect to the database when running docker-compose up
My Dockerfile
is:
# Use the official Python image as the base image
FROM python:3.10
# Set environment variables
ENV PYTHONUNBUFFERED 1
# Set the working directory inside the container
WORKDIR /app
# Copy the requirements file and install dependencies
COPY requirements.txt /app/
RUN pip install -r requirements.txt
CMD ["sh", "-c", "python manage.py migrate"]
# Copy the project files into the container
COPY . /app/
And docker-compose.yml
looks like:
version: '3'
services:
db:
image: mysql:8
ports:
- "3306:3306"
environment:
- MYSQL_DATABASE='model_db'
- MYSQL_USER='root'
- MYSQL_PASSWORD='password'
- MYSQL_ROOT_PASSWORD='password'
volumes:
- /tmp/app/mysqld:/var/run/mysqld
- ./db:/var/lib/mysql
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/app
ports:
- "8000:8000"
depends_on:
- db
env_file:
- .env
I’m using a .env
file to define environment variables, and it is:
MYSQL_DATABASE=model_db
MYSQL_USER=root
MYSQL_PASSWORD=password
MYSQL_ROOT_PASSWORD=password
MYSQL_HOST=db
These are then loaded to the app settings.py
like this:
BASE_DIR = Path(__file__).resolve().parent.parent
env = environ.Env()
if READ_DOT_ENV_FILE := env.bool("DJANGO_READ_DOT_ENV_FILE", default=True):
# OS environment variables take precedence over variables from .env
env.read_env(env_file=os.path.join(BASE_DIR, '.env'))
MYSQL_DATABASE = env('MYSQL_DATABASE', default=None)
MYSQL_USER = env('MYSQL_USER', default=None)
MYSQL_PASSWORD = env('MYSQL_PASSWORD', default=None)
MYSQL_ROOT_PASSWORD = env('MYSQL_ROOT_PASSWORD',default=None)
MYSQL_HOST = env('MYSQL_HOST', default=None)
# Database
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'MYSQL_DATABASE': MYSQL_DATABASE,
'USER': MYSQL_USER, # Not used with sqlite3.
'PASSWORD': MYSQL_PASSWORD, # Not used with sqlite3.
'MYSQL_ROOT_PASSWORD': MYSQL_ROOT_PASSWORD,
'HOST': MYSQL_HOST,
'PORT': 3306,
},
}
When I run docker-compose up
it errors out with _mysql_connector.MySQLInterfaceError: Can't connect to MySQL server on 'db:3306' (99)
Any suggestions?
2
Answers
I've fixed the issues(s), which were several.
The host was wrong. Following several comments, I changed
"MYSQL_HOST=localhost"
to"MYSQL_HOST=db"
, i.e. the container name.The
web
container was starting before the database server was ready, causing the connection error, becausedepends_on
will only wait for a container to be up, not actually fully initialised. Instituting a health_check, following this and this solved the issue.python3 manage.py migrate
would not work unless I created aDATABASE_URL
variable, following this, whereDATABASE_URL == mysql://<username>:<password>@<host>:<port>/<db_name>
(see here)The final working
Dockerfile
,docker-compose.yml
,settings.py
and.env
files were:Dockerfile
.env
settings.py
docker-compose.yml
There some steps i think you should do:
CMD
in your Dockerfile. Just do this in your command directive in your docker-compose:Other things seems right.
Hope it helps !