这是我参与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.7 的 Linux 环境
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 。
运行结果: