让我们使用Docker Compose来启动Django!
最近才开始学习Docker。先读完了《面向程序员的Docker教程 第2版》,现在来试试自己的实践。这次我将使用nginx + (Gunicorn + Django) + PostgreSQL的架构来创建。如果你对本文中使用的代码有兴趣,可以在这里看一下。
开发环境
-
- macOS High Sierra 10.13.6
-
- Docker for Mac
Engine : 18.06.1-ce
Compose : 1.22.0
Python : 3.7
Django : 2.1
准备项目的框架
本次目录的构成如下。
docker-django
├── docker-compose.yml
├── django
│ ├── Dockerfile
│ ├── Dockerfile.base
│ ├── requirements.txt
│ └── requirements.base.txt
└── nginx
├── mime.types
└── nginx.conf
每个容器的配置文件都被放置在与其容器名称对应的目录下。
例如,用于nginx容器的配置文件存储在nginx/文件夹中。
创建用于Django+Gunicorn的基本镜像
首先,创建一个用于开发Django项目的基础镜像。此镜像可用作执行django-admin startproject命令时的容器,或者用作稍后创建的部署镜像的基础镜像。
基础镜像的Dockerfile如下所示。
FROM python:3.7
ENV APP_PATH /opt/apps
COPY requirements.base.txt $APP_PATH/
RUN pip install --no-cache-dir -r $APP_PATH/requirements.base.txt
WORKDIR $APP_PATH
另外,requirements.base.txt文件的内容如下所示。
Django==2.1.11
gunicorn==19.9.0
psycopg2==2.7.5
psycopg2-binary==2.7.5
让我们快速地构建这个。
$ docker build -t django2.1 -f ./django/Dockerfile.base ./django
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
django2.1 latest c391e4c70e98 6 minutes ago 960MB
python 3.7 825141134528 4 weeks ago 923MB
可以看出,基于Python 3.7镜像创建了一个名为django2.1:latest的镜像。
2. 在本地创建 Django 项目
创建了一个可以使用Django的映像后,
我们将创建一个基于此映像的容器来创建项目文件。
在创建容器时,重要的是要用mount选项绑定docker-django/django/。
这样做的好处是容器可以像virtualenv一样使用!
现在立即执行以下命令。
$ cd django
$ docker run --rm \
--mount type=bind,src=$(pwd),dst=/opt/apps \
django2.1 \
django-admin startproject my_docker_project .
由于命令有点长,所以我在其中添加了换行。
让我们一行一行地看。
首先,我们想将Django项目放在./django/文件夹中,所以我们将当前目录切换到该文件夹。
接下来是容器的启动选项。
第一行的–rm是一个选项,表示在命令执行完毕后删除容器。
第二行的–mount是用来配置在容器启动时要挂载的主机目录等。这次我们允许对主机进行读写,所以类型是bind,src是当前目录,dst是容器内的当前目录。
第三行指定了容器的基础镜像。
第四行是在容器内执行的命令。这次我们创建了一个名为my_docker_project的项目。
执行后,查看django文件夹的内容,
$ tree
.
├── Dockerfile
├── Dockerfile.base
├── manage.py
├── my_docker_project
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── requirements.base.txt
└── requirements.txt
Django项目的文件被创建在本地。太棒了!
当使用Django命令进行各种操作时,需要在装载主机的容器中执行。
如果你能够做到这一点,暂时放下Django相关的事情。
创建docker-compose.yml文件并设置各个容器之间的连接配置。
当Django+Gunicorn环境部署好后,我们将把注意力转向容器的整体架构。
我们的目标是使用nginx + (Gunicorn + Django) + PostgreSQL的组合形式。
docker-compose.yml文件如下:
version: '3.7'
services:
django:
restart: always
build: ./django
expose:
- "3031"
depends_on:
- postgres
command: bash -c "python manage.py migrate && gunicorn my_docker_project.wsgi -b 0.0.0.0:3031"
volumes:
- "staticdata:/opt/static/"
nginx:
restart: always
image: nginx
depends_on:
- django
ports:
- "80:80"
volumes:
- "./nginx/:/etc/nginx/"
- "staticdata:/opt/apps/static/"
postgres:
image: postgres
ports:
- "5432:5432"
volumes:
- "dbdata:/var/lib/postgresql/data"
environment:
POSTGRES_PASSWORD: hogemojahogemoja
volumes:
dbdata:
staticdata:
在这里,「我想要将数据库数据持久化。」「我希望从nginx容器中分发静态文件。」这两点很重要。
「我想要对数据库的数据进行持久化处理。」 <=> 「我想要使用容器外部的卷。」
因此,在docker-compose.yml的顶层声明了一个名为dbdata的卷,并将其挂载到容器中。
「我想要从nginx容器传送静态文件。」 <=> 「我想在容器之间共享资源。」
因此,我在顶级目录下声明了一个名为staticdata的卷,并将其挂载到django和nginx的两个容器中。
3-1.配置nginx容器
让我们快速开始,在本次配置中,我们将使用nginx来接收请求,并将其适当地转发到Django(Gunicorn),同时还会提供静态文件服务。我们需要将这些信息写入conf文件中。
http {
#~中略~
include /etc/nginx/mime.types;
#~中略~
upstream django_server {
#docker-compose.ymlに記入したサーバ名、ポートを指定します。 #
server django:3031 fail_timeout=0;
}
server {
#~中略~
location /static/ {
#先ほどしていた静的ファイルのボリュームのマウント先を指定します。#
alias /opt/apps/static/;
}
location / {
try_files $uri @proxy_to_django;
}
location @proxy_to_django {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_redirect off;
proxy_pass http://django_server;
}
#~中略~
}
}
这是Nginx容器的设置。
这次我们采用了最简单的配置,mime.types保持使用默认设置。
创建用于配置和构建Django容器的Dockerfile。
根据docker-compose.yml和nginx.conf文件中的信息,对settings.py进行编辑。
#〜中略〜
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'postgres', #作成時のデフォルト
'USER': 'postgres', #作成時のデフォルト
'PASSWORD' : 'hogemojahogemoja', #作成時にdocker-compose.ymlで設定
'HOST' : 'postgres', #コンテナのサーバ名
'PORT' : 5432,
}
}
#〜中略〜
STATIC_URL = '/static/'
STATIC_ROOT = '/opt/static' #ボリュームマウント先のパス
#〜中略〜
接下来,我们将编辑Dockerfile。
FROM django2.1:latest
ENV APP_PATH /opt/apps
COPY . $APP_PATH/
RUN pip install --no-cache-dir -r $APP_PATH/requirements.txt
WORKDIR $APP_PATH
RUN python manage.py collectstatic --noinput
这个图片和之前的基础图片不同,是用于部署的图片。
我们安装了项目中使用的Python库,并将静态文件打包用于发布。
使用Docker Compose进行启动。
辛苦了,现在只需要更新一下。
$ docker-compose up --build
5. 最后
我对Docker的经验还很浅,但是能够创建出这样各个容器协同运行的场景实在是让我非常激动和快乐。
未来我希望能够更多地将Docker应用于工作和兴趣领域!