部署友好的專案與 Docker 支援

預設的 Django 專案模板很好但是一旦你開始部署你的程式碼,例如 devops 將他們的手放在專案上,事情會變得混亂。你可以做的是將原始碼與儲存庫中所需的其他程式碼分開。

你可以在 GitHub 上找到可用的 Django 專案模板。

專案結構

PROJECT_ROOT
├── devel.dockerfile
├── docker-compose.yml
├── nginx
│   └── project_name.conf
├── README.md
├── setup.py
└── src
    ├── manage.py
    └── project_name
        ├── __init__.py
        └── service
            ├── __init__.py
            ├── settings
            │   ├── common.py
            │   ├── development.py
            │   ├── __init__.py
            │   └── staging.py
            ├── urls.py
            └── wsgi.py

我喜歡為每個專案保留名為 serviceservice 目錄,這要歸功於我可以在我的所有專案中使用相同的 Dockerfile。這裡已經詳細記錄了需求和設定的拆分:
使用多個需求檔案
使用多個設定

Dockerfile

假設只有開發人員使用 Docker(現在並不是每個開發人員都信任它)。這可能是一個開發環境 devel.dockerfile

FROM python:2.7
ENV PYTHONUNBUFFERED 1

RUN mkdir /run/service
ADD . /run/service
WORKDIR /run/service

RUN pip install -U pip
RUN pip install -I -e .[develop] --process-dependency-links

WORKDIR /run/service/src
ENTRYPOINT ["python", "manage.py"]
CMD ["runserver", "0.0.0.0:8000"]

僅新增需求將在構建時利用 Docker 快取 - 你只需要在需求更改時重建。

撰寫

Docker 組合派上用場 - 特別是當你有多個本地執行的服務時。docker-compose.yml

version: '2'
services:
  web:
    build:
      context: .
      dockerfile: devel.dockerfile
    volumes:
      - "./src/{{ project_name }}:/run/service/src/{{ project_name }}"
      - "./media:/run/service/media"
    ports:
      - "8000:8000"
    depends_on:
      - db
  db:
    image: mysql:5.6
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_DATABASE={{ project_name }}
  nginx:
    image: nginx
    ports:
      - "80:80"
    volumes:
      - "./nginx:/etc/nginx/conf.d"
      - "./media:/var/media"
    depends_on:
      - web

Nginx

你的開發環境應該儘可能接近 prod 環境,所以我喜歡從一開始就使用 Nginx。這是一個示例 nginx 配置檔案:

server {
    listen   80;
    client_max_body_size 4G;
    keepalive_timeout 5;

    location /media/ {
        autoindex on;
        alias /var/media/;
    }

    location / {
        proxy_pass_header Server;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Scheme $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Ssl on;
        proxy_connect_timeout 600;
        proxy_read_timeout 600;
        proxy_pass http://web:8000/;
    }
}

用法

$ cd PROJECT_ROOT
$ docker-compose build web  # build the image - first-time and after requirements change
$ docker-compose up  # to run the project
$ docker-compose run --rm --service-ports --no-deps  # to run the project - and be able to use PDB
$ docker-compose run --rm --no-deps <management_command>  # to use other than runserver commands, like makemigrations
$ docker exec -ti web bash  # For accessing django container shell, using it you will be inside /run/service directory, where you can run ./manage shell, or other stuff
$ docker-compose start  # Starting docker containers
$ docker-compose stop  # Stopping docker containers