部署友好的项目与 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