1.Docker是什么

Docker = 给你的程序打包一个「独立、便携、一键运行」的小盒子

这个小盒子里:

  • 装着你的代码(Java/Python)
  • 装着运行需要的环境(JDK、Python 版本、依赖库、配置)
  • 装着启动命令
  • 和你电脑的其他东西完全隔离

一个自带操作系统、自带环境、自带软件的「迷你虚拟机」,但比虚拟机轻量 100 倍,启动只要 1 秒。

2.Docker的作用

你做过小项目,一定遇到过这些崩溃时刻:

  • 在你电脑能跑,换别人电脑就报错
  • Python 换个版本,依赖全炸
  • Java 项目换台机器,JDK 版本不对、环境变量不对
  • 想部署到服务器,配置半天都跑不起来

Docker 就是解决这些问题的终极工具。

它的核心好处:

  • 一次打包,到处运行(Windows/Mac/Linux/ 服务器全都一样跑)
  • 环境隔离,不会污染你本机的 Python/Java 版本
  1. 一键启动,别人不用配环境,直接运行你的项目
  2. 部署超简单,以后把项目放云服务器,一行命令搞定

3.Docker 核心 3 个概念

不用记复杂术语,记住这 3 个就行:

3.1 Dockerfile(食谱)

告诉 Docker:

  • 用什么基础环境(Python3.10 / Java17)
  • 把哪些代码放进去
  • 装哪些依赖
  • 怎么启动

具体讲解请看

3.2 Image(镜像 = 打包好的程序包)

把你的项目 + 环境打包成一个只读文件,叫镜像,就像一个绿色软件安装包。

3.3 Container(容器 = 正在运行的程序)

镜像跑起来,就变成容器。一个镜像可以跑N个容器,互不干扰。

4.使用流程

1.安装WSL2

WSL是Windows 内置轻量化 Linux 内核

下载流程: 保姆级教程:WSL2(Windows Subsystem for Linux)的安装和使用 - 知乎

2.安装Docker

[Docker Desktop: The #1 Containerization Tool for Developers | Docker](https://www.docker.com/products/docker-desktop/)

下载好之后不要双击安装,默认会安装到c盘,之后的镜像也会默认安装到c盘

在终端cd到下载的docker目录中,然后输入以下指令进行安装

start /w "" "Docker Desktop Installer.exe" install --accept-license --installation-dir="D:\software\Docker\App" --wsl-default-data-root="D:\software\Docker\WSLData"

1
2
3
--accept-license: 自动同意协议,不弹窗确认
--installation-dir:docker想安装的目录
--wsl-default-data-root:所有拉取的镜像、容器存在这里(关键,防 C 盘爆满)

之后一路下一步。

3.docker镜像

1
2
3
4
5
6
7
{
"registry-mirrors":[
"https://docker.m.daocloud.io",
"https://docker.1panel.live",
"https://hub.rat.dev"
]
}

##4.简单案例

在终端输入docker run hello-world

可以看到docker desktop里已经有镜像了

WSL 是虚拟磁盘,不能直接在 Windows 文件夹里看到镜像文件,Docker 镜像、容器打包在 ext4.vhdx 虚拟磁盘文件内部,Windows 资源管理器打不开里面的 Linux 文件,只能 WSL 系统内部访问

5.GUI界面使用

完全可以在 Docker Desktop 可视化拉取镜像,不用敲命令

一、图形界面拉取镜像步骤

  1. 打开 Docker Desktop → 顶部【Search】搜索框
  2. 输入nginx/hello-world/mysql:5.7
  3. 搜到目标镜像后,点右侧【Pull】按钮,自动下载
  4. 下载完成 → 左侧【Images】列表出现镜像

二、图形界面启动容器(替代 docker run)

  1. 在 Images 列表,找到已下载镜像,点【Run】
  2. 弹窗配置:
    • Container name:自定义容器名(mynginx)
    • Ports:Host 填8080,Container 填80(端口映射)
  3. 点击Run直接启动容器
  4. 左侧【Containers】就能看到正在运行的服务

三、常用可视化操作

  1. 启停容器:Containers 页面点 ▶️启动 / ⏹停止
  2. 进入容器终端:容器右侧【Exec】图标,直接打开 Linux 命令行
  3. 删除镜像 / 容器:点垃圾桶图标一键删除

小提示

命令行适合批量、脚本自动化;桌面 GUI 适合新手可视化点点操作,两种方式通用。

6.指令使用

一、系统信息

1
2
3
4
5
6
7
8
#查看Docker版本
docker --version
#查看Docker引擎详细配置、镜像源、存储驱动
docker info
#查看镜像/容器/数据卷占用磁盘大小(-v展示明细)
docker system df
#清理无用资源:停止的容器、悬空镜像、无用网络(-a删除所有未使用镜像,--volumes清空无用卷)
docker system prune -a --volumes

二、镜像管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#1.拉取镜像,不加版本默认latest最新版
docker pull nginx:1.25
#2.查看本地全部镜像,-q只输出镜像ID
docker images
docker images -q
#3.删除镜像,-f强制删除(被容器占用也能删)
docker rmi nginx:1.25
docker rmi -f 镜像ID
#4.镜像重命名打标签(用于上传私有仓库)
docker tag nginx:1.25 mynginx:v1
#5.通过Dockerfile构建镜像,-t指定镜像名:版本,末尾.代表Dockerfile在当前目录
docker build -t myweb:1.0 .
#6.镜像打包导出(本地存成tar文件)
docker save -o nginx.tar nginx:1.25
#7.从tar包导入镜像
docker load -i nginx.tar
#8.查询镜像详细参数(分层、环境、挂载配置)
docker inspect nginx:1.25

三、容器生命周期

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
1.创建并启动容器(docker run 核心参数)
#-d:后台守护运行;--name:自定义容器名;-p 宿主机端口:容器内部端口 端口映射
#示例:本机8080访问nginx页面
docker run -d --name mynginx -p 8080:80 nginx:1.25

#-it:交互式前台运行,进入容器终端(用完exit退出)
docker run -it --name myubuntu ubuntu bash

#-e:设置容器环境变量(mysql密码配置)
docker run -d --name mysql57 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7

#-v:挂载宿主机D盘目录到容器目录(持久化数据,D:\nginx-html替换成你的文件夹)
docker run -d --name mynginx -p 8080:80 -v D:\nginx-html:/usr/share/nginx/html nginx:1.25

#--rm:容器停止自动删除(临时测试用)
docker run --rm hello-world

2.容器启停删除
#查看正在运行容器
docker ps
#查看全部容器(含已停止)
docker ps -a
#启动已停止容器
docker start mynginx
#优雅停止容器(等待程序收尾)
docker stop mynginx
#强制杀死容器(立刻断电,数据可能丢失)
docker kill mynginx
#重启容器
docker restart mynginx
#删除已停止容器,-f强制删运行中的容器
docker rm mynginx
docker rm -f mynginx
#批量删除所有停止容器
docker rm $(docker ps -aq)

3.进入运行中容器、查看日志
#进入正在运行容器终端
docker exec -it mynginx bash
#实时查看容器运行日志(-f持续刷新)
docker logs -f mynginx
#查看容器详细配置
docker inspect mynginx
#查看容器资源占用(CPU/内存)
docker stats

四、镜像仓库

1
2
3
4
5
6
7
8
9
#在docker hub搜索镜像
docker search mysql
#登录docker私有仓库(docker hub)
docker login
#退出登录
docker logout
#推送本地镜像到远程仓库(镜像名必须带仓库地址前缀)
docker tag nginx xxx/nginx:v1
docker push xxx/nginx:v1

7.案例

再开一个终端查看正在运行的容器,ps(process states)进程状态,第一个终端有很多日志,执行不了其他的操作,这个时候可以使用docker run -d nginx使容器在后台运行,不输出日志,这时候还可以在这个终端进行其他操作

查看容器进程

关闭启动的容器

删除容器

删除容器使用的指令是:docker rm 容器名(容器id)

删除正在运行的容器:docker rm -f 容器名(容器id)

删除镜像:docker rmi 镜像名(镜像id)

访问宿主机中的容器

docker运行的容器存在与宿主机中的容器中,所以需要用宿主机中的网络端口映射到容器中的网络端口,使用的命令是docker run -p 80:80 nginx

打开容器内部署的nginx

挂载卷:实现数据的持久化存储,把宿主机中的文件目录和容器内的文件目录进行绑定,宿主机中的文件数据改变会影响容器内文件目录的数据,容器内数据改变也会影响到宿主机,但是当删除容器的时候,宿主机的文件目录中的数据还存在,就不会影响数据的持久化存储

可以把网页放在宿主机的目录中(就是在html文件夹中创建一个index.html),这样容器中也有这个html文件了,再次访问宿主机80端口就能看到页面

命名卷挂载

8.Dockerfile文件

1.Dockerfile的作用

Dockerfile就是【打包规则说明书】,是一个文件脚本,用来自定义构建镜像。

业务场景:

当你开发好java代码之后需要打包成镜像部署到云服务器上

不用Dockerflie,传统部署,需要:

1.服务器手动安装 JDK17、Maven;

2.git 拉取代码,手动执行mvn package打包 jar;

3.手动写启动脚本java -jar xxx.jar;

4.换一台新服务器,所有步骤重来,版本、环境容易不一致。

使用Dockerfile部署:

Dockerfile 把安装 Maven、下载依赖、编译打包、精简运行环境全部写成标准化脚本。

1.任意机器拉取代码(带 Dockerfile);

2.执行 docker build -t spring-app:1.0 .

3.自动完成:下载 maven 镜像→缓存依赖→编译代码→生成极小的运行镜像;

4.服务器直接用镜像启动容器,不需要提前装 JDK、Maven。

以下面的Dockerfile文件为例:**

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 使用多阶段构建优化镜像大小
FROM maven:3.9-eclipse-temurin-17 AS builder

WORKDIR /app

# 复制 pom.xml 并下载依赖(利用 Docker 缓存)
COPY pom.xml .
RUN mvn dependency:go-offline -B

# 复制源代码并构建
COPY src ./src
RUN mvn clean package -DskipTests

# 运行阶段
FROM eclipse-temurin:17-jre-jammy

WORKDIR /app

# 复制构建产物,从builder阶段复制打包好的jar包到当前运行镜像,命名app.jar
COPY --from=builder /app/target/*.jar app.jar

# 暴露端口
EXPOSE 8080

# 启动应用
ENTRYPOINT ["java", "-jar", "app.jar"]

① builder编译打包阶段(只用于编译阶段,最终镜像会丢弃这一层)

  • maven:3.9-eclipse-temurin-17:内置 Maven 和完整 JDK,用来编译 Java 代码、打包 Jar
  • AS builder:给当前构建阶段的临时容器起别名,后面运行阶段可以通过--from=builder复制产物
  • WORKDIR /app:设置容器内工作目录,后续所有命令默认在/app下执行,本质是容器内部的一个文件夹,属于容器文件系统,不是宿主机(你的云服务器)上的文件夹

宿主机: 你 ssh 登录云服务器,ls / 看到的系统(服务器真实系统)

容器:docker 启动后独立隔离的文件系统,容器内的 /app 和宿主机目录互不干扰,如果你不写 WORKDIR,默认工作目录是 /(容器根目录)

查看容器里的/app目录:

1.先查看正在运行的容器

1
docker ps

2.进入容器

1
docker exec -it 容器名字/容器ID bash

此时你已经进入容器内部bash

3.现在你就在容器内,执行命令查看 /app

  • RUN mvn dependency:go-offline -B:提前拉取项目所有依赖包到本地仓库,离线打包,-B是批量模式,取消Maven交互输出,精简日志
  • 复制全部代码到临时容器之后,就执行打包RUN mvn clean package -DskipTests,-DskipTests跳过单元测试,加快打包速度,打包完成后/app/target/目录会生成可执行 springboot jar 包。

②运行阶段(最终交付的轻量化镜像)

1
2
# 选用纯JRE镜像(无完整JDK、无Maven),体积极小
FROM eclipse-temurin:17-jre-jammy

多阶段构建核心优势:

  • builder 阶段镜像包含 Maven、JDK、源码、依赖包,体积几百 MB;
  • 最终镜像只保留 JRE(运行 Java 程序最小环境)+ jar 包,体积压缩到几十 MB;
  • 编译工具、源码、maven 全部丢弃,减小镜像大小、降低漏洞风险。

核心流程就是:

启动临时构建容器,把pom.xml、源码src复制到容器内/app;

Maven 编译源码,在容器/app/target生成 jar 包;

构建完成后,整个 builder 环境默认全部销毁。

新建纯净 Java 运行环境镜像,手动从 builder 复制 jar 包;

最终镜像仅保留 JRE + app.jar,无源码、无编译工具;

启动容器执行java -jar,运行后端服务。

2.上传远程代码仓库

结论:强烈建议上传 Dockerfile 到代码仓库

原因:

环境统一:所有开发、运维人员拉取代码后,都能使用同一份 Dockerfile 构建完全一致的镜像,不会出现本地构建和服务器构建差异;

CI/CD 流水线必备:Jenkins/GitLab CI 等自动化部署工具,会自动拉取仓库代码,读取仓库内的 Dockerfile 自动打包镜像;

版本追溯:Dockerfile 随代码一同提交,镜像构建规则和业务代码版本绑定,回滚代码时同步回滚构建配置;

9.docker-compose.yml文件

1.该文件是什么

该文件相当于任务清单

里面记录去哪找 Dockerfile、端口、挂载、网络、依赖服务。

不用你手动敲docker build docker run两条命令,一条命令自动化串联。

直接手动输入docker compose up -d --build,它就会自动去找Dockerfile文件,自动构建镜像、根据镜像运行容器,完全不需要人手动再拉取镜像、创建并运行容器了

2.文件内容

下面是教程示例:

1.文件目录结构为:

1
2
3
4
5
6
7
8
9
项目根目录
├── docker-compose.yml # 编排主文件
├── .env # 环境变量配置(密钥、参数放这里)
├── backend
│ ├── Dockerfile # SpringBoot多阶段构建文件(你之前的那份)
│ ├── pom.xml
│ └── src
└── frontend
└── Dockerfile

2.docker-compose.yml文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# Docker Compose v2 写法,无需声明version
services:
# SpringBoot后端服务
backend:
build:
context: ./backend
dockerfile: Dockerfile
container_name: demo-backend
restart: always
environment:
SPRING_PROFILES_ACTIVE: prod
SERVER_PORT: 8080
DB_HOST: demo-mysql
DB_PORT: 3306
DB_NAME: demo_db
DB_USERNAME: root
DB_PASSWORD: ${MYSQL_ROOT_PASSWORD}
ports:
- "127.0.0.1:8080:8080" # 仅服务器本机访问,外网不能直接访问后端
depends_on:
mysql:
condition: service_healthy
networks:
- demo-network
deploy:
resources:
limits:
memory: 512M
cpus: "1"

# MySQL数据库
mysql:
image: mysql:8.0
container_name: demo-mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: demo_db
TZ: Asia/Shanghai
volumes:
- mysql-data:/var/lib/mysql
networks:
- demo-network
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5

# 前端服务
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
container_name: demo-frontend
restart: always
ports:
- "3000:80" # 唯一对外开放端口,公网IP:3000访问页面
depends_on:
- backend
networks:
- demo-network

# 持久化存储:容器删除数据不丢失
volumes:
mysql-data:

# 自定义容器内网
networks:
demo-network:
driver: bridge

3.配套.env配置文件

因为docker-compose.yml文件一般是要上传到仓库的,一些隐私信息就手动写在配置文件里面

1
MYSQL_ROOT_PASSWORD=Admin@123456

3.手把手部署教程

####1. 概念说明

docker-compose.yml是服务编排配置文件

可以一次性管理多个 Docker 容器:后端、数据库、前端。
一条命令完成:镜像构建 → 创建网络 → 启动容器。

区分两个核心配置

image:直接拉取官方现成镜像(MySQL、Redis)

build:读取 Dockerfile,编译构建我们自己的项目镜像

####2. 文件准备

  1. 在项目根目录创建 docker-compose.yml,复制上面内容
  2. 创建 .env 文件存放密码、密钥等变量
  3. backend 目录放入你的 SpringBoot 项目 + Dockerfile
  4. frontend 目录放入前端项目 + Dockerfile

####3. 核心配置讲解

1.build

1
2
3
build:
context: ./backend
dockerfile: Dockerfile

代表:去./backend文件夹,读取 Dockerfile 构建镜像

执行docker compose up -d --build时自动执行构建

2.container_name

自定义容器名称,同网络下容器可以直接使用名字互相访问

后端连接 mysql 地址:demo-mysql:3306,不用填ip

3.port端口映射(宿主机端口:容器内端口)

  • "127.0.0.1:8080:8080":只允许云服务器本机访问,外网无法访问(安全规范)

  • "3000:80":开放所有网络,公网可以直接访问,等价于0.0.0.0:3000:80

    端口映射 = 打通宿主机 ↔ 容器

    不需要对外访问的服务不要写 ports!

4.depends_on

设置服务启动顺序,等待数据库健康就绪后,再启动后端。

5.volumns数据卷

1
2
3
volumes:
mysql-data:
minio-data:

作用:Docker 托管的持久化存储目录。

  • 容器删除、重建,存放在 volume 内的数据不会丢失;
  • MySQL 数据库、文件存储必须挂载 volume,否则容器销毁数据全部清空。

挂载写法(在 service 内):

1
2
volumes:
- mysql-data:/var/lib/mysql

格式:数据卷名称:容器内路径

volumn相关命令:

1
2
3
4
5
6
# 查看所有数据卷
docker volume ls
# 删除容器但保留数据卷
docker compose down
# 删除容器 + 一并删除数据卷(谨慎!数据丢失)
docker compose down -v

6.networks

创建独立内网,所有服务加入同一网络,容器之间互通,外部无法随意访问。

service服务内:

1
2
networks:
- demo-network

把当前容器加入指定自定义网桥网络。
只有在同一个 network 中的容器,才能通过容器名互相通信。

服务外指定自定义网桥网络:

1
2
3
networks:
demo-network:
driver: bridge
  • driver: bridge:网桥模式(默认最常用)
  • Compose 会自动创建隔离的私有网络;
  • 只有加入该网络的容器才能互相访问;
  • 不同项目的 compose 网络互相隔离。

优势:

  • 服务之间使用容器名称通信,不用维护 IP;
  • 默认隔离,外部容器无法接入;
  • 方便控制集群内部通信。

7.expose

1
2
expose:
- "4000"

仅仅声明容器内部使用的端口,不会映射到宿主机。
仅同一网络内其他容器可访问,外部无法连接,纯内网服务使用。

####4. 常用命令(重点)

1)构建镜像 + 后台启动全部服务(最常用)

1
docker compose up -d --build
  • up:创建并启动容器
  • -d:后台运行
  • --build:自动检测 Dockerfile,重新构建镜像(修改代码后必须执行)

2)查看运行中的容器

1
docker compose ps

3)实时查看日志

1
2
3
docker compose logs -f
# 只看后端日志
docker compose logs -f backend

4)停止服务(容器保留)

1
docker compose stop

5)停止并删除容器(数据卷不会删除)

1
docker compose down

6)彻底删除容器 + 数据(谨慎!数据库数据清空)

1
docker compose down -v

####5. 完整部署流程

1.将整套项目上传至云服务器

2.进入docker-compose.yml所在根目录

3.修改.env 内数据库密码

4.执行启动命令: docker compose up -d --build

5.浏览器访问 服务器IP:3000 打开前端页面

6.重要注意事项

1.修改后端代码后,必须重新执行 docker compose up -d –build,重新构建镜像生效;单纯重启容器不会更新代码。

2..env文件不要上传代码仓库,防止密钥泄露。

3.数据库没有对外开放端口,外部工具无法直连 MySQL,只能容器内部访问;如需调试,使用:docker exec -it demo-mysql mysql -u root -p。

4.所有服务之间通信使用容器名称,不要使用服务器 IP。