一、什么是 Docker?

Docker 是一个开源的容器化平台,解决了软件开发和部署中一个经典痛点:

「在我电脑上能跑,但在别人机器上跑不起来」

核心思想:把应用程序和它所需的所有依赖(运行环境、库、配置文件)打包成一个标准化单元——容器(Container),这个容器可以在任何安装了 Docker 的机器上一致运行。

Docker 解决的核心问题:

  • 环境不一致:开发、测试、生产环境完全一致,杜绝"在我这里没问题"
  • 依赖冲突:不同项目使用不同版本的库,互不干扰
  • 部署复杂:一行命令完成应用部署,无需手动配置环境
  • 资源隔离:多个应用互相隔离,一个崩溃不影响其他

二、核心概念

学 Docker 首先要掌握以下几个核心概念,它们的关系就像:菜谱 → 做好的菜 → 端上桌的菜
在这里插入图片描述

概念类比说明
Dockerfile菜谱描述如何构建镜像的文本文件
Image(镜像)光盘 / 程序安装包只读模板,可分层叠加
Container(容器)正在运行的程序镜像的运行实例,有状态
Registry(仓库)应用商店 / App Store存储和分发镜像的平台
Docker HubGitHub(for images)最大的公共镜像仓库
Volume(卷)外接硬盘持久化容器数据
Network(网络)局域网容器间通信机制

2.1 Dockerfile

Dockerfile 是一个纯文本文件,用特定指令描述如何构建镜像。

常用指令:

  • FROM — 指定基础镜像(起点)
  • RUN — 构建时执行命令,如安装软件包
  • COPY / ADD — 将本地文件复制到镜像中
  • WORKDIR — 设置工作目录
  • EXPOSE — 声明容器监听的端口
  • CMD / ENTRYPOINT — 容器启动时执行的命令
  • ENV — 设置环境变量

示例(Node.js 应用):

# 从官方 Node.js 镜像开始
FROM node:18-alpine

# 设置工作目录
WORKDIR /app

# 复制依赖文件并安装
COPY package*.json ./
RUN npm install

# 复制源码
COPY . .

# 暴露端口
EXPOSE 3000

# 启动命令
CMD ["node", "server.js"]

2.2 Image(镜像)

通过 docker build 根据 Dockerfile 构建出来的只读模板

关键特性:

  • 分层结构:每条 Dockerfile 指令生成一个独立的层,层与层叠加,相同层可被多个镜像复用
  • 只读性:镜像本身不可修改,运行时会在其上面加一层可写层
  • 可分发:可推送到 Docker Hub 或私有仓库,供团队共享

镜像命名格式:

[仓库地址/]用户名/镜像名[:标签]

nginx:latest               # 官方 nginx,最新版
node:18-alpine             # 官方 node,Alpine 变种
myuser/my-app:v1.2.3       # 自定义镜像
registry.company.com/app   # 私有仓库镜像

2.3 Container(容器)

容器是镜像运行起来的实例,是真正在跑的进程。

关键特性:

  • 有状态:运行时可以读写文件,有自己的网络、进程空间
  • 隔离性:通过 Linux namespace / cgroup 与宿主机和其他容器隔离
  • 临时性:默认情况下容器停止后数据丢失,需要 Volume 来持久化
  • 轻量级:启动速度快(毫秒到秒级),资源占用极小

2.4 Registry(镜像仓库)

存储和分发镜像的服务。

  • Docker Hub:最大的公共仓库,官方和社区镜像都在这里
  • 私有 Registry:企业内部搭建,如 Harbor、AWS ECR、阿里云 ACR
  • GitHub Container Registry:GitHub 官方提供的镜像托管服务

三、 Docker 整体架构

Docker 采用 Client-Server 架构
在这里插入图片描述
架构中有三个主要角色:

  • Docker Client 是你直接操作的部分,就是在终端输入 docker run、docker build 这些命令,或者打开 Docker Desktop 图形界面。它通过 REST API 把你的指令发给 Daemon。
  • Docker Daemon(dockerd) 是运行在宿主机上的后台服务,是真正的"大脑",负责管理镜像下载、容器的创建和运行、网络、存储等所有事情。
  • Registry 是镜像仓库,Docker Hub 是最大的公共仓库,企业内部也可以搭建私有仓库。docker pull 就是从仓库下载镜像到本地。

四、容器 vs 虚拟机

在这里插入图片描述

这是理解 Docker 价值的关键对比。

对比维度虚拟机(VM)容器(Container)
隔离级别硬件级别进程级别
操作系统每个 VM 含完整 OS共享宿主机内核
启动时间分钟级秒级甚至毫秒级
镜像大小GB 级别MB 级别
性能开销较大(需模拟硬件)极小(接近原生)
密度一台机器几至几十个一台机器几百甚至上千个
适用场景强隔离、不同 OS 需求微服务、快速部署、CI/CD

为什么容器更轻量?

虚拟机通过 Hypervisor 模拟完整硬件,每个 VM 运行完整的操作系统(含内核),资源开销巨大。容器直接利用宿主机 Linux 内核,靠两个原生技术实现隔离:

  • Namespace:实现隔离,每个容器有独立的进程树、网络、文件系统视图
  • cgroup:实现资源限制,控制容器能使用多少 CPU 和内存

五、常用命令速查

镜像管理

docker images                      # 查看本地所有镜像
docker pull nginx:latest            # 拉取镜像
docker build -t myapp:v1 .         # 构建镜像(. 表示当前目录含 Dockerfile)
docker push myuser/myapp:v1        # 推送镜像到仓库
docker rmi myapp:v1                # 删除本地镜像
docker image prune                 # 清理未使用的镜像

容器生命周期

docker run -d -p 8080:80 --name web nginx   # 创建并启动容器
docker start web                            # 启动已停止的容器
docker stop web                             # 优雅停止容器
docker restart web                          # 重启容器
docker rm web                               # 删除容器
docker rm -f web                            # 强制删除运行中的容器

查看与调试

docker ps                    # 查看运行中的容器
docker ps -a                 # 查看所有容器(含已停止的)
docker logs -f web           # 实时跟踪容器日志
docker exec -it web bash     # 进入容器内部(调试神器)
docker inspect web           # 查看容器详细信息
docker stats                 # 查看容器资源使用(CPU/内存)

docker run 常用参数

-d                        # 后台运行(detached mode)
-p 8080:80                # 端口映射:宿主机端口:容器端口
--name my-container       # 指定容器名称
-v /host/path:/app        # 挂载目录(Bind Mount)
-e KEY=VALUE              # 设置环境变量
--rm                      # 容器停止后自动删除
-it                       # 交互式 + 伪终端(进入 shell 用)
--restart unless-stopped  # 自动重启策略

六、网络与存储

6.1 Docker 网络

容器默认通过端口映射(-p)对外暴露服务。常用网络模式:

  • bridge(默认):容器通过虚拟网桥互联,适合单机多容器
  • host:容器直接使用宿主机网络,性能好但隔离性差
  • 自定义 bridge 网络:同一网络内的容器可以用容器名互相访问(推荐)
# 创建自定义网络
docker network create my-net

# 启动容器并加入网络,之后 app 容器内可以直接用 "db" 访问数据库
docker run -d --name db  --network my-net mysql:8
docker run -d --name app --network my-net -e DB_HOST=db my-app

6.2 存储(Volume)

容器停止后数据默认丢失,Volume 用于持久化:

  • Named Volume:Docker 管理存储位置,推荐用于数据库等持久化数据
  • Bind Mount:将宿主机目录挂载到容器内,开发时用于同步代码
# Named Volume
docker run -d -v mysql-data:/var/lib/mysql mysql:8

# Bind Mount(开发时同步本地代码)
docker run -d -v $(pwd)/src:/app/src my-app

、Docker Compose(多容器编排)

实际项目通常有多个服务(Web + 数据库 + 缓存),用 Docker Compose 可以用一个 YAML 文件统一管理。

示例(docker-compose.yml):

version: '3.8'

services:
  web:
    build: .
    ports:
      - "8080:3000"
    environment:
      - DB_HOST=db
      - REDIS_URL=redis://cache:6379
    depends_on:
      - db
      - cache

  db:
    image: mysql:8
    environment:
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: myapp
    volumes:
      - db-data:/var/lib/mysql

  cache:
    image: redis:7-alpine

volumes:
  db-data:

常用命令:

docker compose up -d       # 后台启动所有服务
docker compose down        # 停止并删除所有容器
docker compose logs -f     # 查看所有服务日志
docker compose ps          # 查看服务状态

一个完整的运行流程

从写代码到容器跑起来,整个过程是这样的
在这里插入图片描述

推荐资源:


记住最核心的一句话:Docker 让你的应用无论在哪台机器上都能以完全相同的方式运行。

更多推荐