The below example is from Coding With Mosh and I have built it via Docker, Docker-Compose using VS Code and a Linux build PC to create this Docker build environment with full maria DB and nice Adminer db viewer. This project show another way to use Docker to containerize the development of Python scripts and projects. See Coding with Mosh for full example. See Setting up Docker here. My build machine was based on this.

Storefront Django project from Coding With Mosh

This is step 1 of Coding with Mosh Django project. The source code for this is available here on my gitlab.

Build steps

These are the steps that I followed to build this in Docker Compose

Step 1 - Create Ignore Files

This has two files needed to setup both Docker and git to ignore data, cache, and databases. .dockerignore file

data/
__pycache*/
db.sqlite3

.gitignore file

data/
__pycache*/
db.sqlite3

Step 2 - Create src Directory

Simple where the src is going to be compiled also created

mkdir -p mariadb/sql

Added file createdb.sql to this folder to create base users

CREATE USER IF NOT EXISTS myuser@'%' IDENTIFIED BY 'thisismyuserpassword';
CREATE DATABASE IF NOT EXISTS myproject;
GRANT ALL ON myproject.* TO myuser@'%';

So far so good? This is the base idea I will have for every project.

Step 3 - Create requirements.txt

So, in the root storefront dir create a file called requirements.txt
This file will be used by the Dockerfile to load python packages needed to build this project. For the start of this project all I am going to load are django and mysqlclient. There are more;
however, I am just keeping simple for now. The rest require modifying associated elements of django; so, I will add as we get to associated training areas focused on the features.

django 
mysqlclient 

Step 4 - Create Dockerfile

Now, it is time to create the Dockerfile in the base storefront dir this is the basis for all

Added sudo user followed this

FROM python:3.12-slim-bookworm

ARG DOCKER_USER=debian

RUN apt-get update && \
    apt-get -y install sudo python3-dev default-libmysqlclient-dev build-essential pkg-config

RUN adduser --disabled-password \
        --gecos '' ${DOCKER_USER} \
    && adduser ${DOCKER_USER} sudo \
    && echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers 

USER ${DOCKER_USER}

WORKDIR /code

COPY ./requirements.txt ./
RUN sudo pip install --no-cache-dir -r requirements.txt

COPY . /code/

RUN sudo chown -R $DOCKER_USER:$DOCKER_USER /code

Step 5 - Create docker-compose.yml

So this is the last step in the config part of the project once this is done you will have all
that is needed to run this project in docker and start building it from there. Almost done, create docker-compose.yml

services:
  db:
  
    image: mariadb:11.3.2-jammy
    restart: always
    environment:
      - MARIADB_ROOT_PASSWORD=Mysql!sql
      - MARIADB_PORT=3306
    ports:
      - 3307:3306
    volumes:
      - ./data:/var/lib/mysql
      - ./src/mariadb/sql:/docker-entrypoint-initdb.d
    

  adminer:
    image: adminer
    restart: always
    ports:
      - 8888:8080
    depends_on:
      - db

  web:
    build: .
    #Use interacive shell with lines below which prevented the crash of container when bad code was hit...
    stdin_open: true 
    tty: true
    # TODO: Use Entrypoint instead of command? Not sure but I think so... Anyway above lines take care of needs for now...
    #command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - ./src:/code
    ports:
      - "9000:8000"
    environment:
      - DB_NAME=myproject
      - DB_USER=myuser
      - DB_PASSWORD=thisismyuserpassword
      - DB_HOST=db
    depends_on:
      - db

Also note run interactive shell via example here There are other mysql types I have tried too like this

services:
  db:
    # image: 'bitnami/mariadb:11.2-debian-12'
    # restart: always
    # environment:
    #   - MARIADB_ROOT_PASSWORD=Hpy@7400sql
    # ports:
    #   - 3307:3306
    # volumes:
    #   - ./data:/bitnami/mariadb
    #   - ./src/mariadb/sql:/docker-entrypoint-startdb.d
    #.
    #.
    #.

For now, I am using the upper one as it is working well. Then run to build *usb

docker compose run --build web django-admin startproject storefront .

This of coarse would fail because manage.py is not there yet; so, take it down. Last, run docker-compose up -d

docker-compose up -d

Step 6 - Connect to VS code Via Docker and Do Real Work in That Env.

Now, that the env is up you can connect via docker extension in VS Code.
This is called Dev Containers
Oh, and I may have forgot to mention VS Code Remote - SSH and Remote - SSH: Editing Configuration Files. Extentions as well Here is my config stored in ~/.ssh/config folder

Host 192.168.0.46
  HostName 192.168.0.46
  IdentityFile ~/.ssh/id-rsa
  User root

Host 192.168.2.15
  HostName 192.168.2.15
  Port 2222
  IdentityFile ~/.ssh/id-rsa
  User debian

Host builder
  HostName builder
  IdentityFile ~/.ssh/id-rsa
  User debian

Yes, builder is the one I installed docker on and used to do all my builds.

This is the docker container that I connect to. That is the far left option on VS code for example here

Step 7 - Setup database connection. First let's make sure the db is happy. In my case I am connecting to [adminer]http://builder:8888

In there I have confirmed that I have a database called myproject and I have a user call myuser

this goes in settings.py under the storefront dir in the VS Code that is running in docker. This can also be modified via
src/storefront/settings.py in from the builder's VS Code if so desired. Note: it is best to work in Docker VS Code as it has full code completion and knows the python env and all install modules. So, modify there!!!

if os.environ.get('DB_PORT') != None:
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': os.environ.get('DB_NAME'),
            'USER': os.environ.get('DB_USER'),
            'PASSWORD': os.environ.get('DB_PASSWORD'),
            'HOST': os.environ.get('DB_HOST'),    
            'PORT': os.environ.get('DB_PORT'),  
        } 
    }
else: # no port so more than likely docker.
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': os.environ.get('DB_NAME'),
            'USER': os.environ.get('DB_USER'),
            'PASSWORD': os.environ.get('DB_PASSWORD'),
            'HOST': os.environ.get('DB_HOST'),    
        } 
    }

Note: this option provides two database maps based on DB port the better way would be to do an inline one and add DB_PORT when needed This allows the code to run a DB from outside the Docker env if DB_PORT is specified. Most of the time I would think the Docker DB would be used.

Also notice the os.environ.get commands all pull from the env variables defined in the docker compose and also the lack of DB_PORT defined in said compose file:

    environment:
      - DB_NAME=myproject
      - DB_USER=myuser
      - DB_PASSWORD=thisismyuserpassword
      - DB_HOST=db

Oh, and for now mariadb/sql/createdb.sql defines them in there too. TODO: Find out if there is a way to pass ENV_VARIABLES into sql scripts

Leave a Reply

Your email address will not be published. Required fields are marked *