创建 Docker + Django + uWSGI + nginx PyCharm 开发环境(包括用于生产环境的文件)

PyCharm 2016 的 Docker 支持非常方便易用。

我第一次使用Docker创建开发环境,

    • ローカル ( mac ) は Docker Toolbox を使って開発環境を作る。PyCharm のデバッガでステップ実行できるようにする。

 

    • ソースコード、およびログディレクトリは Docker イメージの中に入れず、ホストのディレクトリをマウントして使う

 

    公開サーバを見越して uwsgi, nginx の設定も作っておく

因为到了这个地步,所以我将写下步骤。

在此链接中放置了代码:https://github.com/ytyng/docker-django-skeleton。

我参考了这个链接:https://github.com/dockerfiles/django-uwsgi-nginx。

需要安装的必要应用程序

PyCharm v2016.2〜
Docker Toolbox

我会按照安装程序进行安装。

创建项目并在PyCharm中打开

$ mkdir docker-django-skeleton

$ open -a PyCharm docker-django-skeleton

安装用于PyCharm的Bash插件。

在菜单栏中,点击PyCharm → 首选项 → 搜索: 插件 → 在插件搜索中搜索”BashSupport” → 安装找到的相应插件。

スクリーンショット 2016-09-26 17.40.19.png

因为被要求重新启动PyCharm,所以按照指示重新启动它。

创建一个适用于Docker的文件。

为了避免在项目根目录直接放置 Dockerfile 变得混乱不堪,我们创建一个名为 docker 的文件夹,并将相关文件放入其中。

FROM ubuntu:16.04

MAINTAINER ytyng

RUN apt-get update && apt-get install -y \
    python3 \
    python3-pip \
    python3-dev \
    python3-setuptools \
    libjpeg-dev \
    nginx \
    supervisor \
  && rm -rf /var/lib/apt/lists/*

# ipython, gnureadline が必要なら
# lib32ncurses5-dev

RUN ln -s /usr/lib/x86_64-linux-gnu/libjpeg.so /usr/lib/libjpeg.so

# RUN easy_install3 pip  # aptで入れた方が安定

COPY requirements/base.txt /tmp/requirements/base.txt
RUN pip3 install -r /tmp/requirements/base.txt

# setup all the configfiles
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
COPY nginx-app.conf /etc/nginx/sites-available/default
COPY supervisor-app.conf /etc/supervisor/conf.d/

RUN mkdir -p /etc/nginx/certs
# COPY certs /etc/nginx/certs/

# set locale
RUN locale-gen en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8

EXPOSE 80
#EXPOSE 443

考虑到安装Pillow,我已经安装了libjpeg等相关软件。

Django==1.10.1
PyMySQL
pytz

↑ 这个例子中,由于DB是SQLite3,所以不需要PyMySQL。但为了作为示例,还是写上了。

server {
    listen 80;
    # listen 443 ssl;

    server_name docker-django-skeleton.example.com;

    charset utf-8;

    # ssl_certificate /etc/nginx/certs/xxx.crt;
    # ssl_certificate_key /etc/nginx/certs/xxx.key;

    location /static/ {
        alias /var/django/docker-django-skeleton/staticfiles/;
        break;
    }

    location / {
        include uwsgi_params;
        uwsgi_pass 127.0.0.1:3031;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Real-IP $remote_addr;
    }
}
[program:app-uwsgi]
command = /usr/local/bin/uwsgi --ini /var/django/docker-django-skeleton/conf/uwsgi.ini

[program:nginx-app]
command = /usr/sbin/nginx

创建适用于Docker的配置文件

我会准备一个用于配置环境变量的Bash脚本。
我会根据在Mac上执行和在公开服务器上启动的情况下来加载不同的配置。

#!/usr/bin/env bash

APP_NAME=docker-django-skeleton
DJANGO_APP_NAME=docker_django_skeleton

PROJECT_DIR=$(cd $(dirname ${BASH_SOURCE:-$0})/..;pwd)

if [ $(which docker-machine) ]; then
    # mac
    eval "$(docker-machine env default)"
    DOCKER_COMMAND=docker
    DOCKER_MACHINE_COMMAND=docker-machine
    LOG_DIR=/tmp/log/${APP_NAME}
    export UWSGI_PROCESSES=1
    export UWSGI_THREADS=1
    export DJANGO_SETTINGS_MODULE=${DJANGO_APP_NAME}.settings.local
else
    # ubuntu
    DOCKER_COMMAND="sudo docker"
    LOG_DIR=/var/log/${APP_NAME}
    OPTIONAL_PARAMS="--link mysql:mysql"
    RUN_COMMAND="supervisord -n"
    export UWSGI_PROCESSES=2
    export UWSGI_THREADS=2
    export DJANGO_SETTINGS_MODULE=${DJANGO_APP_NAME}.settings.production
fi

用于创建Docker镜像的脚本

#!/usr/bin/env bash
cd $(dirname ${BASH_SOURCE:-$0})
. _settings.sh

${DOCKER_COMMAND} build -t ${APP_NAME} .
#!/usr/bin/env bash
cd $(dirname ${BASH_SOURCE:-$0})
. _settings.sh

mkdir -p -m 777 ${LOG_DIR}

${DOCKER_COMMAND} run -d -P -p 80:80 -p 443:443 \
  -v ${PROJECT_DIR}:/var/django/${APP_NAME} \
  -v ${LOG_DIR}:/var/log/django \
  -v /etc/localtime:/etc/localtime:ro \
  -e DJANGO_SETTINGS_MODULE=${DJANGO_SETTINGS_MODULE} \
  -e UWSGI_PROCESSES=${UWSGI_PROCESSES} \
  -e UWSGI_THREADS=${UWSGI_THREADS} \
  ${OPTIONAL_PARAMS} \
  --name ${APP_NAME} ${APP_NAME} ${RUN_COMMAND}

if [ "${DOCKER_MACHINE_COMMAND}" ]; then
    docker-machine ip default
fi

${DOCKER_COMMAND} ps
#!/usr/bin/env bash
cd $(dirname ${BASH_SOURCE:-$0})
. _settings.sh

EXISTS=$(${DOCKER_COMMAND} ps --quiet --filter name=${APP_NAME})

if [ "${EXISTS}" ]; then
    ${DOCKER_COMMAND} exec -it ${APP_NAME} /bin/bash $@
else
    ${DOCKER_COMMAND} run --rm -it \
    -e DJANGO_SETTINGS_MODULE=${DJANGO_SETTINGS_MODULE} \
    -v ${PROJECT_DIR}:/var/django/${APP_NAME} \
    --name ${APP_NAME} ${APP_NAME} /bin/bash $@
fi
#!/usr/bin/env bash

. _settings.sh

${DOCKER_COMMAND} rm --force ${APP_NAME}
#!/usr/bin/env bash
cd $(dirname ${BASH_SOURCE:-$0})
. _settings.sh

EXISTS=$(${DOCKER_COMMAND} ps --quiet --filter name=${APP_NAME})

if [ "${EXISTS}" ]; then
    ${DOCKER_COMMAND} exec -it ${APP_NAME} \
    /bin/bash -c "cd /var/django/${APP_NAME}/${APP_NAME}/; ./manage.py $*"

else
    ${DOCKER_COMMAND} run --rm -it \
    -e DJANGO_SETTINGS_MODULE=${DJANGO_SETTINGS_MODULE} \
    -v ${PROJECT_DIR}:/var/django/${APP_NAME} \
    --name ${APP_NAME} ${APP_NAME} /bin/bash -c \
    "cd /var/django/${APP_NAME}/${APP_NAME}/; ./manage.py $*"
fi

在.sh文件中,需要赋予执行权限。

$ chmod +x docker-*.sh manage.sh
docker-django-skeleton
└── docker
    ├── Dockerfile
    ├── _settings.sh
    ├── docker-01-build.sh
    ├── docker-02-run.sh
    ├── docker-03-bash.sh
    ├── docker-09-rm.sh
    ├── manage.sh
    ├── nginx-app.conf
    ├── requirements
    │   └── base.txt
    └── supervisor-app.conf

创建Docker镜像

在PyCharm上右键单击先前创建的docker-01-build.sh,然后选择运行’docker-01-build.sh’。

スクリーンショット 2016-09-26 17.34.58.png

可以创建Docker镜像。

创建Django项目目录

如果您在Mac上已经安装了Django来处理其他事务,那么您可以使用它来执行django-admin.py startproject命令,但是本次我们将使用刚刚在Docker镜像中安装的Django来创建Django项目。

将整个项目目录挂载到Docker中,并在Docker内部使用startproject命令进行操作。

$ docker run -it -v `pwd`:/var/django/docker-django-skeleton docker-django-skeleton /bin/bash

※ pwd 是指 docker-django-skeleton 目录。该目录是 docker 目录的父目录。

$ docker run -it -v `pwd`:/var/django/docker-django-skeleton docker-django-skeleton /bin/bash
root@8d2ba7a54287:/# cd /var/django/docker-django-skeleton/
root@8d2ba7a54287:/var/django/docker-django-skeleton# django-admin.py startproject docker_django_skeleton
root@8d2ba7a54287:/var/django/docker-django-skeleton# mv docker_django_skeleton docker-django-skeleton
root@8d2ba7a54287:/var/django/docker-django-skeleton#

在Django项目中,关于目录名的偏好是将下划线改为连字符。

当查看PyCharm时,可以确认已创建了docker-django-skeleton目录。

将设置分成不同部分

在Django中,常常使用的一种做法是将设置(settings)在本地环境和发布环境中分开。

在docker_django_skeleton目录中,

    1. 创建一个名为settings的文件夹

 

    1. 将settings.py重命名为settings/base.py

 

    创建settings/local.py和settings/production.py文件。
スクリーンショット 2016-09-26 18.09.27.png

settings/local.py 和 settings/production.py 的内容如下所示。

from .base import *  # NOQA

没有内容,但这次就这样吧。

把 manage.py 文件的解释器(shebang)更改为 python3

看一下生成的 manage.py,第一行是什么。

#!/usr/bin/env python

但是,由于Docker镜像中仍然保留了Python2,可能会导致故障发生。

#!/usr/bin/env python3

我会做出更改。

在 PyCharm 的解释器中指定 Docker 的 Python。

PyCharm → 首选项 → 搜索: 解释器

出现了项目解释器。

在这里,点击右上角的「…」按钮,然后选择添加远程。

请配置远程Python解释器,
选择”Docker”,镜像名称请选择docker-django-skeleton:latest。

另外,Python解释器路径设置为python,但需要更改为python3。

スクリーンショット 2016-09-26 18.13.17.png

然后,它能够识别Docker内的Python环境。太厉害了!

スクリーンショット 2016-09-26 18.14.12.png

启用Django的支持

偏好设置中,搜索:django

当出现语言和框架的选项时,选择Django,并勾选”启用Django支持”。

Django 项目根目录:位于 manage.py 的 docker-django-skeleton
设置:docker_django_skeleton/settings/local.py
点击“确定”按钮

スクリーンショット 2016-09-26 18.52.11.png

设定项目结构

偏好:搜索功能

选择包含manage.py的docker-django-skeleton目录,点击Source按钮,然后点击OK。

スクリーンショット 2016-09-26 18.51.32.png

迁徙 xǐ)

接下来,我们将执行./manage.py migrate。
由于在docker容器中,执行./manage.py也有些繁琐,但是我已经在docker目录中创建了一个manage.sh文件,我们将使用它。

$ cd docker
$ ./manage.sh

Type 'manage.py help <subcommand>' for help on a specific subcommand.

Available subcommands:

[auth]
    changepassword
    createsuperuser

[django]
    check
    compilemessages
...

$ ./manage.sh migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
...

使用Docker的Django环境完成了迁移工作。

启动测试服务器

在PyCharm的右上角,单击Run/Debug选项,然后选择Edit Configurations…

在运行/调试配置对话框中,点击左上方的 + 按钮。

选择Django服务器

主机:输入0.0.0.0(重要)
名称:随意输入(例如:runserver)
→ 确定

スクリーンショット 2016-09-26 18.53.13.png

在运行服务器执行环境已被选择的状态下,点击虫(调试)按钮。

System check identified no issues (0 silenced).
September 26, 2016 - 09:54:15
Django version 1.10.1, using settings 'docker_django_skeleton.settings.local'
Starting development server at http://0.0.0.0:8000/
Quit the server with CONTROL-C.

点击0.0.0.0:8000,将启动浏览器并重定向到Docker机器,然后显示页面。调试器也处于启用状态,因此可以使用断点。太棒了!

スクリーンショット 2016-09-26 18.55.07.png

在公开环境中启动

[uwsgi]

app = $(APP_NAME)
django_app = $(DJANGO_APP_NAME)

base = /var/django/%(app)/%(app)/
pythonpath = %(base)
chdir = %(base)

socket = 127.0.0.1:3031

module = %(django_app).wsgi:application

processes = $(UWSGI_PROCESSES)
threads = $(UWSGI_THREADS)

master = true

pidfile = /var/run/django/%(app).pid

touch-reload = %(base)/%(django_app)/wsgi.py
lazy-apps = true
thunder-lock = true

buffer-size = 32768

logto = /var/log/django/%(app)/%n.log

这是uwsgi的配置文件吧。

将源代码上传到公开环境的服务器中。

$ ./docker-01-build.sh

在本地创建一个容器(可以将本地创建的容器推送到Docker hub -> 在生产环境中也可以拉取)

$ docker-02-run.sh

在启动时,对于公共环境(或者说是未安装docker-machine的环境),使用生产配置启动nginx → uwsgi → Django。

删除Docker容器时,需要做以下事项。

$ docker-09-rm.sh

会消失。

广告
将在 10 秒后关闭
bannerAds