# Dockerize Django

Hi, this is the first part of [series](https://avik.com.np/series/django-with-docker) where we will be dockerizing a django application with  PostgreSQL database and deploying in server. For production environment we'll use Gunicorn and Nginx. 
In this post we will write a Dockerfile to build a container running a Django application. Dockerize django application with PostgreSQL database.

## What is docker?
Docker is a platform for building, running and shipping applications in consistent manner. It helps to package our application and run it in any machine anywhere. Docker enables you to separate your applications from your infrastructure so you can deliver software quickly.

## Advantages of using docker
- Flexible resource sharing.
- Scalability - many containers can be placed in a single host.
- Running your service on hardware that is much cheaper than standard servers.
- Fast deployment, ease of creating new instances, and faster migrations.
- Ease of moving and maintaining your applications.
- Better security, less access needed to work with the code running inside containers, and fewer software dependencies.

#### Images
An image is a read-only template with instructions for creating a Docker container. Often, an image is based on another image, with some additional customization.

#### Container
Docker provides the ability to package and run an application in a loosely isolated environment called a container. Containers are isolated environment for running the application. The isolation and security allows you to run many containers simultaneously on a given host. Containers are lightweight and contain everything needed to run the application, so you do not need to rely on what is currently installed on the host. 
You can create, start, stop, move, or delete a container using the Docker API or CLI. By default, a container is relatively well isolated from other containers and its host machine. You can control how isolated a container’s network, storage, or other underlying subsystems are from other containers or from the host machine. Difference between containers and virtual machines is that virtual machines virtualize an entire machine down to the hardware layers and containers only virtualize software layers above the operating system level.

#### Pros of using containers over virtual machine:
- Containers are lightweight than virtual machine.
- Containers allows isolation.
- Containers are fast and use less hardware resource than virtual machines.

### Prerequisites for starting dockerizing django applications
- [Docker](https://www.docker.com)
- Python
- [Django](https://www.djangoproject.com/)
- PIP

## Starting the project
If you already have running django application you can skip this part to writing a Dockerfile [here](#heading-what-is-dockerfile). If not let's create new django project.

### creating a django project
 ``` 
django-admin startproject DjangoWithDocker 
```

### Run and test django app
```
cd DjangoWithDocker
python manage.py runserver
```

### Add psycopg2 in requirements for postgres db.
```
pip install psycopg2-binary==2.9.3
```

### Create reqirements.txt file for dependency
```    
pip freeze > requirements.txt
```

## Now, lets create a Dockerfile. 
While running Docker run command docker uses Dockerfile to build the image. It is a text document that contains commands to build a docker image.

Now, create Dockerfile (no any extension) on the root of you project and add code below in file.
```
FROM python:3.10-alpine

ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1

RUN pip install --upgrade pip

ENV APP_DIR /home/DockerWithDjango

WORKDIR ${APP_DIR}

ADD requirements.txt ${APP_DIR}/

RUN pip install -r ${APP_DIR}/requirements.txt

COPY . ${APP_DIR}

EXPOSE 8000

CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
```
### Build docker image
``` 
docker build -t django-with-docker .
```
### Run and test the application
```
docker run django-with-docker
```
To run django application in browser run following command and visit localhost:8000 in browser.
```
docker run --publish 8000:8000 django-with-docker
```

### Add docker-compose.yml file in root of the project
```
version: "3.9"
   
volumes:
  dbdata:

networks:
  django_withdocker:
    driver: bridge

services:
  web:
    build: 
      context: .
    volumes:
      - .:/home/django-with-docker
    ports:
      - 8000:8000
    command: python manage.py runserver 0.0.0.0:8000
    container_name: django_with_docker_web
    restart: always
    depends_on:
      - db
    links:
      - db
    networks:
      - django_withdocker
  db:
    image: postgres
    volumes:
      - dbdata:/var/lib/postgresql
    environment:
      - POSTGRES_DB=postgres
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
    networks:
      - django_withdocker
```

### Now update your database settings on django application settings.
```
DB_NAME = 'postgres',
DB_USER = 'postgres',
DB_PASSWORD = 'postgres',
DB_HOST = 'db',
DB_PORT = 5432
```

### Run and build command
```
docker-compose build
docker-compose up
```

Or just run following code to build and run
```
docker-compose up --build
```

### Make migrations command
```
docker-compose run web python manage.py makemigrations
```

### Migrate command
```
docker-compose run web python manage.py migrate
```

