目录
[二、传统部署 vs Docker容器部署:从"装修每个房间"到"搬入精装房"](#二、传统部署 vs Docker容器部署:从“装修每个房间”到“搬入精装房”)
[1. 镜像(Image)------ "标准化的集装箱设计图"](#1. 镜像(Image)—— “标准化的集装箱设计图”)
[2. 容器(Container)------ "正在运行的集装箱实例"](#2. 容器(Container)—— “正在运行的集装箱实例”)
[3. 仓库(Repository)------ "集装箱仓储中心"](#3. 仓库(Repository)—— “集装箱仓储中心”)
[4. Dockerfile ------ "集装箱建造说明书"](#4. Dockerfile —— “集装箱建造说明书”)
[5. 容器编排(Orchestration)------ "智能物流调度系统"](#5. 容器编排(Orchestration)—— “智能物流调度系统”)
四、实战演练:在宝塔面板部署SpringBoot+Vue项目
[1. 创建Nginx配置目录及前端运行目录](#1. 创建Nginx配置目录及前端运行目录)
[2. 上传前端项目的dist文件至html文件夹](#2. 上传前端项目的dist文件至html文件夹)
[3. conf文件夹中的nginx.conf配置文件](#3. conf文件夹中的nginx.conf配置文件)
[4. 创建redis缓存配置及数据目录](#4. 创建redis缓存配置及数据目录)
[5. redis配置文件](#5. redis配置文件)
[6. 创建后端项目目录](#6. 创建后端项目目录)
[7. Dockerfile文件](#7. Dockerfile文件)
[1. 准备镜像](#1. 准备镜像)
[2. 拉取镜像](#2. 拉取镜像)
[3. 创建docker-compose.yml文件](#3. 创建docker-compose.yml文件)
[4. 使用Docker Compose](#4. 使用Docker Compose)
[1. redis容器问题](#1. redis容器问题)
[2. springboot容器问题](#2. springboot容器问题)
一、初识Docker:什么是"集装箱技术"?
想象一下传统运输场景:货物种类繁多(PHP应用、Java应用、Python应用),包装方式各异(Windows服务器、CentOS系统、Ubuntu系统),依赖环境复杂(需要MySQL 5.7、Redis 6.0、Python 3.8),运输过程充满了不确定性和"在我的机器上能运行"的尴尬。
Docker就像现代物流系统中的标准化集装箱 ,无论你的货物是什么(应用代码),它都能提供一个完全一致的运输箱(容器),里面装好了所有货物运行所需的环境(操作系统、依赖库、配置文件)。这种技术将应用及其依赖打包成一个轻量级、可移植的单元。
二、传统部署 vs Docker容器部署:从"装修每个房间"到"搬入精装房"
传统部署模式(手动装修)
-
购买毛坯房:购买云服务器(ECS)
-
安装基础设施:安装JDK、Nginx、Node.js等
-
配置环境:设置环境变量、修改配置文件
-
部署应用:上传应用代码,调整权限
-
问题频发:
-
"为什么在我的本地能运行,服务器上就不行?"
-
新服务器部署需要从头再来一遍
-
不同应用环境冲突(A应用需要JDK 8,B应用需要JDK 11)
-
Docker容器部署(拎包入住)
-
选择精装房:拉取或构建Docker镜像
-
一键入住:运行容器,瞬间获得完整环境
-
核心优势:
-
环境一致性:开发、测试、生产环境完全一致
-
快速部署:秒级启动,传统方式需要分钟级
-
资源隔离:每个应用独立运行,互不干扰
-
弹性伸缩:轻松复制多个实例应对流量高峰
-
易于迁移:镜像一次构建,随处运行
-
三、Docker核心概念:用物流系统理解技术
1. 镜像(Image)------ "标准化的集装箱设计图"
镜像是只读的模板,包含运行应用所需的代码、运行时、库、环境变量和配置文件。
-
比喻:就像宜家家具的设计图纸和所有零件包,在任何地方都能组装出一模一样的家具
-
技术体现 :
nginx:1.20、mysql:8.0、openjdk:11-jre -
记忆:镜像可以理解为手机中的一个软件
2. 容器(Container)------ "正在运行的集装箱实例"
容器是镜像的运行实例,可以被启动、停止、删除。
-
比喻:根据设计图纸实际组装好的家具,正在被使用中
-
特点:轻量级、隔离性、可写层(数据变化保存在容器层)
-
记忆:容器可以理解为一个小型的手机
3. 仓库(Repository)------ "集装箱仓储中心"
仓库用于存储和分发镜像,分为公共仓库(Docker Hub)和私有仓库。
-
比喻:就像京东仓库存储各种标准化商品,随时可以配送到各地
-
常用仓库:Docker Hub、阿里云容器镜像服务、私有Harbor仓库
-
记忆:仓库可以理解为手机的存储库(存储空间)
4. Dockerfile ------ "集装箱建造说明书"
文本文件包含一系列指令,用于自动化构建镜像。
bash
# 示例:SpringBoot应用Dockerfile
FROM openjdk:11-jre-slim # 基础镜像
COPY target/app.jar /app.jar # 复制应用
EXPOSE 8080 # 暴露端口
ENTRYPOINT ["java", "-jar", "/app.jar"] # 启动命令
记忆:Dockerfile可以理解为软件的安装包apk
5. 容器编排(Orchestration)------ "智能物流调度系统"
当有多个容器需要协同工作时(如微服务架构),需要编排工具来管理。
-
比喻:像双11期间的菜鸟物流系统,智能调度成千上万的包裹
-
常用工具:Docker Compose(单机)、Kubernetes(集群)
-
记忆:容器编排可以理解为手机中的应用市场,可以同时安装多个软件(一键部署)
四、实战演练:在宝塔面板部署SpringBoot+Vue项目
环境准备
-
阿里云ECS服务器(轻量服务器也可以)
-
宝塔面板:11.4.0+(宝塔面板首页可以更新)
-
安装Docker管理器:在宝塔应用商店搜索安装(新版的宝塔面板已经集成)
-
SpringBoot项目的jar包(maven package)
-
构建Vue前端项目的dist目录(npm run build)

步骤一:Docker部署文件统一管理
为了方便后续管理文件,我们在根目录下创建名为docker的文件夹,后续关于docker部署的文件我们统一放在该文件夹下

步骤二:创建所需文件夹
部署前端vue项目,我们需要用到nginx;部署后端springboot项目我们需要用到redis缓存以及mysql数据库,逐个创建这些文件夹
1. 创建Nginx配置目录及前端运行目录

cert文件夹存放域名签证SSL证书的key、pem文件(如果要使用https的话)
conf 文件夹存放nginx.conf配置文件
html 文件夹存放前端打包的dist文件内容
log 文件夹存放的是nginx的运行日志
2. 上传前端项目的dist文件至html文件夹

3. conf文件夹中的nginx.conf配置文件
bash
worker_processes 1;
error_log /var/nginx/log/error.log warn;
pid /var/run/nginx.pid;
events {
# 可以根据业务并发量适当调高
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
# 高效传输文件
sendfile on;
# 长连接超时时间
keepalive_timeout 65;
# 单连接最大请求数,提高长连接复用率
keepalive_requests 100000;
# 限制body大小
client_max_body_size 100m;
client_header_buffer_size 32k;
client_body_buffer_size 512k;
# 开启静态资源压缩
gzip_static on;
# 连接数限制 (防御类配置) 10m 一般够用了,能存储上万 IP 的计数
limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn_zone $server_name zone=perserver:10m;
# 隐藏 nginx 版本号,防止暴露版本信息
server_tokens off;
access_log /var/nginx/log/access.log main;
upstream server {
ip_hash;
server 127.0.0.1:8080;
}
server {
listen 80;
server_name localhost;
# https配置参考 start
#listen 443 ssl;
#server_name localhost;
# 证书直接存放 /docker/nginx/cert/ 目录下即可 更改证书名称即可 无需更改证书路径
#ssl_certificate /etc/nginx/cert/xxx.local.pem; # /etc/nginx/cert/ 为docker映射路径 不允许更改
#ssl_certificate_key /etc/nginx/cert/xxx.local.key; # /etc/nginx/cert/ 为docker映射路径 不允许更改
#ssl_protocols TLSv1.3 TLSv1.2 TLSv1.1 TLSv1;
# https配置参考 end
location / {
root /usr/share/nginx/html; # docker映射路径 不允许更改
try_files $uri $uri/ /index.html;
index index.html index.htm;
}
location /prod-api/ {
# 设置客户端请求头中的 Host 信息(保持原始 Host)
proxy_set_header Host $http_host;
# 获取客户端真实 IP
proxy_set_header X-Real-IP $remote_addr;
# 自定义头 REMOTE-HOST,记录客户端 IP
proxy_set_header REMOTE-HOST $remote_addr;
# 获取完整的客户端 IP 链(经过多级代理时)
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 设置后端响应超时时间
proxy_read_timeout 30s;
# 禁用代理缓冲,数据直接传给客户端
proxy_buffering off;
# 禁用代理缓存
proxy_cache off;
proxy_pass http://server/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
如果要使用https,那么将注释解开后,把你的域名签证SSL证书的key、pem文件放到 cert文件夹中,并将注释中的xxx.local.pem、xxx.local.key修改为你的SSL证书文件名
4. 创建redis缓存配置及数据目录

conf 文件夹存放redis.conf配置文件
data 文件夹存放redis的aof数据文件
注意:data文件夹需要给写入权限,否则redis在启动时会失败,因为redis需要写入rdb、aof文件(可以在配置文件中设置为no)
5. conf 文件夹中的redis.conf配置文件
bash
# redis 密码
requirepass lucky123
# 配置持久化文件存储路径
dir /redis/data
# 配置rdb
# 15分钟内有至少1个key被更改则进行快照
save 900 1
# 5分钟内有至少10个key被更改则进行快照
save 300 10
# 1分钟内有至少10000个key被更改则进行快照
save 60 10000
# 开启压缩
rdbcompression yes
# rdb文件名 用默认的即可
dbfilename dump.rdb
# 开启aof
appendonly yes
# 文件名
appendfilename "appendonly.aof"
# 持久化策略,no:不同步,everysec:每秒一次,always:总是同步,速度比较慢
# appendfsync always
appendfsync everysec
# appendfsync no
6. 创建后端项目目录

在该目录下创建Dockerfile文件并上传springboot的jar包到该目录中
7. Dockerfile文件
bash
FROM openjdk:26-ea-17-jdk
LABEL maintainer="lucky"
WORKDIR /lucky
ENV SERVER_PORT=8080 LANG=C.UTF-8 LC_ALL=C.UTF-8 JAVA_OPTS=""
EXPOSE ${SERVER_PORT}
# 目录需要处于同级,否则会报错(可自行修改)
ADD lucky-admin.jar /lucky/lucky-admin.jar
SHELL ["/bin/bash", "-c"]
ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -Dserver.port=${SERVER_PORT} \
-XX:+HeapDumpOnOutOfMemoryError -XX:+UseZGC ${JAVA_OPTS} \
-jar /lucky/lucky-admin.jar
做好以上工作,就可以开始正式部署了。
注意:因为配置原因,Dockerfile文件要与jar包处于同级目录
步骤三:使用宝塔面板部署
1. 准备镜像
我们本次部署需要四个镜像,nginx、redis、mysql以及后端项目镜像,其中nginx、redis、mysql的镜像官方已经帮我做好了,我们直接拉取即可,而后端项目的镜像就是我们上述的Dockerfile文件,运行该文件之后就可以得到我们后端项目的镜像了。
镜像一个个准备太麻烦,我们可以使用容器编排(其实就是一键部署),更快也更方便。
2. 拉取镜像


点击线上镜像,选择我们需要用到的镜像版本并拉取即可,nginx、redis、mysql的镜像都是如此操作。

使用容器编排的话可以不用这样一个个拉取,容器编排指定镜像版本后会自行下载,不需要我们手动去下载,但是需要你知道对应镜像的版本号。
3. 创建docker-compose.yml文件

在docker文件夹中创建docker-compose.yml文件,复制下面的文件内容,根据自身情况修改并保存
bash
services:
mysql:
image: mysql:8.0.44
container_name: mysql
environment:
# 时区上海
TZ: Asia/Shanghai
# root 密码
MYSQL_ROOT_PASSWORD: lucky123
# 初始化数据库
MYSQL_DATABASE: lucky-vue
ports:
- "3306:3306"
volumes:
# 数据挂载
- /docker/mysql/data/:/var/lib/mysql/
# 配置挂载
- /docker/mysql/conf/:/etc/mysql/conf.d/
command:
# 将mysql8.0默认密码策略 修改为 原先 策略 (mysql8.0对其默认策略做了更改 会导致密码无法匹配)
--default-authentication-plugin=caching_sha2_password
--character-set-server=utf8mb4
--collation-server=utf8mb4_general_ci
--explicit_defaults_for_timestamp=true
--lower_case_table_names=1
privileged: true
network_mode: "host"
redis:
image: redis:8.0.5
container_name: redis
ports:
- "6379:6379"
environment:
# 时区上海
TZ: Asia/Shanghai
volumes:
# 配置文件
- /docker/redis/conf:/redis/config:rw
# 数据文件
- /docker/redis/data/:/redis/data/:rw
command: "redis-server /redis/config/redis.conf"
privileged: true
network_mode: "host"
nginx-web:
image: nginx:1.29.4
container_name: nginx-web
environment:
# 时区上海
TZ: Asia/Shanghai
ports:
- "80:80"
- "443:443"
volumes:
# 证书映射
- /docker/nginx/cert:/etc/nginx/cert
# 配置文件映射
- /docker/nginx/conf/nginx.conf:/etc/nginx/nginx.conf
# 页面目录
- /docker/nginx/html:/usr/share/nginx/html
# 日志目录
- /docker/nginx/log:/var/nginx/log
privileged: true
network_mode: "host"
lucky-admin:
# 创建的镜像名称(可自行修改)
image: lucky-admin:1.0.0
build:
context: /docker/lucky-vue/
dockerfile: Dockerfile
container_name: lucky-admin
environment:
# 时区上海
TZ: Asia/Shanghai
ports:
- "8080:8080"
volumes:
# 配置文件
- /docker/lucky-admin/logs/:/lucky/lucky-admin/logs/
privileged: true
network_mode: "host"
depends_on:
- mysql
- redis
可以看到volumes的参数配置与我们前面步骤二:创建所需文件夹的目录是对应的
运行该文件会创建四个容器,其中nginx、redis、mysql这三个容器会根据我们前面拉取的镜像进行创建,而后端项目的容器则会去应用上下文(/docker/lucky-vue/)中找Dockerfile文件,先创建其镜像(lucky-admin:1.0.0)再创建容器(lucky-admin)。
需要与步骤二:6.创建后端项目目录中的配置一致,否则会找不到文件
4. 使用Docker Compose
接下来就是正式的一键部署环节,上述配置都完成的话,部署起来就会非常快

添加容器编排,将我们的docker-compose.yml文件导入进去

编排名称自拟,点击确定

如果没有问题的话,我们在容器面板可以看到四个正在运行的容器


与此同时,我们的镜像也创建成功了,创建好的镜像我们可以将其推送到我们的私服仓库中,这样后续如果该版本存在问题,旧版本镜像仍然有保存,如此可以直接拉取旧版本的镜像直接运行即可,以实现版本的秒级回退

仓库地址需要自行配置
步骤四:验证部署是否成功
在浏览器输入 http://你的服务器公网IP 或 https://你的域名 ,如果能够正常进入vue前端页面并且后端接口调用成功,那么就说明本次的部署成功了

通过公网IP访问的话一般是80端口,域名访问通常是443端口,我们在nginx的配置文件中已经配置
注意:这两个端口需要在阿里云安全组和宝塔面板防火墙中开放,否则访问不到
排查问题
在运行容器编排阶段难免会出现一些问题,那么如何排查这些问题呢?

在运行容器编排文件后,只要你指定的镜像版本存在,那么在容器列表中是能够看到对应的容器的,容器状态没有在运行中那么就是启动存在问题,我们直接去对应容器的日志查看是什么问题导致的,然后解决即可。
1. redis容器问题
比如我第一次运行redis容器时,就碰到权限不足导致的启动失败。原因就是我们配置了redis的rdb、aof功能,那么redis在启动时就需要向data文件夹写入这些文件,而我们没有给redis的docker容器写入权限,所以导致启动失败。



给data文件夹写入权限之后,重启redis容器即可
2. springboot容器问题

上面的是正常的情况,通常有问题的话也就是redis和mysql的连接问题了,在项目打包之前就应该设置好redis和mysql的生产环境连接,之后在打包即可
连接设置就用localhost就行,因为我们的容器网络设置的是network_mode: "host",host模式表示使用的宿主机网络,当关联的容器都使用这个模式的时候,那么就可以直接通过localhost来访问对应的服务容器,或者可以使用host.docker.internal(Docker 18.03+)或宿主机真实IP。
检查redis和mysql连接设置


检查连接地址host、端口port、密码是否与我们对应的服务容器的配置是一致的
项目修改部署
在部署完成后,后续的项目修改再部署就会非常方便且快速,前端项目直接替换文件即可(建议删除原文件再上传新文件)

后端项目建议先停止原项目容器的运行,而后删除原jar包,再上传新jar包


重新启动springboot后端项目容器即可
五、总结:Docker化部署的价值
通过本次实践,我们可以看到Docker容器化部署带来的显著优势:
-
一键部署:从代码提交到生产部署的完整流水线
-
环境标准化:彻底告别"在我机器上能运行"的问题
-
资源高效利用:比虚拟机更轻量,更高密度部署
-
快速回滚:镜像版本化,出现问题秒级回退
宝塔面板的Docker管理器大大降低了容器技术的使用门槛,使得中小团队也能享受容器化带来的便利。
进阶建议:随着业务增长,可以考虑引入CI/CD流水线、Kubernetes集群管理、服务网格等更高级的云原生技术,构建更加健壮和弹性的应用架构。