Django+MySQL容器化部署实例

314 阅读3分钟

这是我参与8月更文挑战的第12天,活动详情查看:8月更文挑战

Django+MySQL容器化部署

我们在学习面向对象的编程语言时,会想方设法把功能独立的模块给独立出来,方便复用和维护。

容器也是一样的。虽然理论上可以把所有组件塞到同一个容器中去,但更好的做法是各模块在单独容器中,只要保持必要的通信就可以了。

也就是说,本教程中现在需要两个容器了:

● 名称叫 app 的 Django 容器

● 名称叫 db 的 MySQL 容器

所以如何构建 MySQL 镜像?别担心,这么常用的镜像官方已经帮你构建好了,只需要把它从仓库拉取到本地就可以了。

修改上一章写的 docker-compose.yml ,增加 MySQL 容器:

version: "3"
services:
  app:
    restart: always
    build: .
    command: bash start.sh
    volumes:
      - .:/code
    ports:
      - "8888:8888"
    depends_on:
      - db
  db:
    image: mysql:5.6
    volumes:
      - "./mysql:/var/lib/mysql"
    ports:
      - "3307:3306"
    restart: always
    environment:
      - MYSQL_DATABASE=my_django_blog_1
      - MYSQL_ROOT_PASSWORD=root

 app容器的 command指令做了修改,让其在运行前先执行数据迁移;新增了配置 depends_on,意思是此容器需要等待 db容器启动完毕才能够启动。 分析一下新添加的 db容器:

    image:从仓库拉取 MySQL 5.6。最新版本为 MySQL 8,不过很坑的是新版本修改了用户登录的验证方法,导致很容易出现无法通过身份验证的问题。教程为了简单起见选用 5.7 版本。后期会在教程示例代码中添加[mysql-8]()分支并给出操作方法,有兴趣的读者可以查看。
    
    volumes:定义卷(这里实际是挂载),上一章已经讲过了,它实现了宿主机和容器目录的映射。功能是将容器中的 MySQL 数据映射到宿主机。
    
    ports:MySQL 默认通信端口为 3307 。
    
    environment :定义容器的环境变量,设置了 MySQL 的 root 用户的密码、数据库的名称。

这里为什么要用卷?就让数据在容器中、保持隔离不好吗?把数据保存在容器中,理论上确实是可以的,但有一个致命的问题,即数据和容器的生命周期挂钩了:万一哪天手贱把容器给删了,连同里面的数据随风而逝,你就是全公司那个删库跑路的传奇人物了。要知道容器的生命周期可能会非常短暂,删除指令也相当顺滑(docker-compose down)。将数据映射到宿主机,容器即使被删除掉,但数据还是安全的躺在你的服务器中的。换句话说,容器内部非常适合运行无状态的应用;涉及到如数据之类有状态的东西,一定要谨慎思考。

Dockerfile

# 从仓库拉取 带有 python 3.7Linux 环境
FROM python:3.7.0
# 设置 python 环境变量
ENV PYTHONUNBUFFERED 1

# 创建 workspace 文件夹并将其设置为工作目录
RUN mkdir /workspace
WORKDIR /workspace
# 将当前文件夹中的文件和文件夹复制到容器的 workspace 目录
COPY . /workspace
# 安装库
RUN pip install -i https://mirrors.aliyun.com/pypi/simple/ -r requirments.txt
# 容器暴露的端口
EXPOSE 8080

requirements.txt

django==2.2
mysqlclient==1.3.14

settings.py

DB_NAME = 'my_django_blog_1'
DB_USER = 'root'
DB_PASSWORD = 'root'
DB_HOST = '127.0.0.1'
DB_PORT = '3306'

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': DB_NAME,
        'USER': DB_USER,
        'PASSWORD': DB_PASSWORD,
        'HOST': 'db',
        'PORT': DB_PORT
    }
}

注意 HOST 填写的是容器的名称,即 db 。

运行结果: