Docker 核心使用教程

#工具

一、Docker 的核心价值与场景

Docker 是目前最成熟、高效的软件部署技术。它主要解决了软件开发与运维中的三大核心痛点:

01- 消除底层系统的差异

02- 实现轻量级的环境隔离

03- 解决交付与迁移的一致性

二、Docker 的安装 (Windows 环境)

Docker Desktop on Windows 依赖于 WSL 2 (Windows Subsystem for Linux)。

01- 安装前置准备

  1. 网络设置:开启 VPN 并启用 Tun 模式

关键步骤,解决国内镜像拉取失败问题。

  1. 升级 WSL: 在 PowerShell 中执行:
wsl --update

02- 下载与安装

winget install Docker.DockerDesktop

个人喜欢命令行安装,简单高效。

03- 初始化与验证

安装完成后重启计算机,打开 Docker Desktop 并建议完成以下配置:

验证安装:打开终端(PowerShell 或 CMD),输入以下命令

docker run hello-world

如果看到以下输出,说明安装成功:

Hello from Docker! This message shows that your installation appears to be working correctly.

三、单容器创建与管理实战

01- 核心命令:docker run 详解

docker run 是 Docker 中最核心的命令。它实际上是一个组合命令,一步完成了三个动作:

  1. Pull: 拉取镜像(如果本地没有)。
  2. Create: 创建容器。
  3. Start: 启动容器。

命令示例

docker run -d --name c1 -p 80:80 docker.io/library/caddy:2.10.2-alpine

参数拆解

02- 端口映射的深度理解 (-p)

docker run -p 80:80 中的 -p 代表 Publish(发布),允许映射一个或多个端口。

映射规则宿主机端口:容器内端口

💡 独家记忆法:数据流向与写字顺序一致 数据从外部流入,就像我们写字一样,从左往右。 请求 -> 左边(本机/墙) -> 右边(容器/屋里)。

多容器场景: 宿主机端口不能重复占用,但容器端口互不影响。

03- 镜像名称的完整结构

命令中的 docker.io/library/caddy:2.10.2-alpine 是镜像的完全体形态。

结构拆解

  1. 仓库名 (Registry): docker.io

    • 默认是 Docker Hub 官方仓库,可省略。
  2. 命名空间 (Namespace): library

    • 官方镜像的默认空间,可省略。如果是个人镜像,这里是用户名。
  3. 镜像名 (Image): caddy

    • 核心名称,不可省略。
  4. 版本标签 (Tag): 2.10.2-alpine

    • 指定版本。如果不写,默认使用 :latest(最新版)。

极简写法:

如果是官方仓库、官方镜像、且用最新版,命令可简化为:

docker run -d --name c1 -p 80:80 caddy

04- 常用容器管理命令清单

验证容器是否运行成功,可访问浏览器 localhost:80,或使用以下命令:

容器生命周期管理

docker ps # 查看正在运行的容器
docker ps -a # 查看所有容器(含已停止的),-a = --all
docker stop <ID/名> # 停止容器
docker start <ID/名> # 启动容器
docker rm <ID/名> # 删除已停止的容器
docker rm -f <ID/名> # 强制删除正在运行的容器 (-f = force)

镜像管理

docker images # 查看本地已下载的镜像
docker rmi <ID/名> # 删除本地镜像 (Remove Image)

注意:删除镜像前,必须先删除所有基于该镜像创建的容器(哪怕是停止状态的)。

系统清理

docker system prune -a

功能:一键清理所有未使用的对象(停止的容器、未使用的网络、悬空的镜像等),释放空间神器。

四、数据持久化 (Data Persistence)

容器的文件系统是临时的。一旦容器被删除,其内部的所有数据(配置文件、日志、用户上传文件)都会永久丢失。为了保存数据,我们需要将数据“锚定”到宿主机上。

01- 绑定挂载 (Bind Mounts)

docker run -d --name c2 -p 80:80 \
-v D:\docker_cache\html:/usr/share/caddy/ \
caddy

02- 命名卷 (Volumes)

# 1- 创建卷
docker volume create my-data-volume
# 2- 挂载卷 (左边卷名, 右边目录名)
docker run -d --name c2 -p 80:80 \
-v my-data-volume:/usr/share/caddy/ \
caddy

(注:如果卷不存在,Docker 会自动创建,但推荐手动管理)

03- 常用卷管理命令

docker volume ls # 列出所有卷
docker volume inspect <卷名> # 查看卷的物理存储位置
docker volume rm <卷名> # 删除卷
docker volume prune # 清理所有未被容器引用的“孤儿卷”

五、容器间通信 (Networking)

在微服务架构中(如:前端+后端+数据库),容器之间需要相互交流。

01- 核心机制:自定义子网

最佳实践是创建一个自定义网络(User-defined Network)。在同一个自定义网络下的容器,可以通过容器名直接相互访问(Docker 内置了 DNS 解析)。

步骤 1:创建网络

docker network create my-app-net

步骤 2:启动容器并加入网络

以“应用 + 数据库”为例:

docker run -d --name db \
--network my-app-net \
-e MYSQL_ROOT_PASSWORD=secret \
mysql:8.0
docker run -d --name app \
--network my-app-net \
-p 80:80 \
caddy

步骤 3:容器互联

在 app 容器的代码配置中,连接数据库的 Host 地址直接填写:db 即可(无需关心 IP)。

02- 网络生命周期管理命令

docker network ls # 列出网络
docker network inspect <网络名> # 查看网络详情(含已连接容器IP)
docker network rm <网络名> # 删除网络

动态网络操作(热插拔) 与挂载卷不同,网络可以在容器运行时动态调整:

docker network connect <网络名> <容器名> # 让运行中的容器加入新网络
docker network disconnect <网络名> <容器名> # 让运行中的容器断开网络

03- 关键差异总结:存储 vs 网络

这是很多新手容易忽略的架构特性:

特性数据挂载 (Volumes/Mounts)网络连接 (Networks)
时机静态:必须在 docker run 创建容器指定动态:可以在容器运行随时加入或断开
修改容器创建后无法更改挂载点(需删除重建容器)容器创建后可以使用 connect/disconnect 调整

六、容器组编排 (Docker Compose)

在现实项目中,一个完整的应用通常包含多个服务(Web服务器 + 后端 + 数据库 + 缓存)。如果仅使用 docker run,不仅命令繁琐,还容易出错(如忘记网络连接、端口冲突)。

Docker Compose 是 Docker 的官方编排工具。

01- 核心蓝图:docker-compose.yml

docker-compose.yml 是整个容器组的“施工图纸”。

以下是一个经典架构(Caddy Web 服务器 + Redis 缓存)的配置示例:

services: # 服务清单
web: # 服务 1: Web 前端
image: caddy:2.7.5-alpine
container_name: caddy-web
ports: # 端口映射 (宿主机:容器)
- "80:80"
volumes: # 数据挂载
- ./html:/usr/share/caddy # 使用相对路径,将当前目录下的 html 挂载进去
networks:
- app-network
restart: always # 或者 unless-stopped
cache: # 服务 2: Redis 缓存
image: redis:7.0-alpine
container_name: redis-cache
# Redis 不暴露端口给宿主机,只在内部网络开放,更安全
networks:
- app-network
networks: # 【网络定义】
app-network:
driver: bridge # 显式定义桥接网络,方便管理

02- 配置文件核心解读

1- Services (服务)

定义每一个独立的容器实例。

2- Volumes (卷/挂载)

3- Networks (网络)

03- 常用 Compose 命令对照表

Docker Compose 的命令设计与 Docker CLI 高度一致,只是作用对象变成了“一组容器”。

作用单容器命令 (Docker)容器组命令 (Docker Compose)
启动docker run -d ...docker compose up -d (最常用)
查看docker psdocker compose ps
日志docker logs -fdocker compose logs -f
停止docker stopdocker compose stop
销毁docker rmdocker compose down (停止并移除容器/网络)

关于 docker compose up -d 的执行逻辑:

它不仅是启动,而是 “声明式” 的。它会检查当前状态与 YAML 描述是否一致:

  1. 自动创建网络。
  2. 自动拉取所需镜像。
  3. 按顺序启动所有容器。
  4. 自动处理容器间的网络连接。

04- 两个至关重要的实战细节

1. 作用域:基于目录

2. 命名空间:隔离机制

七、镜像封装与构建 (Dockerfile)

前面的章节我们都是在使用别人造好的轮子(官方镜像)。而在实际开发中,我们需要编写 Dockerfile,将自己的代码(Go/Node/Python等)打包成专属镜像,实现标准化的交付。

01- 核心蓝图:Dockerfile

Dockerfile 是一个纯文本文件,包含了一系列指令。这些指令就像是一个脚本,告诉 Docker 如何一步步地“组装”出你的镜像。

经典案例:Go 应用的多阶段构建

# --- 阶段一:构建环境 (Builder) ---
# 选择包含编译器的大镜像
FROM golang:1.21-alpine AS builder
WORKDIR /app
# 利用缓存机制:先复制依赖文件并下载,再复制源码
COPY go.mod go.sum ./
RUN go mod download
COPY . .
# 编译出二进制可执行文件
RUN CGO_ENABLED=0 go build -o /app/myapp
# --- 阶段二:运行环境 (Runner) ---
# 选择极简的小镜像 (仅几 MB)
FROM alpine:3.18
WORKDIR /app
# 关键:只从 builder 阶段复制编译好的文件,丢弃源代码和编译器
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /app/myapp /app/myapp
# 声明端口与启动命令
EXPOSE 8080
CMD ["/app/myapp"]

02- 常用指令速查表

每个指令都会在构建中生成一个新的镜像层 (Layer),层数越少越好。

指令作用关键点
FROM指定基础镜像必须是第一条指令。推荐使用 alpine 版本以减小体积。
WORKDIR设置工作目录相当于 cd。后续的 RUN/CMD/COPY 都在此目录下执行。
COPY复制文件格式:COPY <本地路径> <镜像内路径>
RUN构建时执行命令用于安装依赖、编译代码。如 RUN apt-get update
CMD运行时默认命令容器启动时的入口。一个文件只能有一个 CMD。
EXPOSE声明监听端口仅作为文档说明,不会自动开放端口(需配合 -p 使用)。
ENTRYPOINT设置主程序让容器像一个可执行程序一样运行,CMD 的内容会作为参数传给它。

辨析 RUN vs CMD

  • RUNdocker build 阶段执行(写入镜像)。
  • CMDdocker run 阶段执行(启动容器)。

03- 进阶技巧:多阶段构建 (Multi-Stage Builds)

这是现代 Dockerfile 的最佳实践。

04- 构建与优化 (.dockerignore)

构建命令

docker build -t my-go-app:v1.0 .

忽略文件 (.dockerignore):

类似于 Git 的 .gitignore,用于防止不必要的文件(如 .git、node_modules、本地日志)被上传到 Docker 引擎,加快构建速度并减小体积。

05- 生产安全:资源限制 (Resource Limits)

这部分是生产环境的“安全气囊”,防止某个容器吃光宿主机所有内存导致死机。

方式 A:创建时限制 (docker run)

docker run -d \
--name limited-nginx \
--memory="512m" \
--cpus="1.0" \
-p 80:80 \
nginx

方式 B:运行时动态更新 (docker update)

如果容器已经跑起来了,也可以动态调整:

docker update --memory="1g" --memory-swap="1g" limited-nginx

🎓 总结

本文共分为 7 个部分,介绍了开发中 Docker 最常用的使用方式。

  1. Docker 的原理和使用场景
  2. Docker 的安装和配置
  3. 单容器的创建和管理
  4. 数据持久化
  5. 容器间通信
  6. Docker compose 容器组的创建与管理
  7. 通过 Dockerfile 创建自己的镜像

Docker 的命令很多,可以随着日常使用,不断的学习和掌握。
接下来还会介绍下 k8s 和 podman,欢迎关注