docker-compose.yaml
services:
db:
image: mysql:9.0.1
container_name: db_mysql_container
environment:
MYSQL_DATABASE: backend
MYSQL_USER: asdf
MYSQL_PASSWORD: asdf
MYSQL_ROOT_PASSWORD: asdf
ports:
- '3307:3306'
api:
build: .
container_name: django_container
command: bash -c "pip install -q -r requirements.txt &&
python manage.py migrate &&
python manage.py runserver 0.0.0.0:8000"
volumes:
- .:/app
ports:
- '8000:8000'
depends_on:
- db
django settings
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': "backend",
'USER': "asdf",
'PASSWORD': "asdf",
'HOST': "db",
'PORT': "3307",
}
}
The rest of my django settings file is what the default is. The whole django project is just what you start out with from the django-admin startproject
command, plus the mysqlclient dependency.
Here is my Dockerfile, nothing special going on:
# Use an official Python runtime as a parent image
FROM python:3.12
# Set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# Set the working directory
WORKDIR /app
# Install dependencies
COPY requirements.txt /app/
# Copy the project code into the container
COPY . /app/
requirements.txt:
asgiref==3.8.1
Django==5.1
mysqlclient==2.2.4
sqlparse==0.5.1
When I bring up the db, wait, and then bring up the api, I get this:
django.db.utils.OperationalError: (2002, "Can't connect to server on 'db' (115)")
If I change my docker-compose.yaml to this:
services:
db:
image: mysql:9.0.1
container_name: db_mysql_container
environment:
MYSQL_DATABASE: backend
MYSQL_USER: asdf
MYSQL_PASSWORD: asdf
MYSQL_ROOT_PASSWORD: asdf
MYSQL_TCP_PORT: 3307
ports:
- '3307:3307'
api:
build: .
container_name: django_container
command: bash -c "pip install -q -r requirements.txt &&
python manage.py migrate &&
python manage.py runserver 0.0.0.0:8000"
volumes:
- .:/app
ports:
- '8000:8000'
depends_on:
- db
it works. It seems like I should be able to run mysql in the container on port 3306 and then have docker send traffic sent to my host 3307 port to the container's 3306 port.
Your containers communicate directly to each other over the docker internal network on their "inside" ports. When you do a port exposure like "outside:inside" the outside port is only relevant to traffic targeting the host system. Your containers do not use the host ports to talk to each other.
That's why the 3707:3707
mapping works when the application is configured to connect using port 3707
-- because the inside port is using port 3707
.
In the first example with 3707:3706
, you would need to configure the application to connect on port 3706, since that's the inside port.