How to do it...

The basic structure already created separates aspects of our project into logical groups:

  • All applications to be used in the project are stored under the apps directory, which allows them to be pulled in individually either from version control or other source locations.
  • project and templates are also distinct, which makes sense since the settings and templates for one project switch be shared, whereas applications are commonly intended to be reusable.
  • The static and media files are separated as well, allowing them to be deployed to separate static content containers (and servers) easily.

To make full use of these features, let's update the docker-compose.yml file with some enhancements:

# docker-compose.yml
version: '3'
services:
proxy:
image: 'jwilder/nginx-proxy:latest'
ports:
- '80:80'
volumes:
- '/var/run/docker.sock:/tmp/docker.sock:ro'
db:
image: 'mysql:5.7'
ports:
- '3306'
volumes:
- './config/my.cnf:/etc/mysql/conf.d/my.cnf'
- './mysql:/var/lib/mysql'
- './data:/usr/local/share/data'
environment:
- 'MYSQL_ROOT_PASSWORD'
- 'MYSQL_USER'
- 'MYSQL_PASSWORD'
- 'MYSQL_DATABASE'
app:
build: .
command: python3 manage.py runserver 0.0.0.0:8000
volumes:
- './project:/usr/src/app/myproject'
- './media:/usr/src/app/media'
- './static:/usr/src/app/static'
- './templates:/usr/src/app/templates'
- './apps/external:/usr/src/app/external'
- './apps/myapp1:/usr/src/app/myapp1'
- './apps/myapp2:/usr/src/app/myapp2'
ports:
- '8000'
links:
- db
environment:
- 'SITE_HOST'
- 'MEDIA_HOST'
- 'STATIC_HOST'
- 'VIRTUAL_HOST=${SITE_HOST}'
- 'VIRTUAL_PORT=8000'
- 'MYSQL_HOST=db'
- 'MYSQL_USER'
- 'MYSQL_PASSWORD'
- 'MYSQL_DATABASE'
media:
image: 'httpd:latest'
volumes:
- './media:/usr/local/apache2/htdocs'
ports:
- '80'
environment:
- 'VIRTUAL_HOST=${MEDIA_HOST}'
static:
image: 'httpd:latest'
volumes:
- './static:/usr/local/apache2/htdocs'
ports:
- '80'
environment:
- 'VIRTUAL_HOST=${STATIC_HOST}'

With these changes, there are some corresponding updates needed in the Django project settings as well. The end result should look similar to the following:

# project/settings.py
# ...

ALLOWED_HOSTS = []
if os.environ.get('SITE_HOST'):
ALLOWED_HOSTS.append(os.environ.get('SITE_HOST'))

# ...

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}

if os.environ.get('MYSQL_HOST'):
DATABASES['default'] = {
'ENGINE': 'django.db.backends.mysql',
'HOST': os.environ.get('MYSQL_HOST'),
'NAME': os.environ.get('MYSQL_DATABASE'),
'USER': os.environ.get('MYSQL_USER'),
'PASSWORD': os.environ.get('MYSQL_PASSWORD'),
}

# ...

# Logging
# https://docs.djangoproject.com/en/dev/topics/logging/
LOGGING = {
'version': 1,
'formatters': {
'verbose': {
'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
},
'simple': {
'format': '%(levelname)s %(message)s'
},
},
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'simple'
},
'file': {
'level': 'DEBUG',
'class': 'logging.FileHandler',
'filename': '/var/log/app.log',
'formatter': 'simple'
},
},
'loggers': {
'django': {
'handlers': ['file'],
'level': 'DEBUG',
'propagate': True,
},
}
}

if DEBUG:
# make all loggers use the console.
for logger in LOGGING['loggers']:
LOGGING['loggers'][logger]['handlers'] = ['console']

# ...

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.1/howto/static-files/

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
if os.environ.get('STATIC_HOST'):
STATIC_DOMAIN = os.environ.get('STATIC_HOST')
STATIC_URL = 'http://%s/' % STATIC_DOMAIN

MEDIA_URL = '/media/'

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
if os.environ.get('MEDIA_HOST'):
MEDIA_DOMAIN = os.environ.get('MEDIA_HOST')
MEDIA_URL = 'http://%s/' % MEDIA_DOMAIN

Furthermore, the my.cnf file is referenced in docker-compose.yml as a volume attached to the db service. Although there would be no error, specifically, if it were left out; a directory would be automatically created to satisfy the volume requirement. At a minimum, we can add an empty file under the config folder, or we might add options to MySQL right away, such as the following:

# config/my.cnf
[mysqld]
sql_mode=STRICT_TRANS_TABLES

Then, add a bin subdirectory in myproject_docker, inside of which we will add a dev script (or dev.sh, if the extension is preferred):

#!/usr/bin/env bash
# bin/dev
# environment variables to be defined externally for security
# - MYSQL_USER
# - MYSQL_PASSWORD
# - MYSQL_ROOT_PASSWORD
DOMAIN=myproject.local

DJANGO_USE_DEBUG=1
DJANGO_USE_DEBUG_TOOLBAR=1
SITE_HOST="$DOMAIN"
MEDIA_HOST="media.$DOMAIN"
STATIC_HOST="static.$DOMAIN"
MYSQL_HOST="localhost"
MYSQL_DATABASE="myproject_db"
docker-compose $*

Make sure the script is executable by modifying the permissions, as in the following:

myproject_docker/$ chmod +x bin/dev

Finally, the development hosts need to be mapped to a local IP address, such as via /etc/hosts on macOS or Linux. Such a mapping for our project would look something like this:

127.0.0.1    myproject.local media.myproject.local static.myproject.local
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.237.123