使用 Docker 部署 Python Django 应用程序
本文最初发表于我的个人网站。
大家好,我写这篇文章的灵感来源于我尝试将部署迁移到 Docker 的经历,特别是对于 Django 应用,但我找不到一篇全面涵盖我所需内容的文章。希望这篇文章能帮助到那些和我一样感到困惑的人。
很多人可能已经听到过“Docker”这个词到处都在说了。你可能也搜索过“Docker up”,甚至尝试过,但可能中途就放弃了。说实话,我一开始也犹豫了一两次才真正上手。一开始可能会有点吓人,但是天哪!一旦你开始使用Docker,就再也回不去了。从生产环境迁移到开发环境的便捷程度简直令人难以置信!
好了,废话不多说,让我们开始吧。
什么是 Docker?
Docker 是一款开源工具,它可以自动将应用程序部署到软件容器中。这些容器类似于虚拟机,但更具可移植性、资源占用更少,并且对宿主机操作系统的依赖性更高。
要了解有关 Docker 工作原理的详细信息,我建议阅读这篇文章。对于那些不习惯阅读长篇文章的人,YouTube 上的这个教程系列对介绍 Docker 的概念特别有帮助。
正在安装 Docker。
如果您的机器上尚未安装 Docker,请根据您的操作系统按照以下详细步骤操作。
接下来,我假设您已经有一个 Django 应用程序,因此本教程将仅指导您如何将其容器化。
1. Windows 10 专业版
2.非专业版的 Windows 10
3. Ubuntu
入门
要部署一个典型的 Django 应用程序,您需要以下服务才能使其运行。
- Nginx - 用于提供静态文件和 Web 服务器
- Postgres/您选择的任何数据库
- 安装了 gunicorn 的 python
要启动这些服务,您需要一个 Dockerfile 文件。Dockerfile 本质上是一个文本文件,其中列出了所有命令行界面 (CLI) 命令以及构建镜像的常规步骤。
1.Python镜像
FROM python:3.6
RUN mkdir /code
WORKDIR /code
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
-
第一行必须以FROM关键字开头。它告诉 Docker 你要基于哪个基础镜像创建镜像。在本例中,我们基于 Python 3.6 镜像创建镜像。
-
第二行是RUN命令,用于在镜像上运行指令。在本例中,我们创建了一个名为code 的目录。之后,WORKDIR将 code 目录设置为工作目录,以便 Dockerfile 中的所有后续指令都在此目录下执行。
-
COPY命令会将主机上的特定文件复制到我们正在创建的镜像中。requirements.txt 文件将被复制到之前设置的工作目录中。之后,运行 RIP install 命令来安装项目所需的 Python 包。
-
最后,将当前工作目录中的项目文件从主机复制到 Docker 镜像中。
要构建此镜像,请运行以下简单命令。
docker build .
在当前 Dockerfile 所在目录中。
对于我们的用例,我们将使用多个镜像,为每个镜像运行此命令会非常繁琐。因此,我们需要 docker-compose,稍后我们将详细介绍。
2. Nginx 镜像
FROM nginx
RUN rm /etc/nginx/conf.d/default.conf
COPY mysite.conf /etc/nginx/conf.d
这些命令与 Python 命令相同,只是专门针对 Nginx。
在这种情况下,我们使用 Nginx 基础镜像,删除 Nginx 自带的默认配置文件,并将其替换为我们自定义的配置文件。自定义配置文件
可能如下所示:
upstream my_site {
server web:8080;
}
server {
listen 80;
charset utf-8;
server_name 127.0.0.1;
client_max_body_size 4G;
access_log /code/logs/nginx-access.log;
error_log /code/logs/nginx-error.log;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
if (!-f $request_filename) {
proxy_pass http://my_site;
break;
}
}
location /static/ {
autoindex on;
alias /code/static_cdn/;
}
location /media/ {
autoindex on;
alias /code/media_cdn/;
}
}
文件位置当然会根据您自己的配置而有所不同。
3. PostgreSQL
最后我们来看数据库,在这个用例中,我使用了postgres。
FROM postgres:latest
COPY ./init/01-db_setup.sh /docker-entrypoint-initdb.d/01-db-setup.sh
现在你可能在想:
“但是Lewis,这个初始化文件是什么?”
为了更好地理解,我们来看看项目中的postgres目录。
postgres
├── postgres/Dockerfile
└── postgres/init
└── postgres/init/01-db_setup.sh
这是一个 shell 脚本(docker 入口点),用于指定要在数据库容器上运行的命令,例如创建数据库、用户以及授予所述用户权限。
#!/bin/sh
psql -U postgres -c "CREATE USER $POSTGRES_USER PASSWORD '$POSTGRES_PASSWORD'"
psql -U postgres -c "CREATE DATABASE $POSTGRES_DB OWNER $POSTGRES_USER"
psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE $POSTGRES_DB TO $POSTGRES_USER"
注意:创建此文件时,请不要忘记运行以下命令使其可执行。
sudo chmod u+x filename.sh
4. 最后用 docker-compose 收尾
到目前为止,您可能已经注意到我们有很多 Dockerfile 文件。借助 docker-compose,我们可以方便地使用 以下命令
构建所有这些镜像。
docker-compose build .
首先,我们需要在项目目录下创建一个 docker-compose.yml 文件。我们将在这个文件中指定 Web 应用程序运行所需的各项服务。
version: '3'
services:
web:
build: .
container_name: great
volumes:
- .:/code
- static:/code/static_cdn
- media:/code/media_cdn
depends_on:
- postgres
expose:
- 8080
command: bash -c "python manage.py collectstatic --no-input && python manage.py makemigrations && python manage.py migrate && gunicorn --workers=3 projectname.wsgi -b 0.0.0.0:8080"
postgres:
build: ./postgres
restart: unless-stopped
expose:
- "5432"
environment: # will be used by the init script
LC_ALL: C.UTF-8
POSTGRES_USER: myuser
POSTGRES_PASSWORD: mypassowrd.
POSTGRES_DB: mydb
volumes:
- pgdata:/var/lib/postgresql/data/
nginx:
restart: always
build: ./nginx/
volumes:
- ./nginx/:/etc/nginx/conf.d
- ./logs/:/code/logs
- static:/code/static_cdn
- media:/code/media_cdn
ports:
- "1221:80"
links:
- web
volumes:
pgdata:
media:
static:
逐行分析这些命令:
- 版本 - 指定我们将要使用的 docker-compose 语法版本。
- 服务——接下来,我们将重点介绍即将推出的各项服务。如上所述,这些服务包括 nginx、python 和 postgres,我们可以根据需要为它们命名。就我而言,我将它们命名为 nginx、web 和 postgres。
- 构建——还记得我们花时间编写的那些 Dockerfile 吗?很好。使用 build 命令,您可以指定每个 Dockerfile 的位置,系统将根据这些文件中的命令构建镜像。
- container_name - 这将容器命名为您指定一次的名称,容器即可启动并运行。
- 卷——这是一种在 Docker 容器和主机之间共享数据的方式。即使 Docker 容器被销毁并重新创建,卷也能确保数据的持久性,因为这种情况你会经常遇到。有关卷及其使用方法的更多信息,请参阅这篇文章。
- ports - 这是为了指定 docker 容器中的哪些端口映射到主机,以 nginx 服务为例,容器的 80 端口映射到主机的 1221 端口。
- 暴露端口 - 暴露端口可使链接服务访问该端口,但主机无法访问该端口。
- 重启 - 指定容器在意外关闭时的行为
- 命令 - 指示容器在启动前要运行哪些命令,在这种情况下,Web 服务中的链式命令用于检查数据库的变化并将 Web 服务绑定到端口 8080。
5. 最后步骤
现在构建镜像只需运行以下命令即可。
docker-compose build
由于基础镜像文件需要从本地下载(如果您本地没有这些镜像文件),因此构建过程可能需要几分钟时间。
要启动各种服务容器,只需运行
docker-compose up
或者,如果您想指定在同一个目录中存在多个 docker-compose 文件时要运行哪个 compose 文件。
docker-compose -f filename.yml up
免责声明:请务必在 Django 的 settings.py 文件中将 Debug 设置为 False,并设置允许的主机名,以反映您将使用的域名或 IP 地址。
此外,请将 Django 默认的 sqlite3 数据库更改为我们在 postgres 服务环境变量部分指定的数据库和用户名,
如下所示。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'mydb',
'USER': 'myuser',
'PASSWORD': 'mypassword',
'HOST': 'postgres',
'PORT': 5432,
}
}
就这样。
要查看运行中的网站,请运行
- localhost:1221
- virtual-box-machine-ip:1221(适用于使用 docker-toolbox 的用户)
如果您想停止容器运行,
docker-compose stop
启动已停止的容器
docker-compose start
销毁容器
docker-compose down
您修改了 Docker 文件,需要应用这些更改。
docker-compose down && docker-compose build && docker-compose up
现在,要让网站在网络上运行,只需在本地机器的 nginx(或 apache)服务器上创建一个配置文件,并将其指向运行 Django 应用的 Docker 容器即可。在本例中,您需要将其指向 nginx 容器。127.0.0.1
:1221
要获取 Docker 常用命令列表,请阅读这篇简明扼要的文章。
对于 Laravel 开发者来说,
这里有一些关于 Docker 的入门知识。
非常感谢您抽出时间阅读,希望这篇文章对您有所帮助。如果您想了解更多此类内容,欢迎随时与我联系。
别忘了点赞、分享和订阅。如果您还有什么想补充的,请在下方留言。
谢谢。
文章来源:https://dev.to/lewiskori/deploying-a-python-django-application-using-docker-3d09