用 Docker 部署一个带 MySQL 的 Python 留言板
·
快速导航
- 1.引言
- 2.准备工作
- 3.步骤1:创建 MySQL 容器(搭建数据库)
- 4.步骤2:准备 Python 留言板应用
- 5.步骤3:构建 Python 应用镜像
- 6.步骤4:启动 Python 应用容器(连接 MySQL)
- 7.步骤5:验证应用功能与数据持久化
引言
一个简单的网页应用(Python 写的)
用户可以提交留言,数据存到 MySQL 数据库里,
即使删除容器,留言也不会丢失(靠 volume 持久化)。
准备工作
用到两个容器,一个是mysql容器,用于存储留言数据,需要用volume持久化数据(避免删容器丢数据)
一个是python容器(自己编写dockerfile)运行网页程序,需要连接MySQL容器,读取/写入留言
步骤1:创建 MySQL 容器(搭建数据库)
#创建一个专门存MySQL数据的卷
docker volume create mysql-data
启动MySQL容器
docker run -d \
--name mymysql \
-e MYSQL_ROOT_PASSWORD=123456 \
-e MYSQL_DATABASE=message_board \
-v mysql-data:/var/lib/mysql \
-p 3306:3306 \
mysql:5.7
#数据库持久化:用 docker volume create 创建命名卷,
#挂载到 MySQL 的/var/lib/mysql(这是 MySQL 存储数据的默认目录),
#确保容器删除后数据不丢。
验证 MySQL 是否启动成功
docker logs mymysql
步骤2:准备 Python 留言板应用(简单的python代码,基于flask框架)
在本地创建应用目录并写代码
# 创建存放应用代码的目录
mkdir -p /root/message-board
cd /root/message-board
创建一个 Python 文件(app.py),功能是:显示留言表单→提交后存到 MySQL→展示所有留言
cat > app.py << 'EOF'
from flask import Flask, request, render_template_string, redirect, url_for
import pymysql
import os
app = Flask(__name__)
# 从环境变量获取MySQL连接信息
db_host = os.getenv('DB_HOST', 'mymysql')
db_user = os.getenv('DB_USER', 'root')
db_password = os.getenv('DB_PASSWORD', '123456')
db_name = os.getenv('DB_NAME', 'message_board')
# 初始化数据库,创建留言表(如果不存在)
def init_db():
conn = pymysql.connect(host=db_host, user=db_user, password=db_password, db=db_name)
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS messages (
id INT AUTO_INCREMENT PRIMARY KEY,
content TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')
conn.commit()
conn.close()
# 首页:处理留言提交和展示
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
# 获取表单提交的留言内容
content = request.form.get('content')
if content: # 确保内容不为空
# 连接数据库并插入留言
conn = pymysql.connect(host=db_host, user=db_user, password=db_password, db=db_name)
cursor = conn.cursor()
cursor.execute('INSERT INTO messages (content) VALUES (%s)', (content,))
conn.commit()
conn.close()
# 提交后重定向到首页(避免刷新重复提交)
return redirect(url_for('index'))
# 读取所有历史留言
conn = pymysql.connect(host=db_host, user=db_user, password=db_password, db=db_name)
cursor = conn.cursor()
cursor.execute('SELECT content, created_at FROM messages ORDER BY created_at DESC')
messages = cursor.fetchall()
conn.close()
# 渲染网页
return render_template_string('''
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>留言板</title>
</head>
<body>
<h1>留言板</h1>
<form method="POST">
<textarea name="content" rows="3" cols="50" placeholder="请输入留言..."></textarea><br>
<button type="submit">提交</button>
</form>
<hr>
<h3>历史留言</h3>
{% for msg in messages %}
<p>{{ msg[1] }}:{{ msg[0] }}</p>
{% endfor %}
</body>
</html>
''', messages=messages)
if __name__ == '__main__':
init_db() # 启动时初始化数据库
app.run(host='0.0.0.0', port=5000) # 允许外部访问
EOF
创建依赖文件(告诉 Python 需要安装哪些库)
cat > requirements.txt << 'EOF'
flask==2.0.1
werkzeug==2.0.3 # 新增这行,指定兼容版本
pymysql==1.0.2
EOF
步骤3:构建 Python 应用镜像
自定义镜像:用 Dockerfile 把应用代码和依赖打包成镜像,实现 “一次构建,到处运行”。
cat > Dockerfile << 'EOF'
# 基础镜像:Python 3.9
FROM python:3.9-slim
# 设置工作目录
WORKDIR /app
# 复制依赖文件并安装
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 复制应用代码
COPY app.py .
# 暴露应用端口(Flask默认5000)
EXPOSE 5000
# 启动命令
CMD ["python", "app.py"]
EOF
构建镜像
# 在/root/message-board目录下执行,构建一个叫message-app的镜像
docker build -t message-app:v1 .
步骤4:启动 Python 应用容器(连接 MySQL)
docker run -d \
--name myapp \
-p 5000:5000 \
-e DB_HOST=mymysql \
-e DB_PASSWORD=123456 \
-e DB_NAME=message_board \
--link mymysql:mymysql \
message-app:v1
说明:
docker run -d \
--name myapp \ # 容器名
-p 5000:5000 \ # 端口映射(主机5000→容器5000)
# 环境变量:告诉应用如何连接MySQL(和前面MySQL的配置对应)
-e DB_HOST=mymysql \ # 数据库主机名=MySQL容器名(Docker内部可直接用容器名通信)
-e DB_PASSWORD=123456 \
-e DB_NAME=message_board \
--link mymysql:mymysql \ # 链接到MySQL容器(让两个容器在同一网络)
message-app:v1 # 用刚才构建的镜像
步骤5:验证应用功能与数据持久化
访问 服务器IP:5000,会看到一个留言板页面,输入一条留言hello提交:
测试数据持久化:
# 删掉应用容器再重建(模拟容器故障)
docker rm -f myapp
# 重新启动应用容器(新容器,但数据还是旧数据,验证数据一致性)
docker run -d --name myapp -p 5000:5000 -e DB_HOST=mymysql -e DB_PASSWORD=123456 -e DB_NAME=message_board --link mymysql:mymysql message-app:v1
再次刷新页面,发现数据还在:

因为数据存在 MySQL 的 volume 里,没丢
说明数据确实通过 MySQL 的命名卷持久化了
更多推荐

所有评论(0)