Docker环境下MariaDB数据插入及数据库变更持久化问题
Docker LAMP环境数据插入与数据库结构保存问题解决
背景
刚接触Docker,此前使用Vagrant开发,因资源占用过高转而搭建Docker版LAMP(Linux、Apache、MariaDB、PHP)环境,但测试注册功能时数据无法插入数据库,现求助两个问题:
- 如何实现数据插入到MariaDB?
- 如何保存数据库结构变更,以便后续开发使用?
现有配置
docker-compose.yml
services: foo_php: build: . volumes: - ./src:/var/www/html ports: - 9002:80 foo_db: image: mariadb:latest restart: always environment: MARIADB_ROOT_PASSWORD: Password1234 MYSQL_ROOT_HOST: '%' volumes: - ./mariadb:/var/lib/mysql phpmyadmin: image: phpmyadmin:latest restart: always ports: - 9003:80 environment: - PMA_ARBITRARY=1
Dockerfile
FROM php:8.3-apache MAINTAINER Senior Moe <m.kh.alnahdi@gmail.com> WORKDIR /var/www/html RUN apt update -y && apt upgrade -y && apt install libmariadb-dev -y USER root RUN sed -i -e "/^bind-address/d" /etc/mysql/my.cnf RUN docker-php-ext-install mysqli
注册页面PHP代码(已精简验证逻辑)
<?php include_once "connection_db.php"; if(isset($_POST['your_name']) && isset($_POST['your_email']) && isset($_POST['your_passwrd']) && isset($_POST['repeat_passwrd']) ){ function validation($input){ $input = trim($input); $input = stripslashes($input); $input = htmlspecialchars($input); return $input; } $username = validation($_POST['your_name']); $user_email = validation($_POST['your_email']); $user_password = validation($_POST['your_passwrd']); $repeat = validation($_POST['repeat_passwrd']); $check_query = "SELECT * FROM users WHERE user_email='$user_email'"; $result_check = mysqli_query($connection, $check_query); if(mysqli_num_rows($result_check) === 1 ){ header("Location: ../index.php?registererror=The Email already exist"); exit(); }else{ $hashed_password = password_hash($user_password, PASSWORD_DEFAULT); $record_db = $connection->prepare("INSERT INTO users (username, user_email, user_password) VALUES (?,?,?)"); $record_db->bind_param("sss",$username, $user_email, $user_password); header("Location: ../index.php?status=User Registe Seccessfully!"); exit(); } }else{ header("Location: ../index.php"); exit(); }
数据库连接代码
<?php $server_db = [ "server_name" => "foo_db", "server_user" => "root" , "server_passwd" => "Password1234", "database_name" => "FOO_DB" ]; $connection = mysqli_connect($server_db['server_name'],$server_db['server_user'],$server_db['server_passwd'],$server_db['database_name']); if(!$connection){ echo "connection faild!"; }
解决方案
问题1:实现数据插入到MariaDB
1. 修复PHP代码核心错误
你的注册代码存在几个关键问题,导致数据无法插入:
- 未执行预处理语句:调用
prepare()和bind_param()后,缺少execute()方法执行插入操作 - 使用明文密码而非哈希值:已经生成了
$hashed_password,但绑定参数时用了原密码$user_password - 缺少错误处理:未检查数据库查询、预处理语句是否执行成功,难以定位问题
- 拼写错误:提示信息里的
Registe应为Registered,Seccessfully应为Successfully
修正后的代码片段:
else{ $hashed_password = password_hash($user_password, PASSWORD_DEFAULT); // 检查预处理语句是否创建成功 $record_db = $connection->prepare("INSERT INTO users (username, user_email, user_password) VALUES (?,?,?)"); if (!$record_db) { die("Prepare failed: " . $connection->error); } // 绑定哈希后的密码 $record_db->bind_param("sss",$username, $user_email, $hashed_password); // 执行插入操作 if ($record_db->execute()) { header("Location: ../index.php?status=User Registered Successfully!"); } else { die("Insert failed: " . $record_db->error); } $record_db->close(); exit(); }
同时,给邮箱检查逻辑添加错误处理:
$result_check = mysqli_query($connection, $check_query); if (!$result_check) { die("Check query failed: " . mysqli_error($connection)); }
2. 确认数据库与表结构存在
- 访问
http://localhost:9003打开phpMyAdmin,用用户名root、密码Password1234登录 - 确认
FOO_DB数据库已创建,且users表结构正确,可执行以下SQL创建表:
CREATE TABLE IF NOT EXISTS FOO_DB.users ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(255) NOT NULL, user_email VARCHAR(255) NOT NULL UNIQUE, user_password VARCHAR(255) NOT NULL );
3. 修正Dockerfile无效操作
php:8.3-apache镜像中不存在/etc/mysql/my.cnf(该文件属于MariaDB镜像),删除以下无效行:
RUN sed -i -e "/^bind-address/d" /etc/mysql/my.cnf
问题2:保存数据库结构变更
1. 使用初始化SQL脚本自动初始化
在项目根目录创建initdb文件夹,新建init.sql文件,写入数据库和表的初始化SQL:
CREATE DATABASE IF NOT EXISTS FOO_DB; USE FOO_DB; CREATE TABLE IF NOT EXISTS users ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(255) NOT NULL, user_email VARCHAR(255) NOT NULL UNIQUE, user_password VARCHAR(255) NOT NULL );
修改docker-compose.yml中foo_db服务的volumes,添加初始化脚本挂载:
foo_db: image: mariadb:latest restart: always environment: MARIADB_ROOT_PASSWORD: Password1234 MYSQL_ROOT_HOST: '%' volumes: - ./mariadb:/var/lib/mysql - ./initdb:/docker-entrypoint-initdb.d # 添加这行
MariaDB镜像会在首次启动(数据卷为空时)自动执行/docker-entrypoint-initdb.d目录下的所有.sql脚本,确保数据库结构一致。
2. 定期导出数据库结构
使用mysqldump命令导出仅结构的SQL文件,保存到项目目录中:
docker exec -it $(docker-compose ps -q foo_db) mysqldump -u root -pPassword1234 --no-data FOO_DB > ./db_schema.sql
该命令会导出FOO_DB的表结构(不含数据),方便后续复用或版本控制。
3. 版本控制管理SQL脚本
将初始化脚本、结构变更脚本加入Git等版本控制系统,每次修改数据库结构时更新对应脚本,确保团队成员可以同步最新结构。
内容的提问来源于stack exchange,提问作者Senior-Moe
相关产品推荐
相关产品推荐

