用 Docker 部署一个带 MySQL 的小站:从 0 到 可访问

3162 字
16 分钟
用 Docker 部署一个带 MySQL 的小站:从 0 到 可访问

这篇文章是写给未来自己的 Docker + MySQL 部署速记,用尽量直白的方式把从安装 Docker 到应用连上数据库这一整套流程走一遍。

一、为什么要用 Docker 跑 MySQL?#

在本地或服务器上安装 MySQL,有几种常见方式:

  • 直接在系统里安装(apt install mysql-server、安装包下一路下一步等)
  • 用各种图形化软件自带的数据库(比如某些集成环境)
  • 用 Docker 拉一个 MySQL 容器跑起来(可以理解成在一台“虚拟小机器”里跑 MySQL)

我更倾向于用 Docker,主要有几个原因:

  • 环境干净:不用在系统里装一堆服务,删起来也干净。
  • 版本可控:想用哪个 MySQL 版本在 docker pull mysql:8.0 里写清楚就行。
  • 迁移简单:换一台机器,只要装好 Docker,命令一跑环境就起来了。
  • 和应用解耦:应用挂了、数据库挂了都是独立的,互不污染。

后文会从“什么都没有”的状态开始,依次完成:

  1. Docker 安装好
  2. MySQL 容器跑起来
  3. 数据能够持久化(重启容器不丢)
  4. 应用(或者本地工具)能连上这个 MySQL。

做到这四步,基本就能支撑一个小项目的数据库需求。

二、准备工作:安装 Docker#

1. Windows / macOS#

如果你用的是 Windows 10/11 或 macOS,最省心的方法是直接装 Docker Desktop(以 Windows 为例):

  1. 打开浏览器,搜索 “Docker Desktop Windows 2026”
  2. 在官方页面下载安装包(注意是 docker.com 相关域名)
  3. 安装时基本一路下一步,安装完成后重启电脑
  4. 打开 Docker Desktop,等它状态变成 Running 或者小鲸鱼图标稳定

安装完成后,打开终端(PowerShell / Terminal),执行:

Terminal window
docker version
docker info

能看到版本信息就说明安装成功。

2. Linux#

Linux 发行版比较多,这里以常见的 Debian / Ubuntu 系为例:

Terminal window
sudo apt update
sudo apt install ca-certificates curl gnupg -y
# 添加 Docker 官方 GPG key 和源(略去具体细节)
# 安装 Docker Engine
sudo apt install docker-ce docker-ce-cli containerd.io -y
sudo systemctl enable docker
sudo systemctl start docker

安装完成后同样用 docker version 确认即可。

三、用 Docker 拉起一个 MySQL 容器#

1. 拉取 MySQL 镜像#

先拉一个 MySQL 8 的官方镜像:

Terminal window
docker pull mysql:8.0

拉取完成后,可以用:

Terminal window
docker images

看到类似 mysql 8.0 ... 的一行就说明拉取成功。

2. 第一次运行 MySQL 容器(最简单版本)#

下面是一个最小可运行的示例命令:

Terminal window
docker run --name my-mysql \
-e MYSQL_ROOT_PASSWORD=your_root_password \
-p 3306:3306 \
-d mysql:8.0

参数解释:

  • --name my-mysql:给容器取个名字,后面好操作。
  • -e MYSQL_ROOT_PASSWORD=...:设置 root 用户密码,这是必须的。
  • -p 3306:3306:把宿主机的 3306 端口映射到容器的 3306 端口,便于外部连接。
  • -d:后台运行。
  • mysql:8.0:使用刚才拉下来的 MySQL 8.0 镜像。

启动之后,用:

Terminal window
docker ps

看到 my-mysql 处于 Up 状态,就说明 MySQL 已经在容器里跑起来了。

不过,这个最简单版本没有数据持久化,也只有 root 账户,离生产环境还差一截,下面来补全。

四、给 MySQL 加上数据卷:防止数据丢失#

在 Docker 的世界里,有一个非常重要的概念叫 volume(数据卷),用来把容器内部的数据映射 / 挂载到宿主机,可以粗略理解成“专门留给容器用的一块硬盘区域”。这样,即使容器被删掉,只要卷还在,数据就还在。

MySQL 容器默认会把数据写到 /var/lib/mysql 目录,我们要做的,就是把这个目录挂载到宿主机上的一个真实文件夹。

1. 创建一个数据目录#

比如在宿主机上先创建一个目录:

Terminal window
mkdir -p ~/docker-data/mysql

Windows 下可以用类似:

Terminal window
mkdir C:\docker-data\mysql

2. 用数据卷重新运行 MySQL#

如果之前已经启动过一个名为 my-mysql 的容器,建议先把它停掉并删除:

Terminal window
docker stop my-mysql
docker rm my-mysql

然后用挂载卷的方式重新跑:

Terminal window
docker run --name my-mysql \
-e MYSQL_ROOT_PASSWORD=your_root_password \
-e MYSQL_DATABASE=app_db \
-e MYSQL_USER=app_user \
-e MYSQL_PASSWORD=app_user_password \
-v ~/docker-data/mysql:/var/lib/mysql \
-p 3306:3306 \
-d mysql:8.0

在这个命令里,我们比之前多做了几件事:

  • -v ~/docker-data/mysql:/var/lib/mysql:把容器的 /var/lib/mysql 挂到宿主机目录,实现数据持久化。
  • -e MYSQL_DATABASE=app_db:启动时自动创建一个名为 app_db 的数据库。
  • -e MYSQL_USER=app_user + -e MYSQL_PASSWORD=...:自动创建一个普通用户,适合作为应用连接使用。

这样一来,即使你把 my-mysql 这个容器删了,再用同样的数据卷重新启动一个新的 MySQL 容器,之前的表和数据也都还在。

五、进入容器里看一眼 MySQL#

要直接在容器里执行几条 SQL、确认数据库是否正常工作,可以进入容器内部:

Terminal window
docker exec -it my-mysql bash

进入容器后,使用 MySQL 自带的命令行客户端:

Terminal window
mysql -u root -p

输入刚才设置的 MYSQL_ROOT_PASSWORD,登录成功后就能看到熟悉的 MySQL 提示符。

可以简单测一下:

SHOW DATABASES;
USE app_db;
CREATE TABLE test (
id INT PRIMARY KEY AUTO_INCREMENT,
content VARCHAR(255)
);
INSERT INTO test (content) VALUES ('hello docker mysql');
SELECT * FROM test;

确认没问题后,输入:

Terminal window
exit
exit

第一次是退出 MySQL,第二次是退出容器的 shell。

六、从宿主机或开发工具连接这个 MySQL#

现在 MySQL 容器已经把 3306 端口映射到了宿主机,可以直接用各种工具连上去:

  • 数据库可视化工具:如 Navicat、TablePlus、DBeaver 等
  • 应用程序:Node.js、Java、Go、Python 等后端服务

假设你的 Docker 跑在本机上,连接信息大致如下:

  • 主机(Host)127.0.0.1localhost
  • 端口(Port)3306
  • 用户名(User)app_user
  • 密码(Password)app_user_password
  • 数据库名(Database)app_db

在可视化工具里把这些填上,测试连接通过即可开始用 GUI 管理表和数据。

如果是 Node.js 应用,可以用 mysql2 举个简单例子:

Terminal window
npm install mysql2
import mysql from "mysql2/promise";
const pool = mysql.createPool({
host: "127.0.0.1",
port: 3306,
user: "app_user",
password: "app_user_password",
database: "app_db",
});
async function testConnection() {
const [rows] = await pool.query("SELECT NOW() as now");
console.log(rows);
}
testConnection().catch(console.error);

只要控制台里能打印出当前时间,说明和 Docker 里的 MySQL 已经连通了。

七、用 docker-compose 管理 MySQL(以及未来的应用)#

如果只部署一个 MySQL,用 docker run 还算简单。但一旦出现:

  • 应用容器
  • 数据库容器
  • 可能还有 Redis、Nginx 等

命令一多就很难维护,这时可以用 docker-compose 统一管理。

1. 写一个最简单的 docker-compose.yml#

在你的项目根目录(或者专门的部署目录)创建一个名为 docker-compose.yml 的文件:

version: "3.9"
services:
mysql:
image: mysql:8.0
container_name: my-mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: your_root_password
MYSQL_DATABASE: app_db
MYSQL_USER: app_user
MYSQL_PASSWORD: app_user_password
ports:
- "3306:3306"
volumes:
- ./mysql-data:/var/lib/mysql
command:
- --default-authentication-plugin=mysql_native_password
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci

相较于直接使用命令行,这里做了几件事:

  • 把之前命令行里的参数转成 YAML 配置,清晰可读。
  • 增加了 restart: always,让容器在服务重启后自动拉起。
  • ./mysql-data 做数据卷,方便和项目一起管理。
  • 通过 command 显式设置字符集,为中文内容存储打好基础。

在这个 docker-compose.yml 同级目录下运行:

Terminal window
docker compose up -d

容器就会按照配置自动创建并启动。

查看状态:

Terminal window
docker compose ps

如果要停止服务,可以执行:

Terminal window
docker compose down

注意:默认 down 不会删掉卷里的数据(除非你加了 -v)。

2. 把你的应用也写进 compose#

以后如果你的项目也用 Docker 方式部署,可以直接在 services 下面再加一个服务:

app:
build: .
container_name: my-app
depends_on:
- mysql
environment:
DB_HOST: mysql
DB_PORT: 3306
DB_USER: app_user
DB_PASSWORD: app_user_password
DB_NAME: app_db
ports:
- "8080:8080"

这里有一个关键点需要注意:

  • 在同一个 docker-compose 网络里,服务之间可以通过 服务名 互相访问,所以 DB_HOST 不再是 127.0.0.1,而是 mysql

以后要启动整套服务,只需要一句命令:

Terminal window
docker compose up -d

八、几件容易踩坑但很关键的小事#

1. 端口被占用#

如果你启动容器时报错类似 “Bind for 0.0.0.0:3306 failed: port is already allocated”,说明本机 3306 已经被其他程序占用。

大致的解决思路:

  • 查一下是谁占用了 3306(Windows 下可以用资源监视器,Linux 用 lsof -i:3306 等)。
  • 停掉本机自带的 MySQL 服务,完全改用 Docker 里的。
  • 或者在 Docker 这边改一个宿主机端口,比如:
ports:
- "3307:3306"

连接时用宿主机端口 3307 即可。

2. 权限/读写问题#

在 Linux 上,如果你把数据卷挂到某些权限控制比较严格的目录,有时候会遇到读写权限问题,导致 MySQL 启不起来。

比较通用的经验做法:

  • 用普通用户有权限的目录,比如 /home/youruser/docker-data/mysql
  • 或者为该目录设置合适的权限:
Terminal window
sudo chown -R youruser:youruser /home/youruser/docker-data/mysql

3. 字符集和乱码#

如果你要存中文内容,一定记得把 MySQL 的字符集设成 utf8mb4,否则可能会出现一些隐蔽问题,比如:

  • 表创建时默认不是 utf8mb4
  • 表情符号/部分字符插入失败

docker-compose 的方式,可以统一在 command 里配置:

command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci

已经创建的表,如果字符集不对,可以后续用 ALTER TABLE 改。

九、简单回顾:从 0 到 可以用#

最后简单整理一下本文做的事情:

  1. 安装 Docker / Docker Desktop,让机器具备跑容器的能力。
  2. 拉取 MySQL 官方镜像:docker pull mysql:8.0
  3. docker run 启动一个 MySQL 容器,确认可以运行。
  4. 给 MySQL 挂上卷,把 /var/lib/mysql 映射到宿主机目录,实现数据持久化。
  5. 通过 docker exec 进入容器,直接在 MySQL 里创建数据库和表,确认一切正常。
  6. 从宿主机或者应用代码里,使用正确的主机、端口和账号连接到容器里的 MySQL。
  7. docker-compose 把配置写进一个文件里,以后一句命令就能启动完整的服务。

目的只是保留一套自己踩过坑之后沉淀出来的流程,方便以后再部署带 MySQL 的小项目时少查文档、少走弯路,也希望能顺便帮你省点试错时间。

十、如果要放到真正的服务器上,我会怎么做?#

最后补充一点更贴近“上线”的思路,给整篇笔记收个尾,也方便以后自己查阅。

  1. 先在本地把 docker-compose 跑顺。
    所有服务(应用、MySQL、缓存、Nginx 等)都写在一个 docker-compose.yml 里,确保在本地一句 docker compose up -d 就能跑起来,并且各个服务之间的网络配置是正确的。

  2. 服务器上只做三件事:装 Docker、拉代码、改配置。

    • 安装 Docker / Docker Compose(新版本已经合并成 docker compose)。
    • 从 Git 仓库把项目拉到服务器上。
    • 根据服务器环境,调整 .envdocker-compose.yml 里的少量配置(比如端口、域名、密码)。
  3. 把所有敏感信息挪到环境变量或 .env 文件里。
    开发阶段可能直接把 MYSQL_ROOT_PASSWORDDB_PASSWORD 写在 docker-compose.yml 里,上服务器之后更推荐的做法是:

    • 新建 .env 文件(不要提交到 Git 仓库)。
    • 把密码、密钥、连接串等写到 .env 里。
    • docker-compose.yml 里用 ${VAR_NAME} 的形式引用。
  4. 做好备份和监控的最低配置。
    即使用的是 Docker 里的 MySQL,也一定要定期备份数据,比如:

    • 写一个简单的备份脚本,用 mysqldump 把数据导出到宿主机目录。
    • 再配合 crontab,让它每天/每周自动执行一次。
    • 最起码在重要更新前,手动备份一份,这一步永远不会多余。
  5. 用 Nginx(或其他反向代理)把流量引到应用容器。
    当你的应用也跑在 Docker 里时,可以:

    • 用另一个 Nginx 容器做反向代理,通过域名访问。
    • 或者用宿主机上的 Nginx 转发请求到 Docker 网络里的应用容器。
    • MySQL 通常不会直接对公网开放,而是只允许应用容器访问,或者只对特定的 IP 段开放。
  6. 保留一份“最小可用”的部署文档。
    本文其实已经是一个雏形,但你可以在自己的仓库里再写一份更贴近你项目的 README:

    • 如何在新机器上从零开始部署。
    • 所有需要的环境变量列表。
    • 常见错误(比如端口冲突、权限问题)以及解决方式。

当这些东西都跑通之后,再看 Docker + MySQL 部署,你可能会发现它不再是一个“神秘的黑盒”,而只是你工具箱里一套相对顺手的流程而已。等未来你要再加上 Redis、消息队列,甚至是整套 CI/CD,只需要在现在这套基础上继续往前“加一层楼”就行了。

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或赞助支持!

赞助
用 Docker 部署一个带 MySQL 的小站:从 0 到 可访问
https://firefly.cuteleaf.cn/posts/docker-mysql-deploy/
作者
Airio_
发布于
2026-02-26
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
Airio_
Hello, I'm Airio_.
公告
欢迎来到OfoCa Space。
音乐
封面

音乐

暂未播放

0:00 0:00
暂无歌词
分类
标签
站点统计
文章
6
分类
1
标签
16
总字数
18,733
运行时长
0
最后活动
0 天前

目录