文章目录
Docker 简介
Docker 是一个开源的容器化平台,它允许开发者将应用程序及其依赖打包到一个轻量级、可移植的容器 中,然后在任何运行 Docker 的环境中一致地运行。
如果说虚拟机是"装修好的整间新房 "(需要独立地基、水电),那么 Docker 就是"宜家的模块化储物箱"(即拿即用、可叠放、搬家直接抱走)。
核心概念
| 概念 | 通俗解释 | 核心特点 | 类比 |
|---|---|---|---|
| 镜像(Image) | 容器的「模板」,包含运行应用所需的代码、依赖、配置(如 nginx 镜像) | 只读、分层存储、可复用 | 面向对象中的「类」 |
| 容器(Container) | 镜像的「运行实例」,是独立的运行环境(启动镜像即创建容器) | 可读写、独立隔离、生命周期可控 | 面向对象中的「对象」 |
| 数据卷(Volume) | 用于容器数据持久化的目录,独立于容器生命周期 | 持久化、可共享、跨容器使用 | 容器的「外部硬盘」 |
| 仓库(Registry) | 存储镜像的仓库(如 Docker Hub 公有仓库,Harbor 私有仓库) | 拉取/推送镜像、私有/公有部署 | 镜像的「GitHub」 |
| Dockerfile | 构建自定义镜像的「脚本文件」,定义镜像的构建步骤 | 代码化构建、可版本控制、可复用 | 镜像的「配方」 |
| Docker Compose | 定义和运行多容器应用的「编排文件」(YAML 格式) | 一键启停、依赖管理、环境隔离 | 应用的「说明书」 |
| 网络(Network) | 容器间通信的「虚拟通道」,实现容器隔离与互联 | 隔离、可自定义、支持多驱动 | 容器的「路由器」 |
主要优势
环境一致 :解决"在我机器上能跑"的问题,开发、测试、生产环境无差异。
轻量高效 :共享宿主机操作系统内核,比传统虚拟机启动快(秒级),占用资源小。
可移植性 :一次打包,可在任何支持 Docker 的系统(Linux、Windows、macOS)运行。
简化配置 :通过 Dockerfile 和 docker-compose.yml 轻松管理应用依赖和服务编排。
隔离性:每个容器拥有独立的文件系统、网络和进程空间,互不干扰。
Docker vs 传统虚拟机
| 特性 | Docker 容器 | 传统虚拟机 |
|---|---|---|
| 启动速度 | 秒级 | 分钟级 |
| 磁盘占用 | MB 级 | GB 级 |
| 性能损耗 | 几乎为零 | 较高 |
| 隔离级别 | 进程级隔离 | 完全系统隔离 |
| 内核共享 | 共享宿主机内核 | 每个 VM 独立内核 |
常见使用场景
| 场景 | 说明 | 典型例子 |
|---|---|---|
| 开发环境统一 | 让团队所有成员的开发环境完全一致,避免"在我电脑上能跑"的问题 | 前端:Node.js + Redis + MySQL 一键启动 |
| 微服务架构 | 每个服务独立打包成镜像,独立部署、升级、伸缩 | 订单服务、用户服务、支付服务各跑一个容器 |
| CI/CD 流水线 | 在自动化构建、测试、部署流程中使用容器隔离环境 | Git push 触发构建镜像 → 推送到仓库 → 自动部署 |
| 应用打包分发 | 将应用及其所有依赖打包成一个镜像,随处运行 | 内部工具打包分发,客户直接 docker run |
| 快速搭建中间件 | 无需安装配置,一行命令启动数据库、缓存等 | docker run -d redis、docker run -d mysql |
| 本地测试/实验 | 临时运行某个环境,用完即删,不影响宿主机 | 测试不同版本 Python、尝试新软件 |
Windows 上安装 Docker
最官方和推荐的方法是安装 Docker Desktop。它会提供一个完整的图形化管理界面,并在后台帮你配置好运行环境。整个过程主要分为以下三步:
第一步:检查 Windows 系统
- 操作系统:
Windows 11/10 :需要 22H2 或更高版本
💡 如何检查系统信息?
可以按Win + R键,输入winver并回车,在弹出的窗口中就能看到详细的系统版本和内部版本号。 - 硬件要求:
- 64位处理器,且必须支持并已在 BIOS/UEFI 设置中开启硬件虚拟化(即 Intel VT-x 或 AMD-V,验证方法:打开任务管理器→"性能"选项卡→查看"虚拟化"是否显示"已启用")。
- 系统内存至少 4 GB(强烈建议 8 GB 以上)。
第二步:安装并配置WSL 2后端
- 启用 WSL 2 功能 :以管理员身份打开 PowerShell 或命令提示符,输入以下命令并回车
bash
wsl --install
这个命令会自动完成安装 WSL 所需的一切(包括Linux内核和设置为WSL 2)。安装完成后,根据提示重启电脑。
- 更新 WSL 内核:打开命令行,运行以下命令确保WSL是最新版本:
bash
wsl --update
第三步:下载并安装 Docker Desktop
-
下载安装程序:前往 Docker 官方下载页面,下载 Docker Desktop for Windows 的稳定版安装程序。Intel Core i3/i5/i7/i9、AMD Ryzen 系列选 AMD64 版本。
Docker 官方虽未在首页提供历史版本的下载入口,但其发布页面和文档中仍保留了部分历史信息。访问 Docker Desktop 官方发布说明页面:Docker 官方维护了Windows 的 Release Notes 页面,其中包含了每个版本的发布说明和对应的下载链接。
-
运行安装程序:
找到下载的
Docker Desktop Installer.exe,双击运行,点击 "OK",等待安装完成。 -
完成安装并验证:
- 安装完成后,点击 "Close" 并重启电脑(如果被提示的话)。
- 重启后,从开始菜单启动 Docker Desktop。
- 程序启动后,你可以在任务栏通知区域看到一个鲸鱼图标的 Docker 标志。
- 打开命令行(PowerShell 或 CMD),输入以下命令验证是否安装成功:
bashdocker --version docker run hello-world
在docker run hello-world出现错误 A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.这是由于网络原因,直接从 Docker Hub 拉取镜像可能会非常慢或失败,需要配置国内镜像加速器,配置步骤:
-
打开 Docker Desktop,点击右上角的 Settings(⚙️图标)
-
选择左侧菜单的 Docker Engine
-
在配置文件中添加 registry-mirrors 项:
json"registry-mirrors": [ "https://docker.1ms.run", "https://docker.xuanyuan.me" ]上面是毫秒镜像和轩辕镜像的镜像源,免费且无需注册。
-
点击右下角的 Apply & Restart 按钮
-
再次运行 docker run hello-world 测试,看到镜像被正常拉取并打印出 Hello from Docker! 的欢迎信息,说明配置成功了。

Docker使用
一、镜像管理
| 命令 | 作用 | 示例 | 注意事项 |
|---|---|---|---|
| docker pull 镜像名:标签 | 拉取镜像(默认从 Docker Hub) | docker pull nginx:1.24 | 标签省略默认拉取 latest(不稳定),建议指定版本 |
| docker images | 查看本地所有镜像 | docker images | 加 -q 只显示镜像 ID:docker images -q |
| docker rmi 镜像ID/镜像名 | 删除镜像(需先删依赖容器) | docker rmi nginx:latest | 强制删除:docker rmi -f 镜像ID(如果有容器在使用。谨慎,避免删错) |
| docker save -o 文件名.tar 镜像 | 导出镜像为压缩包 | docker save -o nginx.tar nginx | 可批量导出:docker save -o apps.tar nginx:latest hello-world:latest |
| docker load -i 文件名.tar | 导入本地镜像包 | docker load -i nginx.tar | 导入后自动保留原标签,无需重新打标签 |
| docker search 镜像名 | 搜索 Docker Hub 镜像 | docker search nginx | 加 --filter=stars=1000 筛选高星镜像:docker search --filter=stars=1000 nginx |
| docker tag 原镜像 新镜像:标签 | 给镜像打新标签(用于推送私有仓库) | docker tag hello-world:latest localhost:5000/my-hello:test | 推送前必须打仓库地址标签 |
| docker push 镜像名:标签 | 推送镜像到仓库 | docker push localhost:5000/my-hello:test |
二、容器管理
| 命令 | 作用 | 示例 | 扩展说明 |
|---|---|---|---|
| docker run [参数] 镜像 | 创建并启动容器 | docker run -d -p 80:80 --name nginx nginx | 核心参数见下表 |
| docker ps | 查看运行中的容器 | docker ps | 加 -a 查看所有容器(含停止的);加 -q 只显示 ID |
| docker start/stop/restart 容器ID/名 | 启动 / 停止 / 重启容器 | docker restart nginx | 批量操作:docker start $(docker ps -aq)(启动所有容器,注意 在Linux/macOS 的 Bash 终端支持,但是Windows 中的PowerShell和CMD不支持) |
| docker rm 容器ID/名 | 删除容器(需先停止) | docker rm nginx | 强制删除运行中容器:docker rm -f nginx |
| docker exec -it 容器ID/名 命令 | 进入容器执行命令(交互模式) | docker exec -it nginx /bin/bash | 非交互执行:docker exec nginx ls /usr/share/nginx/html |
| docker logs -f 容器ID/名 | 实时查看容器日志 | docker logs -f nginx | 加 --tail=100 只看最后 100 行:docker logs --tail=100 -f nginx |
| docker inspect 容器ID/名 | 查看容器详细信息(IP、挂载等) | docker inspect nginx | 过滤查看 IP:docker inspect -f '{{.NetworkSettings.IPAddress}}' nginx |
| docker rename 旧名 新名 | 容器重命名 | docker rename nginx nginx-proxy | 重命名不影响容器运行 |
| docker cp 主机路径 容器ID:容器路径 | 主机→容器拷贝文件 | docker cp index.html nginx:/usr/share/nginx/html | 反向拷贝(容器→主机):docker cp nginx:/usr/share/nginx/html/index.html ./ |
| docker export 容器ID -o 文件名.tar | 导出容器为镜像包(仅含文件系统) | docker export nginx -o nginx-container.tar | 与 save 区别:save 存镜像(分层),export 存容器(扁平) |
| docker import 文件名.tar 新镜像:标签 | 导入容器包为镜像 | docker import nginx-container.tar my-nginx:1.0 | 导入后需重新指定启动命令-g "daemon off;" |
docker run 核心参数(细化说明)
| 参数 | 作用 | 示例 | 实用场景 |
|---|---|---|---|
| -d | 后台运行容器(守护进程模式) | -d | 生产环境必加,避免终端关闭容器停止 |
| -p | 端口映射(主机:容器) | -p 8080:8080 | 多个端口映射:-p 80:80 -p 443:443 |
| -P | 随机映射容器暴露的所有端口 | -P | 测试场景,无需手动指定端口 |
| --name | 指定容器名称(唯一) | --name my_web | 便于管理,避免默认随机名称 |
| -e | 设置环境变量 | -e MYSQL_ROOT_PASSWORD=123456 | 多个变量:-e KEY1=VAL1 -e KEY2=VAL2 |
| -v | 挂载数据卷 / 目录 | -v nginx-vol:/usr/share/nginx/html | 权限控制::ro 只读,:rw 读写(默认) |
| --network | 指定容器网络 | --network my-net | 自定义网络实现容器名互通 |
| --restart | 容器重启策略 | --restart always | 可选值:always(始终重启)、on-failure(失败时重启)、no(不重启) |
| --memory | 限制容器内存 | --memory 1G | 防止容器占用过多主机资源 |
| --cpus | 限制容器 CPU 核心数 | --cpus 2 | 限制使用 2 个核心,小数也可:--cpus 1.5 |
| --privileged | 赋予容器主机特权(慎用) | --privileged | 需访问主机硬件 / 内核时使用 |
- 示例:运行一个 Web 服务器
bash
# 1. 后台运行 Nginx,将 80 端口映射到主机的 8080
docker run -d --name my-nginx -p 8080:80 nginx
# 2. 验证:打开浏览器访问 http://localhost:8080,应该能看到 Nginx 欢迎页
# 3. 查看日志
docker logs my-nginx
# 4. 进入容器内部修改默认页面
docker exec -it my-nginx bash
# 进入后执行:
echo "<h1>Hello from Docker</h1>" > /usr/share/nginx/html/index.html
exit
# 5. 刷新浏览器,会看到修改后的内容
# 6. 停止并删除容器
docker stop my-nginx
docker rm my-nginx
三、Dockerfile(构建自己的镜像)
Dockerfile 就是一个文本文件,其中包含一个个的指令(Instruction),用指令来说明要执行什么操作来构建镜像。每一个指令都会形成一层Layer。
| 指令 | 作用 | 示例 | 注意事项 |
|---|---|---|---|
| FROM | 指定基础镜像(必选,第一行) | FROM python:3.9-slim | 优先选轻量镜像(alpine < 10MB),减少体积 |
| RUN | 构建时执行命令(分层构建) | RUN pip install | 多命令合并用 &&,减少分层:RUN yum update && yum install -y nginx && yum clean all |
| COPY | 复制主机文件到容器(本地→容器) | COPY app.py . | 支持通配符:COPY *.jar /app/;路径必须是构建上下文内的文件 |
| ADD | 复制文件(支持解压、URL) | ADD app.tar.gz /usr/local/ | 慎用 URL 下载(增加镜像体积),建议用 RUN wget |
| WORKDIR | 设置工作目录(后续指令的默认目录) | WORKDIR /app | 自动创建不存在的目录,推荐用绝对路径 |
| ENV | 设置环境变量(构建 / 运行时均生效) | ENV JAVA_HOME /usr/local/jdk8 | 引用变量:ENV PATH $JAVA_HOME/bin:$PATH |
| EXPOSE | 声明容器端口(仅说明,无映射) | EXPOSE 8080 | 仅为文档说明,运行时仍需 -p 映射 |
| CMD | 容器启动时执行命令(可被覆盖) | CMD ["nginx", "-g", "daemon off;"] | 仅最后一个 CMD 生效;运行时可覆盖:docker run 镜像 自定义命令 |
| ENTRYPOINT | 容器启动时执行命令(不可被覆盖) | ENTRYPOINT ["java", "-jar"] | 结合 CMD 传参:ENTRYPOINT ["java", "-jar"] + CMD ["app.jar"] |
| VOLUME | 声明数据卷(建议运行时再挂载) | VOLUME ["/data"] | 运行时可通过 -v 覆盖:docker run -v 卷名:/data 镜像 |
| USER | 指定容器运行用户 | USER nginx | 需先在镜像中创建用户:RUN useradd -m nginx |
-
示例:构建一个简单的 Python Web 应用
-
创建项目文件夹:
bashmkdir my-python-app cd my-python-app -
创建
app.py:pythonfrom flask import Flask app = Flask(__name__) @app.route('/') def hello(): return 'Hello from Docker!' if __name__ == '__main__': app.run(host='0.0.0.0', port=5001) -
创建
Dockerfile:text# 使用 Python 3.9 作为基础镜像 FROM python:3.9-slim # 设置工作目录 WORKDIR /app # 复制依赖文件 COPY requirements.txt . # 安装依赖 RUN pip install --no-cache-dir -r requirements.txt # 复制应用代码 COPY app.py . # 暴露端口 EXPOSE 5001 # 启动命令 CMD ["python", "app.py"] -
创建
requirements.txt:textflask -
构建并运行:
bash# 构建镜像(注意最后的 . 表示当前目录) docker build -t my-python-app . # 运行容器 docker run -d -p 8000:5001 --name my-app my-python-app # 访问 http://localhost:8000 查看效果
-
-
示例:Docker中运行jar包:
-
准备工作
创建一个专门的目录(例如my-docker-app),并将 JAR 包放入其中。text/my-docker-app ├── Dockerfile # 没有后缀名 └── user-service-1.0.0.jar -
编写 Dockerfile:
text# 第一阶段:使用官方的 OpenJDK 运行时作为一个轻量级的父镜像 # 推荐使用 eclipse-temurin(原 AdoptOpenJDK)或官方的 openjdk 镜像 FROM eclipse-temurin:11-jre-alpine # 在镜像中创建一个目录来存放我们的应用程序 WORKDIR /app # 将宿主机的 JAR 文件复制到镜像中的工作目录下,并重命名为 app.jar # 第一个参数是宿主机文件,第二个参数是镜像内路径 COPY user-service-0.0.1-SNAPSHOT.jar app.jar # 声明容器运行时暴露的端口号,这个数字必须和你的 Spring Boot 应用配置的服务器端口一致 EXPOSE 8081 # 指定容器启动时运行的命令,使用 java -jar 命令来启动我们的应用程序 ENTRYPOINT ["java", "-jar", "app.jar"] # 可以添加额外的 JVM 参数,例如设置内存或启用调试 # ENTRYPOINT ["java", "-Xmx256m", "-jar", "app.jar"] -
构建 Docker 镜像
在包含 Dockerfile 和 jar 包的目录下,打开终端(命令行),执行以下命令:bashdocker build -t user-service-app:1.0.0 .-t user-service-app:1.0.0:为镜像指定一个名称和标签(tag),格式为名称:标签。
.:表示当前目录是构建上下文(Context),Docker 会查找当前目录下的 Dockerfile。 -
运行 Docker 容器
镜像构建成功后,就可以通过镜像来创建并运行容器了:bashdocker run -d -p 8081:8081 --name my-running-app user-service-app:1.0.0通过访问 http://localhost:8081 查看效果。
-
四、Docker Compose(多容器编排)
当需要多个服务配合时(如 Web + Redis + MySQL),使用 docker-compose.yml。
| 命令 | 作用 | 示例 | 扩展说明 |
|---|---|---|---|
| docker-compose up | 创建并启动所有容器(前台) | docker-compose up | 加 -d 后台运行:docker-compose up -d |
| docker-compose up -d --build | 构建镜像并启动容器 | docker-compose up -d --build | 镜像有更新时强制重新构建 |
| docker-compose down | 停止并删除容器、网络(保留数据卷) | docker-compose down | 加 -v 删除数据卷:docker-compose down -v(谨慎) |
| docker-compose ps | 查看 Compose 管理的容器 | docker-compose ps | 加 -a 查看所有(含停止的) |
| docker-compose logs | 查看容器日志 | docker-compose logs nginx | 加 -f 实时查看:docker-compose logs -f tomcat |
| docker-compose restart | 重启指定 / 所有容器 | docker-compose restart mysql | 重启所有:docker-compose restart |
| docker-compose stop/start | 停止 / 启动容器 | docker-compose stop | 仅停止容器,不删除 |
| docker-compose exec | 进入指定容器 | docker-compose exec nginx bash | 等同于 docker exec,无需记容器名 |
| docker-compose build | 构建指定 / 所有镜像 | docker-compose build tomcat | 加 --no-cache 无缓存构建:docker-compose build --no-cache |
-
示例:搭建一个访客计数器系统,包含三个服务:
- 前端 Web:显示访问次数,每次刷新页面数字 +1
- 后端 API:处理计数逻辑,提供 REST API
- Redis:存储计数值(内存数据库)
完整项目结构,创建一个新目录,比如 demo-compose,然后创建以下文件:
textdemo-compose\ (项目根目录) ├── docker-compose.yml ├── web\ │ ├── index.html │ └── nginx.conf └── api\ ├── Dockerfile ├── requirements.txt └── app.py-
创建前端页面 (web/index.html)
html<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Docker Compose 演示 - 访客计数器</title> <style> body { font-family: Arial; text-align: center; margin-top: 50px; } .count { font-size: 48px; font-weight: bold; color: #2c3e50; } button { padding: 10px 20px; font-size: 16px; cursor: pointer; } .log { margin-top: 30px; font-size: 12px; color: #7f8c8d; } </style> </head> <body> <h1>🐳 Docker Compose 演示</h1> <p>每次刷新页面,计数器 +1</p> <div class="count" id="count">加载中...</div> <button onclick="refresh()">🔄 手动刷新</button> <div class="log" id="log"></div> <script> function refresh() { fetch('/api/count') .then(res => res.json()) .then(data => { document.getElementById('count').innerHTML = data.count; document.getElementById('log').innerHTML = `最后更新: ${new Date().toLocaleTimeString()} | 数据来自 Redis`; }) .catch(err => { document.getElementById('count').innerHTML = '连接失败'; }); } refresh(); setInterval(refresh, 2000); </script> </body> </html> -
创建后端 API (api/app.py)
pythonfrom flask import Flask, jsonify from flask_cors import CORS import redis import os app = Flask(__name__) CORS(app) # 连接到 Redis(通过服务名 "redis") r = redis.Redis(host='redis', port=6379, decode_responses=True) @app.route('/api/count') def get_count(): # 计数器 +1 count = r.incr('visitor_count') print(f"✅ 收到请求,当前计数: {count}") # 这行会显示在 docker logs 中 return jsonify({'count': count}) if __name__ == '__main__': app.run(host='0.0.0.0', port=5005) -
创建 requirements.txt (api/requirements.txt)
textflask redis flask-cors -
创建 docker-compose.yml
yamlversion: '3.8' services: # Redis 服务(存储数据) redis: image: redis:alpine container_name: demo-redis restart: always ports: - "6379:6379" # 可选,方便外部查看 networks: - demo-network # API 服务(后端逻辑) api: build: ./api container_name: demo-api restart: always ports: - "5005:5005" depends_on: - redis networks: - demo-network # 显式声明启动命令,确保能看到打印日志 command: python app.py # Web 服务(前端界面) web: image: nginx:alpine container_name: demo-web restart: always ports: - "8080:80" volumes: - ./web:/usr/share/nginx/html:ro # 静态文件挂载 - ./web/nginx.conf:/etc/nginx/conf.d/default.conf:ro # 配置文件挂载 depends_on: - api networks: - demo-network networks: demo-network: driver: bridgevolumes 挂载语法基本格式:
yamlvolumes: - "宿主机路径:容器内路径:可选参数" -
创建 API 的 Dockerfile (api/Dockerfile)
textFROM python:3.9-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY app.py . # 确保 Python 输出不缓冲,这样日志能实时显示 ENV PYTHONUNBUFFERED=1 CMD ["python", "app.py"] -
创建 Nginx 配置文件 web/nginx.conf
nginxserver { listen 80; server_name localhost; # 静态文件(前端页面) location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; } # API 请求转发到后端服务 location /api/ { proxy_pass http://api:5005; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } -
运行体验
bash# 1. 启动所有服务(-d 后台运行) docker compose up -d # 2. 查看实时日志(关键!能清楚看到服务间通信) docker compose logs -f执行后会看到如下日志:

打开浏览器 :访问 http://localhost:8080每刷新一次页面(或等待2秒自动刷新),网页上会看到:
- 网页上的数字 +1
- 终端日志中同时出现 ✅ 收到请求,当前计数: X
该案例中包含了如下特性:
特性 通过这个案例如何直观感受 服务发现 API 代码中用 host='redis' 连接,而不是 IP 地址 依赖管理 depends_on 确保 Redis 先于 API 启动 网络隔离 三个服务在同一个 demo-network 中互通 一键启动 一个命令启动 3 个服务,无需手动 docker run 3 次 日志聚合 docker compose logs -f 看到所有服务的输出混在一起 声明式配置 整个系统架构写在 YAML 文件中,可版本控制
五、数据管理
Docker Volume 是一种用于在容器之间共享和持久化数据的存储机制。与绑定挂载 不同,Docker Volume 是完全由 Docker 管理的,独立于宿主机的文件系统 ,提供了更高的灵活性和安全性。Volume 可以存储在宿主机的文件系统中,也可以通过网络文件系统(如 NFS)或云存储服务进行远程存储。使用 Docker Volume,容器可以在不同的生命周期中共享数据,这在需要持久化存储(如数据库数据、日志文件等)或在多个容器之间共享文件时特别有用。Docker 提供了多种与 Volume 相关的命令,允许用户创建、管理和删除卷。此外,Volume 的隔离特性确保了宿主机和容器之间的安全性,减少了对宿主机文件系统的依赖,从而提高了应用的可移植性和数据的可靠性。
| 命令 | 作用 | 示例 | 扩展说明 |
|---|---|---|---|
| docker volume create | 创建数据卷 | docker volume create my-data | 可指定驱动和选项 |
| docker volume ls | 列出所有数据卷 | docker volume ls | 加 -q 只显示ID,加 -f 过滤 |
| docker volume inspect | 查看数据卷详情 | docker volume inspect my-data | 显示挂载点、驱动等信息 |
| docker volume rm | 删除数据卷 | docker volume rm my-data | 只能删除未被使用的卷 |
| docker volume prune | 删除所有未使用的卷 | docker volume prune | 加 -f 跳过确认,加-a 删除所有未挂载的卷 |
挂载类型对比
| 类型 | 管理方式 | 位置 | 适用场景 | 示例 |
|---|---|---|---|---|
| 数据卷(Volume) | Docker 管理 | C:\ProgramData\Docker\volumes\(Win) | 生产环境、数据持久化 | -v my-data:/app/data |
| 绑定挂载(Bind Mount) | 用户管理 | 宿主机任意路径 | 开发环境、配置文件注入 | -v ./local:/app/config(当前目录(./)下的 local 文件夹映射到容器内的/app/config目录中) |
| 临时挂载(tmpfs) | 内存 | 内存 | 临时缓存、敏感数据 | --tmpfs /app/tmp |
-
案例:Redis 数据持久化
启动一个 Redis 容器,写入数据后删除容器,重新创建后数据依然存在。项目结构:
textredis-demo/ └── docker-compose.yml-
创建 docker-compose.yml
yamlversion: '3.8' services: redis: image: redis:alpine container_name: my-redis restart: always ports: - "6379:6379" volumes: - ./data:/data # 关键:数据持久化 -
启动并测试
bash# 启动容器 docker compose up -d # 进入 Redis 写入数据 docker exec -it my-redis redis-cli # 在 Redis 命令行中执行: SET mykey "Hello Docker" GET mykey EXIT # 删除容器(模拟故障或升级) docker compose down # 重新创建容器 docker compose up -d # 再次进入 Redis,数据还在! docker exec -it my-redis redis-cli GET mykey # 应该返回 "Hello Docker"
-
六、搭建私有仓库
在 Docker 中创建一个本地的私有仓库
- 第一步:快速启动一个本地仓库
在命令行窗口中执行以下命令,它会下载并运行一个私有仓库容器:
bash
docker run -d --name my-registry -p 5000:5000 --restart=always registry:2
命令参数详解 :
-d:在后台运行容器。
--name my-registry:给容器命名为 my-registry,方便管理。
-p 5000:5000:将宿主机的 5000 端口映射到容器的 5000 端口。这样你就可以通过 localhost:5000 访问仓库了。
--restart=always:设置容器在 Docker 重启后自动启动,比较方便。
registry:2:使用官方 Registry 服务的第 2 版镜像。
关于数据持久化
上面的命令没有挂载数据卷。这意味着,如果你删除这个 my-registry 容器,里面存储的所有镜像也会随之丢失。
如果希望保存镜像数据,可以在 docker run 命令中添加 -v /your/data/path:/var/lib/registry 参数,将容器内的镜像存储目录映射到电脑的硬盘上。例如:docker run -d --name my-registry -p 5000:5000 --restart=always -v D:/demo/docker/v:/var/lib/registry registry:2
验证仓库是否启动成功:
执行以下命令,如果返回 {},说明仓库已经成功运行。
bash
curl http://localhost:5000/v2/_catalog
-
第二步:配置 Docker 允许 HTTP 访问
Docker 出于安全考虑,默认只允许通过 HTTPS 访问仓库。但我们自己搭建的本地测试仓库用的是 HTTP,所以需要手动将其设置为"可信的"仓库(insecure-registries)。- 打开 Docker Desktop,点击顶部导航栏的 设置 (Settings) 图标(⚙️)。
- 从左侧菜单中选择 Docker Engine。
- 在 JSON 配置中,添加或修改 insecure-registries 字段:
json{ "builder": { "gc": { "defaultKeepStorage": "20GB", "enabled": true } }, "experimental": false, "insecure-registries": [ "localhost:5000" ], "registry-mirrors": [ "https://docker.1ms.run", "https://docker.xuanyuan.me" ] }- 点击界面右下角的 Apply & Restart 按钮,Docker 会自动重启以使配置生效。
七、释放空间
Docker 使用了"写时复制"(Copy-on-Write)机制和分层存储,删除镜像并不会立即释放磁盘空间给主机系统,这些空间会被 Docker 保留以供后续使用。
- 释放磁盘空间:
-
方法一:通过 Docker Desktop GUI 清理
- 打开 Docker Desktop
- 找到Troubleshoot(故障排除),点击
Clean / Purge data
-
方法二:使用命令行清理
bash# 删除所有停止的容器、未使用的网络、悬挂镜像和构建缓存 docker system prune # 单独删除悬挂镜像(none标签的) docker image prune # 删除所有未被任何容器引用的镜像 docker image prune -a # 更加彻底的清理(包括未使用的镜像和卷,需要确认) docker system prune -a --volumes
-
总结
Docker 通过容器化技术,让应用交付变得更简单、可靠、高效,已成为现代云原生开发和 DevOps 实践的基石工具。