Django for beginners par William Vincent

Thanks to William Vincent !

total 52
drwxrwxr-x. 6 pvergain pvergain 4096 28 mai   16:10 ch10-bootstrap
drwxrwxr-x. 6 pvergain pvergain 4096 28 mai   16:10 ch11-password-change-reset
drwxrwxr-x. 6 pvergain pvergain 4096 28 mai   16:10 ch12-email
drwxrwxr-x. 7 pvergain pvergain 4096 28 mai   16:10 ch13-newspaper-app
drwxrwxr-x. 7 pvergain pvergain 4096 28 mai   16:10 ch14-permissions-and-authorizations
drwxrwxr-x. 7 pvergain pvergain 4096 28 mai   16:10 ch15-comments
drwxrwxr-x. 4 pvergain pvergain   92 28 mai   16:10 ch2-hello-world-app
drwxrwxr-x. 5 pvergain pvergain  103 28 mai   16:10 ch3-pages-app
drwxrwxr-x. 5 pvergain pvergain 4096 28 mai   16:15 ch4-message-board-app
drwxrwxr-x. 7 pvergain pvergain 4096 28 mai   16:10 ch5-blog-app
drwxrwxr-x. 7 pvergain pvergain 4096 28 mai   16:10 ch6-blog-app-with-forms
drwxrwxr-x. 7 pvergain pvergain 4096 28 mai   16:10 ch7-blog-app-with-users
drwxrwxr-x. 4 pvergain pvergain 4096 28 mai   16:10 ch8-custom-user-model
drwxrwxr-x. 5 pvergain pvergain 4096 28 mai   16:10 ch9-user-authentication
-rw-rw-r--. 1 pvergain pvergain  689 28 mai   16:15 Readme.md

tree ch4-message-board-app

tree ch4-message-board-app
ch4-message-board-app/
├── Dockerfile
├── manage.py
├── mb_project
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── Pipfile
├── Pipfile.lock
├── posts
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   │   ├── 0001_initial.py
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── Procfile
└── templates
        └── home.html

Installing django with pipenv and python 3.6

Dockerfile

cat Dockerfile
FROM python:3.6

ENV PYTHONUNBUFFERED 1

COPY . /code/
WORKDIR /code/

RUN pip install pipenv
RUN pipenv install --system

EXPOSE 8000

Pipfile

$ cat Pipfile
[[source]]
url = "https://pypi.python.org/simple"
verify_ssl = true
name = "pypi"

[packages]
gunicorn = "*"
django = "*"
"psycopg2" = "*"

[dev-packages]

[requires]
python_version = "3.6"

docker build –tag gdevops/django36_ch4 .

See also

We can’t run a Docker container until it has an image so let’s do that by building it.

docker build --tag gdevops/django36_ch4 .
Sending build context to Docker daemon  48.82MB
Step 1/7 : FROM python:3.6
3.6: Pulling from library/python
cc1a78bfd46b: Pull complete
6861473222a6: Pull complete
7e0b9c3b5ae0: Pull complete
3ec98735f56f: Pull complete
9b311b87a021: Pull complete
048165938570: Pull complete
1ca3d78efb22: Pull complete
0f6c8999c3b7: Pull complete
5a85410f5000: Pull complete
Digest: sha256:52a2bd143faf6430b182b56a5fdeb70f26b8ca8fbd40210c3ed8a8ee1eaba343
Status: Downloaded newer image for python:3.6
 ---> 29d2f3226daf
Step 2/7 : ENV PYTHONUNBUFFERED 1
 ---> Running in ee1ad676c613
Removing intermediate container ee1ad676c613
 ---> 8fb46520978f
Step 3/7 : COPY . /code/
 ---> 3a6b8395d66b
Step 4/7 : WORKDIR /code/
Removing intermediate container 72885dc811e1
 ---> e0c26850ab99
Step 5/7 : RUN pip install pipenv
 ---> Running in 19666f95212b
Collecting pipenv
  Downloading https://files.pythonhosted.org/packages/8d/fe/4faa519acfb984015dde4e2973d89e47baf6a9cd81e9d58e2f2d3c47fb6f/pipenv-2018.5.18-py3-none-any.whl (6.4MB)
Requirement already satisfied: setuptools>=36.2.1 in /usr/local/lib/python3.6/site-packages (from pipenv) (39.1.0)
Collecting certifi (from pipenv)
  Downloading https://files.pythonhosted.org/packages/7c/e6/92ad559b7192d846975fc916b65f667c7b8c3a32bea7372340bfe9a15fa5/certifi-2018.4.16-py2.py3-none-any.whl (150kB)
Collecting virtualenv (from pipenv)
  Downloading https://files.pythonhosted.org/packages/b6/30/96a02b2287098b23b875bc8c2f58071c35d2efe84f747b64d523721dc2b5/virtualenv-16.0.0-py2.py3-none-any.whl (1.9MB)
Collecting virtualenv-clone>=0.2.5 (from pipenv)
  Downloading https://files.pythonhosted.org/packages/6d/c2/dccb5ccf599e0c5d1eea6acbd058af7a71384f9740179db67a9182a24798/virtualenv_clone-0.3.0-py2.py3-none-any.whl
Requirement already satisfied: pip>=9.0.1 in /usr/local/lib/python3.6/site-packages (from pipenv) (10.0.1)
Installing collected packages: certifi, virtualenv, virtualenv-clone, pipenv
Successfully installed certifi-2018.4.16 pipenv-2018.5.18 virtualenv-16.0.0 virtualenv-clone-0.3.0
Removing intermediate container 19666f95212b
 ---> 2f8d9ee873ca
Step 6/7 : RUN pipenv install --system
 ---> Running in baca593927a8
Installing dependencies from Pipfile.lock (c2c6d4)…
Removing intermediate container baca593927a8
 ---> 2d402a8f0e26
Step 7/7 : EXPOSE 8000
 ---> Running in c3e7a4b032d8
Removing intermediate container c3e7a4b032d8
 ---> b44a8c214cdf
Successfully built b44a8c214cdf
Successfully tagged gdevops/django36_ch4:latest

docker images

See also

$ docker images --no-trunc
REPOSITORY             TAG                 IMAGE ID                                                                  CREATED             SIZE
gdevops/django36_ch4   latest              sha256:b44a8c214cdfc23f6f8a4481277028fd56b1adcce615f92f703ddca728e054e0   5 minutes ago       1.04GB
python                 3.6                 sha256:29d2f3226daf297b27f0240244f4e8d614fb63eeab8cd09d816e8b7b04d1c011   3 weeks ago         911MB

mb_project/settings.py

# Database
# https://docs.djangoproject.com/en/2.0/ref/settings/#databases

# https://djangoforbeginners.com/docker-postgresql/
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'postgres',
        'USER': 'postgres',
        'HOST': 'db', # set in docker-compose.yml
        'POST': 5432 # default postgres port
    }
}

Launch the db and web services with docker-compose.yml

version: '3'

services:
  db:
    image: postgres:10.4
    volumes:
      - postgres_data:/var/lib/postgresl/data/

  web:
    build: .
    command: python /code/manage.py migrate --noinput
    command: python /code/manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    depends_on:
      - db

volumes:
  postgres_data:

On the top line we’re using the most recent version of Compose which is 3.

db

Under db for the database we want the Docker image for Postgres 10.4 and use volumes to tell Compose where the container should be located in our Docker container.

web

For web we’re specifying how the web service will run. First Compose needs to build an image from the current directory, automatically run migrations and hide the output, then start up the server at 0.0.0.0:8000.

volumes

We use volumes to tell Compose to store the code in our Docker container at /code/.

Warning

Cela nous permet d’avoir accès à notre code sur le host.

ports

The ports config lets us map our own port 8000 to the port 8000 in the Docker container.

And finally depends_on says that we should start the db first before running our web services.

volumes

The last section volumes is because Compose has a rule that you must list named volumes in a top-level volumes key.

Docker is all set!

docker-compose run web python /code/manage.py migrate –noinput

$ docker-compose run web python /code/manage.py migrate --noinput
Creating network "ch4-message-board-app_default" with the default driver
Creating volume "ch4-message-board-app_postgres_data" with default driver
Pulling db (postgres:10.4)...
10.4: Pulling from library/postgres
f2aa67a397c4: Pull complete
8218dd41bf94: Pull complete
e9b7fa2e6bd8: Pull complete
7288a45ee17f: Pull complete
0d0f8a67376c: Pull complete
972b115243de: Pull complete
d38528c83dd1: Pull complete
9be166d23dee: Pull complete
12015b5ceae7: Pull complete
363876c09ce9: Pull complete
b810ba8b2ac0: Pull complete
e1ee11d636cf: Pull complete
50d32813cba1: Pull complete
4f0109485c03: Pull complete
Digest: sha256:1acf72239c685322579be2116dc54f8a25fc4523882df35171229c9fee3b3b17
Status: Downloaded newer image for postgres:10.4
Creating ch4-message-board-app_db_1 ... done
Building web
Step 1/7 : FROM python:3.6
 ---> 29d2f3226daf
Step 2/7 : ENV PYTHONUNBUFFERED 1
 ---> Using cache
 ---> 8fb46520978f
Step 3/7 : COPY . /code/
 ---> 3b31f2bb6016
Step 4/7 : WORKDIR /code/
Removing intermediate container 183aa302c2d1
 ---> fd032580fe90
Step 5/7 : RUN pip install pipenv
 ---> Running in 8f333f7716ee
Collecting pipenv
  Downloading https://files.pythonhosted.org/packages/8d/fe/4faa519acfb984015dde4e2973d89e47baf6a9cd81e9d58e2f2d3c47fb6f/pipenv-2018.5.18-py3-none-any.whl (6.4MB)
Collecting certifi (from pipenv)
  Downloading https://files.pythonhosted.org/packages/7c/e6/92ad559b7192d846975fc916b65f667c7b8c3a32bea7372340bfe9a15fa5/certifi-2018.4.16-py2.py3-none-any.whl (150kB)
Requirement already satisfied: setuptools>=36.2.1 in /usr/local/lib/python3.6/site-packages (from pipenv) (39.1.0)
Requirement already satisfied: pip>=9.0.1 in /usr/local/lib/python3.6/site-packages (from pipenv) (10.0.1)
Collecting virtualenv (from pipenv)
  Downloading https://files.pythonhosted.org/packages/b6/30/96a02b2287098b23b875bc8c2f58071c35d2efe84f747b64d523721dc2b5/virtualenv-16.0.0-py2.py3-none-any.whl (1.9MB)
Collecting virtualenv-clone>=0.2.5 (from pipenv)
  Downloading https://files.pythonhosted.org/packages/6d/c2/dccb5ccf599e0c5d1eea6acbd058af7a71384f9740179db67a9182a24798/virtualenv_clone-0.3.0-py2.py3-none-any.whl
Installing collected packages: certifi, virtualenv, virtualenv-clone, pipenv
Successfully installed certifi-2018.4.16 pipenv-2018.5.18 virtualenv-16.0.0 virtualenv-clone-0.3.0
Removing intermediate container 8f333f7716ee
 ---> f27a4a1e4257
Step 6/7 : RUN pipenv install --system
 ---> Running in 2519166487e4
Installing dependencies from Pipfile.lock (c2c6d4)…
Removing intermediate container 2519166487e4
 ---> 255cb3b345c2
Step 7/7 : EXPOSE 8000
 ---> Running in 8cb1c964976e
Removing intermediate container 8cb1c964976e
 ---> 376512737492
Successfully built 376512737492
Successfully tagged ch4-message-board-app_web:latest
WARNING: Image for service web was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, posts, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying posts.0001_initial... OK
  Applying sessions.0001_initial... OK

docker-compose run web python /code/manage.py createsuperuser

$ docker-compose run web python /code/manage.py createsuperuser
WARNING: The Docker Engine you're using is running in swarm mode.

Compose does not use swarm mode to deploy services to multiple nodes in a swarm. All containers will be scheduled on the current node.

To deploy your application across the swarm, use `docker stack deploy`.

Starting ch4messageboardapp_db_1 ... done
Username (leave blank to use 'root'):
Email address: patrick.vergain@id3.eu
Password:
Password (again):
The password is too similar to the email address.
This password is too short. It must contain at least 8 characters.
Password:
Password (again):
Superuser created successfully.
../../_images/create_superuser.png

docker-compose run web python /code/manage.py createsuperuser

docker-compose up

Y:\projects_id3\P5N001\XLOGCA135_tutorial_docker\tutorial_docker\tutoriels\djangoforbeginners\ch4-message-board-app>docker-compose up
WARNING: The Docker Engine you're using is running in swarm mode.

Compose does not use swarm mode to deploy services to multiple nodes in a swarm. All containers will be scheduled on the current node.

To deploy your application across the swarm, use `docker stack deploy`.

ch4messageboardapp_db_1 is up-to-date
Creating ch4messageboardapp_web_1 ... done
Attaching to ch4messageboardapp_db_1, ch4messageboardapp_web_1
db_1   | The files belonging to this database system will be owned by user "postgres".
db_1   | This user must also own the server process.
db_1   |
db_1   | The database cluster will be initialized with locale "en_US.utf8".
db_1   | The default database encoding has accordingly been set to "UTF8".
db_1   | The default text search configuration will be set to "english".
db_1   |
db_1   | Data page checksums are disabled.
db_1   |
db_1   | fixing permissions on existing directory /var/lib/postgresql/data ... ok
db_1   | creating subdirectories ... ok
db_1   | selecting default max_connections ... 100
db_1   | selecting default shared_buffers ... 128MB
db_1   | selecting dynamic shared memory implementation ... posix
db_1   | creating configuration files ... ok
db_1   | running bootstrap script ... ok
db_1   | performing post-bootstrap initialization ... ok
db_1   | syncing data to disk ... ok
db_1   |
db_1   | Success. You can now start the database server using:
db_1   |
db_1   |     pg_ctl -D /var/lib/postgresql/data -l logfile start
db_1   |
db_1   |
db_1   | WARNING: enabling "trust" authentication for local connections
db_1   | You can change this by editing pg_hba.conf or using the option -A, or
db_1   | --auth-local and --auth-host, the next time you run initdb.
db_1   | ****************************************************
db_1   | WARNING: No password has been set for the database.
db_1   |          This will allow anyone with access to the
db_1   |          Postgres port to access your database. In
db_1   |          Docker's default configuration, this is
db_1   |          effectively any other container on the same
db_1   |          system.
db_1   |
db_1   |          Use "-e POSTGRES_PASSWORD=password" to set
db_1   |          it in "docker run".
db_1   | ****************************************************
db_1   | waiting for server to start....2018-01-23 08:34:30.556 UTC [39] LOG:  listening on IPv4 address "127.0.0.1", port 5432
db_1   | 2018-01-23 08:34:30.557 UTC [39] LOG:  could not bind IPv6 address "::1": Cannot assign requested address
db_1   | 2018-01-23 08:34:30.557 UTC [39] HINT:  Is another postmaster already running on port 5432? If not, wait a few seconds and retry.
db_1   | 2018-01-23 08:34:30.682 UTC [39] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
db_1   | 2018-01-23 08:34:30.865 UTC [40] LOG:  database system was shut down at 2018-01-23 08:34:28 UTC
db_1   | 2018-01-23 08:34:30.928 UTC [39] LOG:  database system is ready to accept connections
db_1   |  done
db_1   | server started
db_1   | ALTER ROLE
db_1   |
db_1   |
db_1   | /usr/local/bin/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*
db_1   |
db_1   | 2018-01-23 08:34:31.493 UTC [39] LOG:  received fast shutdown request
db_1   | waiting for server to shut down....2018-01-23 08:34:31.557 UTC [39] LOG:  aborting any active transactions
db_1   | 2018-01-23 08:34:31.559 UTC [39] LOG:  worker process: logical replication launcher (PID 46) exited with exit code 1
db_1   | 2018-01-23 08:34:31.560 UTC [41] LOG:  shutting down
db_1   | 2018-01-23 08:34:32.052 UTC [39] LOG:  database system is shut down
db_1   |  done
db_1   | server stopped
db_1   |
db_1   | PostgreSQL init process complete; ready for start up.
db_1   |
db_1   | 2018-01-23 08:34:32.156 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
db_1   | 2018-01-23 08:34:32.156 UTC [1] LOG:  listening on IPv6 address "::", port 5432
db_1   | 2018-01-23 08:34:32.256 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
db_1   | 2018-01-23 08:34:32.429 UTC [57] LOG:  database system was shut down at 2018-01-23 08:34:31 UTC
db_1   | 2018-01-23 08:34:32.483 UTC [1] LOG:  database system is ready to accept connections
web_1  | Performing system checks...
web_1  |
web_1  | System check identified no issues (0 silenced).
web_1  | January 23, 2018 - 08:46:09
web_1  | Django version 2.0.1, using settings 'mb_project.settings'
web_1  | Starting development server at http://0.0.0.0:8000/
web_1  | Quit the server with CONTROL-C.

We can confirm it works by navigating to http://127.0.0.1:8000/ where you’ll see the same homepage as before.

docker-compose ps

PS Y:\projects_id3\P5N001\XLOGCA135_tutorial_docker\tutorial_docker\tutoriels\william_vincent\ch4-message-board-app> docker-compose ps
          Name                        Command               State           Ports
------------------------------------------------------------------------------------------
ch4messageboardapp_db_1    docker-entrypoint.sh postgres    Up      5432/tcp
ch4messageboardapp_web_1   python /code/manage.py run ...   Up      0.0.0.0:8000->8000/tcp

::

docker-compose exec db bash

docker-compose exec db bash

psql -d db -U postgres

root@ee941cf5bc20:/# psql -U postgres
psql (10.1)
Type "help" for help.

dt

postgres=# \dt
                   List of relations
 Schema |            Name            | Type  |  Owner
--------+----------------------------+-------+----------
 public | auth_group                 | table | postgres
 public | auth_group_permissions     | table | postgres
 public | auth_permission            | table | postgres
 public | auth_user                  | table | postgres
 public | auth_user_groups           | table | postgres
 public | auth_user_user_permissions | table | postgres
 public | django_admin_log           | table | postgres
 public | django_content_type        | table | postgres
 public | django_migrations          | table | postgres
 public | django_session             | table | postgres
 public | posts_post                 | table | postgres
(11 rows)

conninfo

postgres=# \conninfo
You are connected to database "postgres" as user "postgres" via socket in "/var/run/postgresql" at port "5432".
postgres=# \l
                                 List of databases
   Name    |  Owner   | Encoding |  Collate   |   Ctype    |   Access privileges
-----------+----------+----------+------------+------------+-----------------------
 postgres  | postgres | UTF8     | en_US.utf8 | en_US.utf8 |
 template0 | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
           |          |          |            |            | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
           |          |          |            |            | postgres=CTc/postgres
(3 rows)

dn

postgres=# \dn
  List of schemas
  Name  |  Owner
--------+----------
 public | postgres
(1 row)

d posts_post

postgres=# \d posts_post
                            Table "public.posts_post"
 Column |  Type   | Collation | Nullable |                Default
--------+---------+-----------+----------+----------------------------------------
 id     | integer |           | not null | nextval('posts_post_id_seq'::regclass)
 text   | text    |           | not null |
Indexes:
    "posts_post_pkey" PRIMARY KEY, btree (id)