When it comes to setting up the database for your django app, there are quite a number of options. For starters, you need to choose which database you are going to use. Django comes with sqlite3 by default. For some very small to mid scale applications sqlite3 might just do it. So, i tried to integrate sqlite3 with docker first. But, sqlite3 isnt a real database, is it ? :3 So yeah, i could not find a decent way to do that. Thats why (and many other reasons) i leave out sqlite3 when im thinking deployment. My preferred options are either mysql or postgresql. In this tutorial, i will demonstrate setting up both of them.
The second option you would have to consider is between choosing a database service (like aws RDS) or deploying the database on your own. Now there are some pros and cons to each option. If you want someone to take care of most things (like configuring, maintaining, and securing) for you, just go with RDS. On the other hand, if you want more control and flexibility, you can just setup your database inside, say an EC2 Instance. If you want to go with RDS, setting up RDS is really easy. Just Check This Out In this tutorial though, i wanted to explore something different. Hence, i would show you how to setup the database on your own and ofcourse dockerize stuff to make things nicer as always 0:)
Updating Django App Dockerfile
Basically we need to install some dependencies in our debian container.
For,
- Postgres: postgresql
- MySql: default-libmysqlclient-dev So, we need to update this line in our Django App Dockerfile like so:
RUN apt-get install -y --no-install-recommends gcc libc-dev python3-dev [ default-libmysqlclient-dev or postgresql ]
So our Dockerfile looks sth like:
FROM python:3.8-slim-buster
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
ENV PATH="/scripts:${PATH}"
RUN pip install --upgrade pip
COPY ./requirements.txt /requirements.txt
# packages required for setting up WSGI
RUN apt-get update
RUN apt-get install -y --no-install-recommends gcc libc-dev python3-dev default-libmysqlclient-dev
RUN pip install -r /requirements.txt
RUN mkdir /app
COPY ./src /app
WORKDIR /app
COPY ./scripts /scripts
RUN chmod +x /scripts/*
# folder to serve media files by nginx
RUN mkdir -p /vol/web/media
# folder to serve static files by nginx
RUN mkdir -p /vol/web/static
# always good to run our source code with a different user other than root user
RUN useradd user
RUN chown -R user:user /vol
# chmod 755 means full access to owner and read-access to everyone else
RUN chmod -R 755 /vol/web
RUN chown -R user:user /app
RUN chmod -R 755 /app
# switch to our user
USER user
CMD ["entrypoint.sh"]
Updating docker-compose
Now, we need to create a new service for our db in our docker-compose. Like we did for our static data, we need to also persist our database beyond the life of our container. Therefore, we need to use a volume for our db as well. Lets call it, production_db_volume. We need to choose the docker image for our service as well. In this tutorial, i chose one thats relatively newer but also has a long term support.
You can find the available options here:
So, our docker-compose becomes sth like:
version: '3.7'
services:
db:
image: mysql:5.7
ports:
- "3306:3306"
restart: always
volumes:
- production_db_volume:/var/lib/mysql
env_file:
- .live.env
# or
# db:
# image: postgres:12.5
# ports:
# - "5432:5432"
# restart: always
# volumes:
# - production_db_volume:/var/lib/postgresql/data/
# env_file:
# - .live.env
app:
build:
context: .
ports:
- "8000:8000"
volumes:
- production_static_data:/vol/web
restart: always
env_file:
- .live.env
depends_on:
- db
proxy:
build:
context: ./proxy
volumes:
- production_static_data:/vol/static
restart: always
ports:
- "80:80"
depends_on:
- app
volumes:
production_static_data:
production_db_volume:
Notice, we have mentioned the .live.env file for our db
service. Our db containers need some environment variables initiate properly, we would provide them inside our .live.env.
MySql Environment Variables
MYSQL_DATABASE=blah_blah_bleh
MYSQL_ROOT_PASSWORD=blah_blah_bleh
MYSQL_USER=blah_blah_bleh
MYSQL_PASSWORD=blah_blah_bleh
Postgres Environment Variables
POSTGRES_USER=blah_blah_bleh
POSTGRES_PASSWORD=blah_blah_bleh
POSTGRES_DB=blah_blah_bleh
Notice, we are re-using the same .live.env file we used for our 'app' service. It is because we will need the 'db' environment variables in our django app settings.py as well.
Updating settings.py
# for mysql
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': os.environ.get("MYSQL_DATABASE"),
'USER': os.environ.get("MYSQL_USER"),
'PASSWORD': os.environ.get("MYSQL_PASSWORD"),
'HOST': 'db', # docker-compose service name 'db' resolves to host name 'db'
'PORT': 3306
}
}
# or, for postgres
DATABASES = {
"default": {
"ENGINE": 'django.db.backends.postgresql',
"NAME": os.environ.get("POSTGRES_DB"),
"USER": os.environ.get("POSTGRES_USER"),
"PASSWORD": os.environ.get("POSTGRES_PASSWORD"),
"HOST": 'db',
"PORT": 5432,
}
}
you get the idea !!
Finally, we need to update our django app requirements.txt.
Updating requirements.txt
# for postgres
psycopg2-binary==2.8.5
or
# for mysql
mysqlclient==1.4.6
django-mysql==3.8.1
Now, bringing down the existing containers and their volume:
docker-compose down -v
and just executing a docker-compose up -d --build
should setup your db container, run the migrations (since, we have put the *manage.py migrate command in our docker entrypoint in our earlier tutorial).
And thats it for the database setup, in the next tutorial we will work on securing our deployment with ssl, certbot and other django security checks.
Top comments (0)