当前位置: 首页 > news >正文

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

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.1804LABEL 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:v1WORKDIR /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.shEXPOSE 8002CMD ["./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指令)
http://www.lryc.cn/news/616153.html

相关文章:

  • 【代码随想录day 15】 力扣 257. 二叉树的所有路径
  • [FOC电机控制] 电压频谱图
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘ray’问题
  • Redis一站式指南一:从MySQL事务到Redis持久化及事务实现
  • 【每天一个知识点】深度领域对抗神经网络
  • MACBOOK M1安装达梦8数据库
  • nginx-主配置文件
  • 异步问题的概念和消除问题技巧
  • 【Tomcat】企业级web应用服务器
  • ATF(TF-A)安全通告 TFV-12(CVE-2024-5660)
  • nestjs官网推荐typeorm而不是prisma的原因
  • 实现MATLAB2024b和M文件关联(防止运行多个MATLAB)
  • 【0基础3ds Max】主工具栏介绍(下)
  • 金融机构在元宇宙中的业务开展与创新路径
  • ATF(TF-A)安全通告 TFV-13(CVE-2024-7881)
  • vue3项目中在一个组件中点击了该组件中的一个按钮,那么如何去触发另一个组件中的事件?
  • RAG (Retrieval-Augmented Generation) 原理详解与实例
  • Stream流应用
  • 工业相机选择规则
  • Java数据结构——LinkedList
  • MariaDB 数据库管理与web服务器
  • JUC学习笔记-----ReentrantLock
  • 通过trae开发你的第一个Chrome扩展插件
  • CST MATLAB 联合仿真超材料开口谐振环单元
  • Pytorch进阶-timm库-00快速开始
  • 数据结构(17)排序(下)
  • Excel常用功能函数
  • 深度相机---双目深度相机
  • CPP多态
  • 信号处理函数中调用printf时,遇到中断为什么容易导致缓冲区损坏?