创建 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” → 安装找到的相应插件。
因为被要求重新启动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’。
可以创建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目录中,
-
- 创建一个名为settings的文件夹
-
- 将settings.py重命名为settings/base.py
- 创建settings/local.py和settings/production.py文件。
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。
然后,它能够识别Docker内的Python环境。太厉害了!
启用Django的支持
偏好设置中,搜索:django
当出现语言和框架的选项时,选择Django,并勾选”启用Django支持”。
Django 项目根目录:位于 manage.py 的 docker-django-skeleton
设置:docker_django_skeleton/settings/local.py
点击“确定”按钮
设定项目结构
偏好:搜索功能
选择包含manage.py的docker-django-skeleton目录,点击Source按钮,然后点击OK。
迁徙 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)
→ 确定
在运行服务器执行环境已被选择的状态下,点击虫(调试)按钮。
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机器,然后显示页面。调试器也处于启用状态,因此可以使用断点。太棒了!
在公开环境中启动
[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
会消失。