You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker环境下MariaDB数据插入及数据库变更持久化问题

Docker LAMP环境数据插入与数据库结构保存问题解决

背景

刚接触Docker,此前使用Vagrant开发,因资源占用过高转而搭建Docker版LAMP(Linux、Apache、MariaDB、PHP)环境,但测试注册功能时数据无法插入数据库,现求助两个问题:

  1. 如何实现数据插入到MariaDB?
  2. 如何保存数据库结构变更,以便后续开发使用?

现有配置

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 14:37:35