Docker项目部署上线之MySQL和Redis
前言
前面我们已经完成了 Linux 环境准备,也成功把 Spring Boot 项目打包成 jar 包并运行起来。
但是一个完整的后端项目通常不只有 Spring Boot,还依赖:
- MySQL 数据库
- Redis 缓存
- 文件存储
- Nginx
- 日志目录
如果每个软件都手动安装,配置过程会比较繁琐,而且不同服务器之间容易出现环境差异。
所以这一篇开始学习 Docker,先使用 Docker 部署 MySQL 和 Redis。
本篇主要内容:
- 安装 Docker
- 配置 Docker 镜像源
- 创建项目网络
- Docker 部署 MySQL
- Docker 部署 Redis
- 配置数据持久化
- 测试 MySQL 和 Redis 是否正常
- 总结容器常见问题
一、为什么使用 Docker 部署 MySQL 和 Redis
如果直接在 Linux 上安装 MySQL 和 Redis,通常需要处理:
- 软件版本
- 配置文件
- 用户权限
- 服务启动
- 开机自启
- 数据目录
- 卸载和升级
使用 Docker 后,可以把软件和运行环境封装在容器中。
整体流程变成:
准备 Docker
|
拉取 MySQL 镜像
|
创建 MySQL 容器
|
挂载数据目录
|
拉取 Redis 镜像
|
创建 Redis 容器
|
Spring Boot 通过容器网络访问Docker 的好处主要有:
- 安装过程更统一
- 不污染宿主机环境
- 版本更容易控制
- 容器启动和停止方便
- 数据可以通过 Volume 持久化
- 多个服务可以使用 Docker 网络互相访问
二、安装 Docker
如果服务器上已经安装 Docker,可以先检查版本:
docker --version
查看 Docker 服务状态:
systemctl status docker
如果没有安装,可以根据系统选择安装方式。
三、Ubuntu 安装 Docker
1. 更新软件包
sudo apt-get update
2. 安装基础工具
sudo apt-get install -y ca-certificates curl gnupg
3. 添加 Docker 密钥
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \ | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
设置密钥权限:
sudo chmod a+r /etc/apt/keyrings/docker.gpg
4. 添加 Docker 软件源
echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \ | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
5. 安装 Docker
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
6. 启动 Docker
sudo systemctl enable docker sudo systemctl start docker
查看版本:
docker version
四、CentOS 安装 Docker
如果服务器使用 CentOS,可以执行:
sudo yum install -y yum-utils
添加 Docker 软件源:
sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo
安装 Docker:
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
启动 Docker:
sudo systemctl enable docker sudo systemctl start docker
查看版本:
docker version
文字说明
不同 Linux 发行版的安装命令不一样。
如果服务器是 Ubuntu,主要使用 apt;如果是 CentOS,主要使用 yum。
实际操作前可以先确认系统类型:
cat /etc/os-release
五、配置 Docker 镜像加速
Docker 默认从 Docker Hub 拉取镜像。
如果服务器访问 Docker Hub 较慢,可以配置镜像加速地址。
创建配置目录:
sudo mkdir -p /etc/docker
编辑配置文件:
sudo vim /etc/docker/daemon.json
示例内容:
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://dockerproxy.com"
]
}重启 Docker:
sudo systemctl daemon-reload sudo systemctl restart docker
查看 Docker 信息:
docker info
如果配置生效,可以在输出中看到 Registry Mirrors。
文字说明
镜像加速地址可能会发生变化,实际使用时需要选择当前可用的镜像服务。
如果服务器网络正常,也可以不配置镜像加速。
六、拉取 MySQL 镜像
先查看 Docker 是否可以正常运行:
docker run hello-world
如果输出欢迎信息,说明 Docker 基本正常。
拉取 MySQL 8 镜像:
docker pull mysql:8.0
查看本地镜像:
docker images
示例:
REPOSITORY TAG IMAGE ID CREATED SIZE mysql 8.0 xxxxxxxx 2 weeks ago 600MB
文字说明
这里使用了固定版本:
mysql:8.0
不建议直接使用:
mysql:latest
因为 latest 可能随着时间变化,导致重新部署时版本不一致。
七、创建 Docker 网络
后面的 MySQL、Redis、Spring Boot 容器需要互相访问,所以先创建一个专用网络。
docker network create project-net
查看网络:
docker network ls
检查网络详情:
docker network inspect project-net
文字说明
同一个 Docker 网络中的容器,可以通过容器名互相访问。
例如:
MySQL 容器名:mysql Redis 容器名:redis
后端容器中就可以使用:
mysql redis
作为主机地址。
这里有一个非常重要的概念:
在 Docker 容器中,localhost 指的是当前容器本身,不是宿主机,也不是其他容器。
八、准备 MySQL 数据目录
如果直接创建 MySQL 容器而不挂载数据目录,删除容器时可能导致数据库数据丢失。
所以先创建宿主机目录:
mkdir -p /opt/project/mysql/data mkdir -p /opt/project/mysql/conf mkdir -p /opt/project/mysql/init
目录作用:
/opt/project/mysql/data 保存数据库数据 /opt/project/mysql/conf 保存 MySQL 配置文件 /opt/project/mysql/init 保存初始化 SQL
文字说明
数据持久化是 Docker 部署数据库时必须考虑的问题。
容器本身可以删除和重建,但数据库数据不能因为容器删除就丢失。
九、准备初始化 SQL
在服务器上创建初始化 SQL 文件:
vim /opt/project/mysql/init/init.sql
示例内容:
create database if not exists project_prod
default character set utf8mb4
collate utf8mb4_unicode_ci;
use project_prod;
create table if not exists user (
id bigint primary key auto_increment comment '用户ID',
username varchar(50) not null unique comment '用户名',
password varchar(255) not null comment '密码',
nickname varchar(50) comment '昵称',
status tinyint default 1 comment '状态',
create_time datetime default current_timestamp comment '创建时间'
) comment '用户表';
create table if not exists product (
id bigint primary key auto_increment comment '商品ID',
name varchar(100) not null comment '商品名称',
price decimal(10, 2) not null comment '商品价格',
stock int default 0 comment '库存',
status tinyint default 1 comment '状态',
create_time datetime default current_timestamp comment '创建时间',
update_time datetime default current_timestamp on update current_timestamp comment '更新时间'
) comment '商品表';
文字说明
MySQL 官方镜像在第一次初始化容器时,会执行:
/docker-entrypoint-initdb.d/
目录下的 .sql 文件。
所以后面把宿主机的 init 目录挂载进去后,数据库第一次启动时会自动执行这些 SQL。
注意:初始化 SQL 一般只在数据库目录为空时执行。
如果容器已经初始化过,再修改 SQL 文件,重新启动容器通常不会自动执行。
十、创建 MySQL 容器
执行下面命令:
docker run -d \ --name mysql \ --network project-net \ --restart unless-stopped \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD=****** \ -e MYSQL_DATABASE=project_prod \ -v /opt/project/mysql/data:/var/lib/mysql \ -v /opt/project/mysql/conf:/etc/mysql/conf.d \ -v /opt/project/mysql/init:/docker-entrypoint-initdb.d \ mysql:8.0
文字说明
这条命令比较长,我们拆开说明。
-d
表示后台运行容器。
--name mysql
给容器命名为 mysql。
--network project-net
加入前面创建的 Docker 网络。
--restart unless-stopped
除非手动停止,否则 Docker 重启后自动启动该容器。
-p 3306:3306
把宿主机 3306 端口映射到容器 3306 端口。
-e MYSQL_ROOT_PASSWORD=******
设置 MySQL root 密码。
-e MYSQL_DATABASE=project_prod
创建默认数据库。
-v /opt/project/mysql/data:/var/lib/mysql
将宿主机数据目录挂载到 MySQL 容器数据目录。
十一、查看 MySQL 容器状态
查看正在运行的容器:
docker ps
查看所有容器:
docker ps -a
查看 MySQL 日志:
docker logs mysql
持续查看日志:
docker logs -f mysql
如果看到类似内容:
ready for connections
说明 MySQL 已经准备好接受连接。
查看容器详细信息:
docker inspect mysql
十二、进入 MySQL 容器测试
进入容器:
docker exec -it mysql bash
在容器中执行:
mysql -uroot -p
输入密码后,查看数据库:
show databases;
切换数据库:
use project_prod;
查看表:
show tables;
退出 MySQL:
exit
退出容器:
exit
文字说明
也可以不进入容器,直接执行 MySQL 命令:
docker exec -it mysql mysql -uroot -p project_prod
实际开发中,docker exec 是非常常用的容器排查命令。
十三、拉取 Redis 镜像
拉取 Redis 7 镜像:
docker pull redis:7.2
查看镜像:
docker images redis
文字说明
Redis 版本也建议固定,不要直接使用 latest。
本篇使用:
redis:7.2
如果项目对 Redis 版本有明确要求,以项目要求为准。
十四、准备 Redis 数据目录
创建 Redis 目录:
mkdir -p /opt/project/redis/data mkdir -p /opt/project/redis/conf
创建 Redis 配置文件:
vim /opt/project/redis/conf/redis.conf
示例内容:
bind 0.0.0.0 protected-mode no port 6379 appendonly yes appendfsync everysec requirepass replace-with-your-redis-password
文字说明
这里开启了 AOF 持久化:
appendonly yes
Redis 会将写命令追加到 AOF 文件中。
配置密码:
requirepass replace-with-your-redis-password
正式环境不要使用示例密码,应该替换成安全密码,并通过权限控制保护配置文件。
十五、创建 Redis 容器
docker run -d \ --name redis \ --network project-net \ --restart unless-stopped \ -p 6379:6379 \ -v /opt/project/redis/data:/data \ -v /opt/project/redis/conf/redis.conf:/usr/local/etc/redis/redis.conf \ redis:7.2 \ redis-server /usr/local/etc/redis/redis.conf
文字说明
这里将 Redis 数据目录挂载到宿主机:
-v /opt/project/redis/data:/data
Redis 配置文件挂载到容器中:
-v /opt/project/redis/conf/redis.conf:/usr/local/etc/redis/redis.conf
最后通过:
redis-server /usr/local/etc/redis/redis.conf
指定配置文件启动 Redis。
十六、测试 Redis 是否正常
查看 Redis 容器状态:
docker ps
查看 Redis 日志:
docker logs redis
进入 Redis 容器:
docker exec -it redis redis-cli
如果配置了密码,进入后执行:
auth replace-with-your-redis-password
测试连接:
ping
正常返回:
PONG
写入测试数据:
set test-key hello
读取数据:
get test-key
退出:
exit
文字说明
如果 Redis 启用了密码,不要把真实密码直接写进博客命令中。
可以使用占位符:
replace-with-your-redis-password
十七、查看容器网络连通性
MySQL 和 Redis 都加入了 project-net 网络。
查看网络详情:
docker network inspect project-net
可以看到:
mysql redis
后面创建 Spring Boot 容器时,也加入这个网络。
这样后端配置中的数据库地址可以写:
host: mysql
Redis 地址可以写:
host: redis
而不是:
host: localhost
十八、Spring Boot 连接容器中的 MySQL 和 Redis
如果 Spring Boot 也运行在 Docker 容器中,可以这样配置:
spring:
datasource:
url: jdbc:mysql://${DB_HOST:mysql}:${DB_PORT:3306}/${DB_NAME:project_prod}?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: ${DB_USERNAME:root}
password: ${DB_PASSWORD}
data:
redis:
host: ${REDIS_HOST:redis}
port: ${REDIS_PORT:6379}
password: ${REDIS_PASSWORD}
如果是 Spring Boot 2,Redis 配置可能写成:
spring:
redis:
host: ${REDIS_HOST:redis}
port: ${REDIS_PORT:6379}
password: ${REDIS_PASSWORD}
文字说明
这里最重要的是:
DB_HOST: mysql REDIS_HOST: redis
容器之间通过 Docker 网络和容器名通信。
如果 Spring Boot 在宿主机运行,而 MySQL、Redis 在容器中,那么可以使用:
localhost
因为宿主机通过端口映射访问容器。
但是如果 Spring Boot 也在容器中,就必须使用:
mysql redis
这也是 Docker 部署中非常容易弄错的地方。
十九、停止、启动和删除容器
停止 MySQL:
docker stop mysql
启动 MySQL:
docker start mysql
重启 MySQL:
docker restart mysql
停止 Redis:
docker stop redis
删除容器:
docker rm mysql
强制删除正在运行的容器:
docker rm -f mysql
文字说明
删除容器不等于删除挂载到宿主机的数据。
只要宿主机数据目录还在,重新创建容器时仍然可以使用原来的数据。
但是如果使用匿名 Volume 或没有挂载数据,删除容器后数据可能无法恢复。
二十、常见问题
1. MySQL 容器启动后立即退出
先查看日志:
docker logs mysql
常见原因:
- 数据目录权限问题
- 端口 3306 已被占用
- 配置参数错误
- 宿主机数据目录中存在不兼容数据
- 内存不足
查看端口:
ss -tunlp | grep 3306
2. Redis 容器无法连接
先查看日志:
docker logs redis
再测试:
docker exec -it redis redis-cli
如果启用了密码,记得先执行:
auth 密码
3. MySQL 初始化 SQL 没有执行
MySQL 官方镜像只会在第一次初始化数据目录时执行初始化 SQL。
如果已经创建过容器,后面再修改 init.sql,不会自动重新执行。
开发环境可以删除容器并清空数据目录后重新初始化,但生产环境不要随意清空数据。
4. 宿主机端口已经被占用
如果宿主机 3306 已经被本地 MySQL 占用,可以映射成其他端口:
-p 13306:3306
外部连接使用:
服务器IP:13306
但是容器网络内部访问 MySQL 时,仍然使用:
mysql:3306
二十一、实际开发建议
1. 不要把 MySQL 和 Redis 端口 暴露到公网
如果 Spring Boot 和数据库都在同一个 Docker 网络中,MySQL 和 Redis 不一定需要映射到公网。
例如:
# 不映射端口,只让其他容器访问 docker run -d --name mysql --network project-net ...
如果需要通过本地工具连接,再临时映射端口,并配合防火墙限制访问来源。
2. 数据目录一定要持久化
MySQL 至少要挂载:
/var/lib/mysql
Redis 至少要挂载:
/data
否则容器删除后,数据可能丢失。
3. 生产环境不要在命令中直接写密码
命令行中的密码可能进入 shell 历史记录。
更推荐使用环境变量文件或 Docker Secrets。
本篇为了便于阅读使用了占位命令,正式部署时要单独保护密码。
4. 版本固定
推荐:
mysql:8.0 redis:7.2
不要长期依赖:
mysql:latest redis:latest
固定版本更方便排查问题和回滚。
二十二、总结
这一篇我们完成了 Docker 部署 MySQL 和 Redis 的完整流程:
- 安装 Docker
- 配置镜像加速
- 创建 Docker 网络
- 拉取 MySQL 镜像
- 创建 MySQL 数据目录
- 使用初始化 SQL 创建数据库和表
- 创建 MySQL 容器
- 拉取 Redis 镜像
- 配置 Redis 持久化和密码
- 创建 Redis 容器
- 测试数据库和缓存服务
- 理解容器之间通过服务名通信
这一篇的关键并不只是记住几条 docker run 命令,而是要理解 Docker 中的三个核心概念:
- 镜像:软件运行模板
- 容器:镜像启动后的运行实例
- 网络和数据卷:解决容器通信和数据持久化
到此这篇关于Docker项目部署上线之MySQL和Redis的文章就介绍到这了,更多相关Docker部署MySQL和Redis内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
docker 命令报异常permission denied的解决方案
这篇文章主要介绍了docker 命令报异常permission denied的解决方案,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧2021-03-03
docker Compose部署springboot+vue前端端分离
本文主要介绍了docker Compose部署springboot+vue前端端分离,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2022-08-08


最新评论