Docker教程核心概念详解:从容器化思想到实践
在当今的软件开发与部署领域,Docker 已经从一个新兴工具演变为一项不可或缺的核心技术。它通过容器化技术,彻底改变了我们构建、分发和运行应用程序的方式,实现了“一次构建,处处运行”的梦想。无论是开发复杂的微服务架构,还是部署一个简单的 Web 应用,理解 Docker 的核心概念都是现代开发者和运维人员的必备技能。本文将深入浅出地解析 Docker 的核心概念,并结合 Windows Server、TypeScript 和 Express 等关键词,展示其在实际场景中的应用。
一、容器与镜像:Docker的基石
要理解 Docker,首先必须分清两个最核心的概念:镜像(Image) 和 容器(Container)。
1.1 镜像:不可变的蓝图
镜像是 Docker 世界的“构建模块”和“只读模板”。它包含了运行一个应用所需的一切:代码、运行时环境、系统工具、库和配置。你可以将镜像想象成一个软件的安装包(如 `.exe` 或 `.dmg` 文件),但它更加完整和独立。
- 分层结构:Docker 镜像采用分层存储。每一层代表 Dockerfile 中的一条指令。例如,基础操作系统层、安装依赖层、复制代码层等。这种设计使得镜像的构建、分发和存储非常高效。
- 只读性:镜像是不可变的。当你运行一个镜像时,Docker 会在其之上创建一个可写的容器层,所有修改都发生在这个容器层,而不会影响底层的镜像。
例如,一个典型的 Node.js + TypeScript 应用的 Dockerfile 可能如下所示,它清晰地展示了镜像的分层构建过程:
# 第一层:指定基础镜像
FROM node:18-alpine
# 第二层:设置工作目录
WORKDIR /app
# 第三层:复制 package.json 和 package-lock.json
COPY package*.json ./
# 第四层:安装依赖
RUN npm ci --only=production
# 第五层:复制 TypeScript 源码并编译
COPY src ./src
COPY tsconfig.json ./
RUN npm run build
# 第六层:声明运行时暴露的端口(元数据层)
EXPOSE 3000
# 定义启动命令
CMD ["node", "dist/index.js"]
1.2 容器:镜像的运行实例
容器是镜像的一个运行实例。你可以使用 `docker run` 命令从镜像启动一个或多个容器。容器是轻量级、可执行的独立环境,拥有自己的进程、网络和文件系统(基于镜像层加上一个可写的容器层)。
- 生命周期:容器可以被创建、启动、停止、移动和删除。
- 隔离性:每个容器在主机操作系统(如 Windows Server 或 Linux)的用户空间中独立运行,通过内核的命名空间和控制组(cgroups)实现进程、网络、文件系统等资源的隔离。
启动一个基于上述镜像的容器非常简单:
docker run -p 8080:3000 --name my-ts-app your-image-name
这条命令将容器的 3000 端口(Express 应用监听的端口)映射到主机的 8080 端口。
二、Dockerfile:构建镜像的配方
Dockerfile 是一个文本文件,包含了一系列用于构建镜像的指令。它是实现应用容器化、可重复构建的关键。
2.1 常用指令解析
- FROM:指定基础镜像。这是所有 Dockerfile 的第一条有效指令。
- WORKDIR:设置工作目录,后续的 `RUN`、`CMD`、`COPY` 等指令都会在这个目录下执行。
- COPY/ADD:将文件从构建上下文复制到镜像中。
- RUN:在构建镜像时执行命令,常用于安装软件包。
- EXPOSE:声明容器运行时监听的端口(仅声明作用,实际映射在 `run` 时指定)。
- CMD:指定容器启动时默认执行的命令。一个 Dockerfile 中只能有一条 `CMD` 指令。
2.2 结合 TypeScript 与 Express 的实践
让我们构建一个更完整的、适用于开发的 TypeScript Express 应用 Dockerfile。这个配置支持在容器内进行热重载,非常适合开发阶段。
# 使用带有 npm 的 Node.js 官方镜像作为基础
FROM node:18-alpine
# 安装全局依赖(如 ts-node 用于开发)
RUN npm install -g ts-node typescript
# 设置工作目录
WORKDIR /usr/src/app
# 复制依赖定义文件
COPY package*.json ./
# 安装所有依赖(包括开发依赖)
RUN npm install
# 复制源代码
COPY . .
# 开发模式:使用 ts-node 直接运行,并监听文件变化
CMD ["npx", "nodemon", "--exec", "ts-node", "./src/index.ts"]
使用此 Dockerfile 构建镜像:`docker build -t express-ts-dev .`。在 Windows Server 上运行此命令与在 Linux 上完全一致,体现了 Docker 的跨平台一致性。
三、Docker Compose:定义和运行多容器应用
现代应用通常由多个服务组成(如 Web 前端、API 后端、数据库、缓存等)。Docker Compose 是一个用于定义和运行多容器 Docker 应用的工具。通过一个 `docker-compose.yml` 文件,你可以配置所有服务、网络和卷。
3.1 Compose 文件核心结构
以下是一个典型的 `docker-compose.yml` 示例,它定义了一个 Express (TypeScript) API 服务和一个 PostgreSQL 数据库服务。
version: '3.8'
services:
# Express API 服务
api:
build: . # 使用当前目录的 Dockerfile 构建
container_name: my-express-api
ports:
- "3000:3000" # 主机端口:容器端口
environment:
- DATABASE_URL=postgresql://user:password@db:5432/mydb
volumes:
- ./src:/usr/src/app/src # 挂载源代码,实现开发热重载
- /usr/src/app/node_modules # 匿名卷,防止主机 node_modules 覆盖容器内的
depends_on:
- db # 声明依赖,确保 db 服务先启动
restart: unless-stopped
# PostgreSQL 数据库服务
db:
image: postgres:15-alpine
container_name: my-postgres-db
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: mydb
volumes:
- postgres_data:/var/lib/postgresql/data # 命名卷,持久化数据库数据
ports:
- "5432:5432"
# 定义命名卷
volumes:
postgres_data:
3.2 在 Windows Server 上使用 Docker Compose
在 Windows Server 2016 及以上版本中,Docker 和 Docker Compose 可以作为 Windows 容器或 Linux 容器运行(通过 WSL 2 后端在较新版本上获得最佳体验)。启动上述应用栈只需一行命令:
docker-compose up -d
这条命令会构建镜像(如果需要)、创建网络、启动所有定义的服务并在后台运行。使用 `docker-compose down` 可以停止并移除所有资源。
四、数据管理与网络:容器的持久化与通信
4.1 数据卷(Volumes)
容器的文件系统是临时的,容器被删除后,其中的数据也会丢失。为了持久化数据(如数据库文件、上传的文件),Docker 提供了卷(Volumes)和绑定挂载(Bind Mounts)。
- 命名卷:由 Docker 管理,是最佳的数据持久化方式。如上例中的 `postgres_data` 卷。
- 绑定挂载:将主机上的一个特定目录或文件挂载到容器中。常用于开发时同步源代码,如上例中将 `./src` 挂载到容器内。
4.2 网络(Networks)
默认情况下,Docker 会为 Compose 应用栈创建一个独立的网络。在这个网络中,服务可以使用服务名作为主机名相互访问。这是微服务架构中服务发现的关键机制。
在上面的 Compose 例子中,`api` 服务可以通过连接字符串 `db:5432` 访问 `db` 服务,因为 `db` 既是服务名,也在网络内部被解析为对应容器的 IP 地址。
你也可以创建自定义网络以实现更精细的控制:
docker network create my-app-network
docker run --network my-app-network --name api your-api-image
docker run --network my-app-network --name db postgres:15-alpine
总结
Docker 的核心概念——镜像、容器、Dockerfile、Docker Compose、数据卷和网络——共同构成了一个强大而灵活的容器化生态系统。通过将应用及其依赖打包进一个标准化的单元,Docker 解决了“在我机器上能运行”的经典难题。
结合本文的实践示例,我们可以看到:
- 使用 Dockerfile 可以标准化地构建包含 TypeScript 编译环境的 Express 应用镜像。
- Docker Compose 使得在本地或 Windows Server 生产环境中编排多服务应用(如 API + 数据库)变得轻而易举。
- 数据卷和网络机制确保了应用数据的持久化和服务间的可靠通信。
掌握这些核心概念,你就已经迈入了现代化应用部署和 DevOps 实践的大门。无论是开发、测试还是生产部署,Docker 都能提供一致的环境,极大地提升效率与可靠性。下一步,你可以探索 Docker 仓库(如 Docker Hub)、容器编排工具(如 Kubernetes)以及更深入的 Docker 安全最佳实践,以构建更健壮、可扩展的云原生应用。




