完整Docker部署全流程教程(Windows本地 → Ubuntu服务器)

这份教程整合了从Docker安装到最终在Ubuntu服务器运行的全流程,涵盖MySQL(含初始化SQL)、Redis、SpringBoot容器的构建、互通、打包迁移,同时标注了你之前踩过的所有坑,确保一步到位。

一、前置说明

  • 适用场景:Windows本地开发调试Docker容器,迁移到Ubuntu服务器稳定运行
  • 核心目标:实现MySQL(含初始化SQL)、Redis、SpringBoot容器互通,迁移后无需重复配置
  • 工具准备
    • Windows:Docker Desktop、PowerShell(管理员模式)、Maven(打包SpringBoot)
    • Ubuntu服务器:已安装SSH、开放22/8080/3306/6379端口
    • 网络:Windows能访问Ubuntu服务器(公网/内网)

二、阶段1:Windows本地环境准备(解决镜像源坑)

1. 安装Docker Desktop

2. 配置国内镜像源(解决拉取镜像超时/403)

❗ 坑点1:直接拉取Docker Hub镜像会超时/403,必须配置国内源
打开Docker Desktop → SettingsDocker Engine

三、阶段2:Windows本地拉取基础镜像(MySQL/Redis)

打开Windows PowerShell(管理员模式),执行以下命令:

# 拉取MySQL 8.0镜像(稳定版)
docker pull mysql:8.0

# 拉取Redis最新版镜像
docker pull redis:latest

❗ 坑点2:若仍拉取失败 → 确认镜像源配置生效,或后续用「手动导入镜像包」兜底。

四、阶段3:Windows本地配置MySQL容器(含初始化SQL+数据持久化)

1. 准备本地目录(映射数据+初始化SQL)

# 创建MySQL数据/初始化SQL目录
mkdir -p D:\docker-mysql\data
mkdir -p D:\docker-mysql\sql
  • 将项目的初始SQL文件(如init.sql)复制到 D:\docker-mysql\sql 目录。

2. 创建自定义网络(解决容器互通坑)

❗ 坑点3:默认bridge网络无法解析容器名,必须创建自定义网络

# 创建专属网络(所有容器接入此网络)
docker network create my-app-network

3. 启动MySQL容器(一键初始化)

docker run -d \
--name mysql-container \
--network my-app-network \
-p 3306:3306 \
-v D:\docker-mysql\data:/var/lib/mysql \ # 数据持久化(关键!避免容器删了数据丢)
-v D:\docker-mysql\sql:/docker-entrypoint-initdb.d \ # 自动导入init.sql
-e MYSQL_ROOT_PASSWORD=123456 \ # root密码
-e MYSQL_DATABASE=your_db \ # 初始化创建的数据库名
-e MYSQL_CHARACTER_SET_SERVER=utf8mb4 \ # 解决中文乱码
-e MYSQL_COLLATION_SERVER=utf8mb4_unicode_ci \
-e TZ=Asia/Shanghai \ # 时区同步(避免时间错乱)
mysql:8.0 \
--default-authentication-plugin=mysql_native_password # 兼容SpringBoot连接

❗ 坑点4:初始化SQL仅首次启动生效 → 若已启动过容器,需先删除D:\docker-mysql\data目录再重启;
❗ 坑点5:容器内localhost不是宿主机 → 后续SpringBoot配置中MySQL host填容器名(mysql-container)。

4. 验证MySQL容器(确认SQL导入成功)

# 进入MySQL容器
docker exec -it mysql-container /bin/bash

# 登录MySQL(输入密码123456)
mysql -uroot -p

# 验证数据库和表
use your_db;
show tables; # 能看到init.sql中的表则成功

五、阶段4:Windows本地配置Redis容器

docker run -d \
--name redislocal \
--network my-app-network \
-p 6379:6379 \
redis:latest \
--bind 0.0.0.0 --protected-mode no # 关闭保护模式,允许容器访问

❗ 坑点6:Redis无法访问 → 必须加--bind 0.0.0.0 --protected-mode no

六、阶段5:Windows本地构建SpringBoot镜像

1. 准备SpringBoot项目

(1)固定JAR包名称(避免Dockerfile找不到JAR)

修改项目pom.xml

<build>
<finalName>app</finalName> <!-- 打包后生成target/app.jar -->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

(2)修改配置文件(关键:容器名访问MySQL/Redis)

修改application.yml(删除冗余配置,核心如下):

spring:
# 连接MySQL容器(host填容器名,不是localhost)
datasource:
url: jdbc:mysql://mysql-container:3306/your_db?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
# 连接Redis容器(host填容器名)
redis:
host: redislocal
port: 6379
# 生产环境配置(也可启动时指定)
profiles:
active: prod
server:
port: 8080

2. 打包SpringBoot项目

# 进入项目根目录(如D:\your-springboot-project)
cd D:\your-springboot-project

# 打包(跳过测试,加快速度)
mvn clean package -DskipTests

❗ 坑点7:打包失败 → 确认Maven环境正常,项目无语法错误。

3. 编写Dockerfile(放在项目根目录)

❗ 坑点8:避免用Ubuntu镜像+Supervisor(复杂易报错),直接用纯JDK镜像

# 用国内华为云源的OpenJDK 17,避免Docker Hub 403
FROM swr.cn-east-3.myhuaweicloud.com/opensourceway/openjdk:17-jdk-slim

# 环境配置(时区+端口+JVM参数)
ENV TZ=Asia/Shanghai
ENV SERVER_PORT=8080
ENV JAVA_OPTS="-Xms512m -Xmx1024m -Djava.security.egd=file:/dev/./urandom -Duser.timezone=Asia/Shanghai"

# 配置时区
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

# 部署项目
WORKDIR /app
COPY target/app.jar /app/app.jar

# 暴露端口
EXPOSE ${SERVER_PORT}

# 启动命令
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar /app/app.jar --server.port=${SERVER_PORT}"]

4. 构建SpringBoot镜像

# 项目根目录执行
docker build -t sb-booking:v1 .

❗ 坑点9:提示app.jar找不到 → 确认mvn package成功,target目录下有app.jar

5. 启动SpringBoot容器(验证互通)

docker run -d \
--name sb-booking \
--network my-app-network \
-p 8080:8080 \
-e spring.profiles.active=prod \ # 启动时指定生产环境(优先级最高)
sb-booking:v1

6. 验证SpringBoot容器

  • 访问http://localhost:8080(能打开项目接口文档/首页则启动成功);
  • 调用接口验证:确认能读写MySQL/Redis(无连接错误则互通成功)。

七、阶段6:Windows本地打包容器为镜像(避免重复配置)

将已配置好的MySQL容器保存为自定义镜像(含初始化SQL、环境变量),迁移后无需重复配置:

# (可选)停止MySQL容器(更稳定)
docker stop mysql-container

# 提交容器为新镜像(快照)
docker commit mysql-container mysql-custom:v1

# 启动MySQL容器(可选)
docker start mysql-container

导出镜像为tar包(迁移用)

# 创建镜像导出目录
mkdir -p D:\docker-images

# 导出MySQL自定义镜像
docker save -o D:\docker-images\mysql-custom-v1.tar mysql-custom:v1

# 导出SpringBoot镜像
docker save -o D:\docker-images\sb-booking-v1.tar sb-booking:v1

# (可选)导出Redis镜像
docker save -o D:\docker-images\redis-custom-v1.tar redis:latest

❗ 坑点10:镜像体积过大 → 导出前可清理容器日志(docker exec -it 容器名 rm -rf /var/log/*.log),或压缩为tar.gz

八、阶段7:传输tar包到Ubuntu服务器

1. 先给Ubuntu安装Docker(若未安装)

登录Ubuntu服务器(SSH),执行:

# 更新源
sudo apt update

# 安装Docker
sudo apt install -y docker.io

# 启动并开机自启
sudo systemctl start docker
sudo systemctl enable docker

# 给普通用户Docker权限(避免每次输sudo)
sudo usermod -aG docker $USER

# 重启SSH会话生效(退出再重新登录)

2. Windows传输tar包到Ubuntu(SCP命令)

# Windows PowerShell执行(替换服务器IP/用户名)
# 传输MySQL镜像
scp D:\docker-images\mysql-custom-v1.tar root@你的服务器IP:/usr/local/docker-images/

# 传输SpringBoot镜像
scp D:\docker-images\sb-booking-v1.tar root@你的服务器IP:/usr/local/docker-images/

# (可选)传输Redis镜像
scp D:\docker-images\redis-custom-v1.tar root@你的服务器IP:/usr/local/docker-images/

❗ 坑点11:SCP传输超时 → 确认服务器防火墙开放22端口,网络稳定。

九、阶段8:Ubuntu服务器导入并运行镜像

1. 登录Ubuntu服务器,创建目录

# 创建镜像/数据目录
mkdir -p /usr/local/docker-images
mkdir -p /usr/local/docker-mysql/data

2. 导入镜像

# 导入MySQL自定义镜像
docker load -i /usr/local/docker-images/mysql-custom-v1.tar

# 导入SpringBoot镜像
docker load -i /usr/local/docker-images/sb-booking-v1.tar

# (可选)导入Redis镜像
docker load -i /usr/local/docker-images/redis-custom-v1.tar

❗ 坑点12:导入后镜像名显示<none> → 手动打标签:docker tag 镜像ID mysql-custom:v1(镜像ID用docker images查看)。

3. 创建自定义网络(和本地一致)

docker network create my-app-network

4. 运行MySQL容器(无需冗长配置)

docker run -d \
--name mysql-container \
--network my-app-network \
-p 3306:3306 \
-v /usr/local/docker-mysql/data:/var/lib/mysql \ # 数据持久化
--restart=always \ # 开机自启
mysql-custom:v1

5. 运行Redis容器(Ubuntu)

docker run -d \
--name redislocal \
--network my-app-network \
-p 6379:6379 \
--restart=always \
redis:latest \
--bind 0.0.0.0 --protected-mode no

6. 运行SpringBoot容器(Ubuntu)

docker run -d \
--name sb-booking \
--network my-app-network \
-p 8080:8080 \
-e spring.profiles.active=prod \
--restart=always \ # 异常重启
sb-booking:v1

7. 验证运行状态

# 查看容器状态(全部Up则成功)
docker ps

# 查看SpringBoot日志(无报错则正常)
docker logs sb-booking

# 验证端口可访问
curl http://localhost:8080

❗ 坑点13:服务器外网无法访问8080/3306 → 开放防火墙端口:

sudo ufw allow 8080/tcp
sudo ufw allow 3306/tcp
sudo ufw reload

(云服务器需额外在安全组开放端口)

十、全流程核心踩坑总结(必看!)

  1. 镜像源问题:Docker Hub拉取超时/403 → 配置中科大/网易镜像源,或用国内厂商镜像(如华为云OpenJDK);
  2. 容器互通问题:默认bridge网络无法解析容器名 → 创建自定义bridge网络,所有容器接入;
  3. MySQL初始化问题:SQL仅首次启动生效 → 首次启动前确保数据目录为空;
  4. 地址配置问题:容器内localhost不是宿主机 → SpringBoot配置中MySQL/Redis host填容器名;
  5. 数据持久化问题:容器删除数据丢失 → 必须挂载宿主机目录到/var/lib/mysql
  6. 端口问题:容器创建后无法改端口 → 重建容器(推荐),避免修改Docker配置文件;
  7. 环境变量优先级docker run -e > Dockerfile ENV > 配置文件 → 生产环境优先用启动参数指定;
  8. 架构兼容问题:Windows打包的x86镜像不能在ARM服务器运行 → 打包时加--platform linux/amd64
  9. Ubuntu权限问题:运行Docker需sudo → 添加用户到docker组;
  10. 端口访问问题:服务器容器端口无法访问 → 开放防火墙+云服务器安全组端口。

十一、最终验证

在Ubuntu服务器外网访问http://服务器IP:8080,调用接口验证MySQL/Redis读写正常,即全流程部署成功。