【Docker实战】将Django应用容器化的完整指南

发布于:2025-08-11 ⋅ 阅读:(19) ⋅ 点赞:(0)

Docker实战:将Django应用容器化的完整指南

本文将带你从零开始,一步步将Django应用容器化,包括Dockerfile编写、镜像优化和容器部署的完整流程。

一、Dockerfile核心指令快速掌握

Dockerfile是构建镜像的"食谱",包含了一系列构建指令。在开始实战前,我们先掌握这些最常用的核心指令:

指令 作用说明 实战价值
FROM 指定基础镜像(必须是第一条指令) 站在巨人的肩膀上,无需从零构建操作系统环境
WORKDIR 设置工作目录(后续命令的执行目录) 避免使用复杂的绝对路径,让Dockerfile更清晰
COPY 复制本地文件到镜像中 将应用代码和配置文件打包到镜像
RUN 执行命令(构建镜像时运行) 安装依赖、编译代码等构建阶段操作
ENV 设置环境变量 配置应用运行参数,避免硬编码敏感信息
EXPOSE 声明容器运行时监听的端口 文档化端口信息,提醒使用者需要映射的端口
CMD 容器启动命令(可被docker run参数覆盖) 定义应用的启动方式
ENTRYPOINT 容器入口点(不可被覆盖,常与CMD配合) 固定应用的启动流程,仅动态参数通过CMD传递

小贴士:COPYADD的区别:COPY仅用于复制本地文件,ADD还支持URL下载和自动解压压缩包。实际开发中,优先使用COPY,它更直观且避免意外行为。

二、Django应用容器化实战步骤

我们以一个典型的Django博客应用为例,演示完整的容器化过程。

2.1 项目结构准备

首先确保你的Django项目结构如下(关键文件必须包含):

myblog/
├── Dockerfile          # 核心构建文件
├── requirements.txt    # Python依赖列表
├── run.sh              # 应用启动脚本
├── myblog.conf         # Nginx配置文件
└── 其他Django项目文件  # 包括manage.py、应用代码等

其中几个关键文件的内容参考:

requirements.txt(列出项目依赖):

Django==3.2.16
djangorestframework==3.13.1
pymysql==1.0.2
uwsgi==2.0.21

run.sh(启动脚本,负责启动Nginx和uWSGI):

#!/bin/bash
# 启动Nginx
nginx
# 启动uWSGI服务
uwsgi --ini uwsgi.ini

2.2 编写基础Dockerfile

创建Dockerfile文件,逐步构建我们的镜像:

# 1. 选择基础镜像(CentOS 7.5,稳定性好)
FROM centos:centos7.5.1804

# 2. 设置维护者信息(可选,但推荐)
LABEL maintainer="your_email@example.com"

# 3. 配置环境变量(解决中文乱码等问题)
ENV LANG en_US.UTF-8
ENV LC_ALL en_US.UTF-8

# 4. 配置国内YUM源(加速依赖安装)
RUN curl -so /etc/yum.repos.d/Centos-7.repo http://mirrors.aliyun.com/repo/Centos-7.repo

# 5. 安装系统依赖(Python3、编译工具等)
RUN yum install -y python36 python3-devel gcc pcre-devel zlib-devel make net-tools

# 6. 设置工作目录(后续命令将在此目录执行)
WORKDIR /opt/myblog

# 7. 复制项目文件到镜像中
COPY . .

# 8. 安装Nginx(从源码编译,可指定版本)
RUN tar -zxf nginx-1.13.7.tar.gz -C /opt && \
    cd /opt/nginx-1.13.7 && \
    ./configure --prefix=/usr/local/nginx && \
    make && make install && \
    ln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx  # 创建软链接方便调用

# 9. 配置Nginx(复制应用专属配置)
RUN cp myblog.conf /usr/local/nginx/conf/myblog.conf

# 10. 安装Python依赖(使用阿里云PyPI镜像加速)
RUN pip3 install -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com -r requirements.txt

# 11. 赋予启动脚本执行权限,并清理缓存
RUN chmod +x run.sh && rm -rf ~/.cache/pip

# 12. 声明应用监听端口
EXPOSE 8002

# 13. 容器启动命令(执行启动脚本)
CMD ["./run.sh"]

关键说明:

  • 选择centos7.5.1804而非latest,是为了保证构建环境的一致性
  • 所有RUN命令尽量合并成一行(用&&连接),可以减少镜像层数
  • 安装依赖时使用国内镜像源(阿里云),大幅提升构建速度
  • 最后清理缓存(rm -rf ~/.cache/pip),减小镜像体积

2.3 构建并测试镜像

镜像编写完成后,执行以下命令构建:

# 构建镜像(-t指定名称和标签,.表示当前目录为构建上下文)
docker build . -t myblog:v1

# 查看构建好的镜像
docker images | grep myblog
# 预期输出:myblog   v1    xxxxxxxxxx   2 minutes ago   890MB

构建成功后,我们需要先启动依赖的MySQL容器,再启动Django应用:

# 1. 启动MySQL容器(数据持久化到宿主机/opt/mysql/mysql-data目录)
docker run -d -p 3306:3306 --name mysql \
  -v /opt/mysql/mysql-data/:/var/lib/mysql \
  -e MYSQL_DATABASE=myblog \
  -e MYSQL_ROOT_PASSWORD=123456 \
  mysql:5.7

# 2. 启动Django应用容器(连接到MySQL)
docker run -d -p 8002:8002 --name myblog \
  -e MYSQL_HOST=172.17.0.2  # 替换为实际的MySQL容器IP或使用--link
  -e MYSQL_USER=root \
  -e MYSQL_PASSWD=123456 \
  myblog:v1

# 3. 查看容器运行状态
docker ps | grep -E "mysql|myblog"

连接数据库技巧:在生产环境中,更推荐使用Docker网络(--network)让容器通过服务名通信,而不是硬编码IP。例如:

# 创建自定义网络
docker network create my-network
# 启动MySQL时加入网络
docker run ... --network my-network --name mysql ...
# 启动应用时加入同一网络,直接用mysql作为主机名
docker run ... --network my-network -e MYSQL_HOST=mysql ...

最后执行数据库迁移并创建管理员用户:

# 执行数据库迁移
docker exec -ti myblog python3 manage.py migrate

# 创建超级用户(按提示输入用户名、邮箱、密码)
docker exec -ti myblog python3 manage.py createsuperuser

现在访问宿主机的8002端口,就能看到你的Django应用了!

三、镜像优化:更小、更快、更高效

上面的基础镜像可以工作,但还有优化空间。主要问题是:每次代码修改都要重新安装所有依赖,构建速度慢;镜像体积较大(接近1GB)。

3.1 优化思路:提取基础镜像

将不常变化的部分(系统依赖、Nginx、Python环境)构建成基础镜像,应用代码和依赖作为上层镜像,这样每次代码更新时,只需重新构建上层镜像。

创建基础镜像的Dockerfile(Dockerfile-base):

FROM centos:centos7.5.1804

LABEL maintainer="your_email@example.com"

ENV LANG en_US.UTF-8
ENV LC_ALL en_US.UTF-8

# 配置YUM源并安装系统依赖
RUN curl -so /etc/yum.repos.d/Centos-7.repo http://mirrors.aliyun.com/repo/Centos-7.repo && \
    yum install -y python36 python3-devel gcc pcre-devel zlib-devel make net-tools

# 提前下载Nginx源码包(避免每次构建重新下载)
COPY nginx-1.13.7.tar.gz /opt/

# 安装Nginx
RUN tar -zxf /opt/nginx-1.13.7.tar.gz -C /opt && \
    cd /opt/nginx-1.13.7 && \
    ./configure --prefix=/usr/local/nginx && \
    make && make install && \
    ln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx && \
    rm -f /opt/nginx-1.13.7.tar.gz  # 清理安装包

构建基础镜像:

docker build -f Dockerfile-base -t centos-django-base:v1 .

3.2 基于基础镜像构建应用镜像

创建应用镜像的Dockerfile(Dockerfile-app):

# 基于我们构建的基础镜像
FROM centos-django-base:v1

WORKDIR /opt/myblog

# 先复制requirements.txt并安装依赖(利用Docker缓存)
COPY requirements.txt .
RUN pip3 install -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com -r requirements.txt && \
    rm -rf ~/.cache/pip

# 再复制其他项目文件(代码变动频繁,放在后面不破坏前面的缓存)
COPY . .

# 配置Nginx
RUN cp myblog.conf /usr/local/nginx/conf/myblog.conf

# 赋予执行权限
RUN chmod +x run.sh

EXPOSE 8002

CMD ["./run.sh"]

关键优化点:

  1. 先复制requirements.txt并安装依赖,只有依赖变化时才会重新执行这一步
  2. 最后复制应用代码,代码修改不会影响前面步骤的缓存
  3. 基础镜像只需构建一次,后续构建应用镜像速度提升50%以上

构建优化后的应用镜像:

docker build -f Dockerfile-app -t myblog:v2 .

对比优化前后的效果:

  • 构建时间:从5分钟缩短到1分钟(代码修改时)
  • 镜像体积:从890MB减小到650MB(去除重复的基础组件)

四、总结与最佳实践

总结几个关键经验:

  1. Dockerfile编写原则

    • 指令顺序:从少变到多变(利用缓存)
    • 合并命令:减少镜像层数(用&&\换行)
    • 清理冗余:每次安装后清理缓存和临时文件
  2. 生产环境建议

    • 不要使用latest标签,固定具体版本(如centos:7.5.1804
    • 避免在镜像中存储敏感信息,通过环境变量或Docker Secrets注入
    • 以非root用户运行容器(在Dockerfile中添加USER指令)

网站公告

今日签到

点亮在社区的每一天
去签到