Docker 与容器解析:面向初学者的 Docker 工作原理指南

发布: (2026年1月16日 GMT+8 18:43)
12 min read
原文: Dev.to

Source: Dev.to

现代软件开发已经不再仅仅是编写代码。它还涉及 在任何地方可靠地运行这些代码——无论是在你的笔记本电脑、测试环境还是生产环境。这就是容器化和 Docker 的用武之地。

在本篇博客中,我们将分解说明:

  • 什么是容器
  • 为什么会创建 Docker
  • Docker 的内部工作原理

……以一种即使你完全是新手也能轻松理解的方式。

为什么我们需要容器

在容器出现之前,应用程序通常直接部署在服务器或虚拟机上。这导致了若干问题:

问题描述
环境漂移不同环境(开发、测试、生产)表现不一致
依赖冲突应用程序在库、运行时等方面产生冲突
部署和回滚困难手动步骤多,发布窗口长,存在停机时间
可扩展性差增加容量意味着克隆整个服务器/虚拟机

开发者需要一种方法来将应用程序及其运行所需的所有内容打包,并在任何地方以相同方式运行它。

什么是容器

容器是一个 轻量级、可移植的单元,它打包了:

  • 应用代码
  • 运行时(Node、Python、Java 等)
  • 库和依赖
  • 配置

容器 共享宿主操作系统内核,但在隔离的用户空间中运行,使其快速且高效。

集装箱类比

  • 船只并不关心内部的内容。
  • 集装箱可以在船只、卡车或港口之间移动。
  • 内部的一切保持不变。

虚拟机 vs. 容器

特性虚拟机容器
操作系统每个虚拟机都有完整的客体操作系统共享宿主操作系统内核
启动时间几分钟秒甚至毫秒
资源使用较高轻量级
隔离进程级别隔离
可移植性有限非常高

类比:
虚拟机就像为每位客人租一整栋房子。
容器就像在同一栋楼里租房间。

容器化之前的痛点

  • 依赖地狱 – 一个应用需要 Node 16,另一个需要 Node 18 → 升级其中一个会导致另一个坏掉。
  • “在我的笔记本上能跑”综合症 – 在开发者的笔记本上可以运行,QA 环境失败,生产环境因操作系统版本、库、配置或运行时不同而崩溃。
  • 扩展痛点 – 为了处理更多流量,你需要克隆服务器/虚拟机,重新配置所有内容,然后等待。
  • 手动部署 – 发布窗口长,回滚容易出错,频繁出现停机。

容器能解决什么

  • 相同的容器可以在任何地方运行 – 再也没有环境漂移。
  • 通过运行更多容器来扩展 – 快速、低成本且自动化。
  • 通过切换容器版本实现回滚 – 简单且可靠。

进入 Docker

Docker 是一个帮助你:

  • 打包你的应用 – 包含运行所需的一切。
  • 在任何机器上以相同方式运行 – “构建一次我的应用,随处运行。”

与手动设置环境不同,Docker 使用容器来实现自动化。

Docker 之前

  • 容器已经存在,但难以使用。
  • 每家公司都有自己的定制工具。
  • 开发者在环境搭建和一致性方面苦苦挣扎。

Docker 的答案

  • 标准化格式Dockerfile 与镜像。
  • 简洁命令docker builddocker run
  • 轻松共享镜像 – 注册表(Docker Hub、GHCR、私有注册表)。

Docker 直接解决了我们讨论的问题:

问题Docker 解决方案
依赖冲突每个应用都有自己的容器
环境不匹配同一镜像在任何地方都能运行
部署缓慢几秒钟内启动容器
回滚困难轻松切换镜像版本

Docker 并没有消除复杂性——它 把复杂性整齐地打包

Docker 在现代工作流中的定位

  • 本地开发 – 所有开发者使用相同的设置。
  • CI/CD 流水线 – 可预测的构建和测试。
  • 微服务 – 每个服务在自己的容器中运行。
  • 云端与 Kubernetes – Docker 镜像是标准单元。

Docker 通常是 迈向 的第一步:

  • Kubernetes
  • DevOps
  • 云原生架构

Source:

Docker 构建模块

Component功能说明
Docker Client你在终端输入的命令(docker builddocker run)或 GUI 调用的操作。向守护进程发送请求。
Docker Daemon (dockerd)在后台运行的服务,真正负责构建镜像和运行容器。
containerd & runc守护进程使用的底层工具,用于把镜像转化为运行中的进程。你不必记住它们的细节——只需了解 Docker 将实际的进程创建委托给这些专用工具。
Image冻结的快照(只读),类似配方或蓝图。
Container镜像的运行实例。会在只读层之上添加一个薄的可写层,使应用在运行时能够修改文件。
Dockerfile包含构建镜像指令的简单文本文件(基镜像、要复制的文件、要执行的命令)。docker build 读取它并创建镜像。
Registry存放镜像的仓库(Docker Hub、GitHub Container Registry、私有仓库等)。实现从任意位置 docker pushdocker pull

Docker 依赖的内核特性

  • Namespaces – 为容器提供独立的进程、网络、文件系统等视图。可以把命名空间想象成一个私人房间:看不到其他房间的内容。
  • cgroups(control groups) – 限制容器可以使用的 CPU、内存或磁盘等资源。可以把 cgroup 看作房间的电力限制器。

它们共同让容器表现得像 不需要完整操作系统开销的隔离环境

镜像层

每个 Dockerfile 步骤都会生成一个 。如果层的内容没有变化,这些层会被 缓存,因此合理安排 Dockerfile 的顺序可以加快构建速度。

网络

Docker 为每个容器分配网络接口,并允许你映射主机端口(-p host:container),从而使服务可被访问。

数据卷

对于需要在容器重启后仍然保留的数据,请使用 。卷将数据保存在容器临时可写层之外。

示例 Dockerfile

# Use an official Node runtime as a parent image
FROM node:18-alpine

# Set working directory inside the container
WORKDIR /app

# Copy package.json and package-lock.json first (for caching)
COPY package*.json ./

# Install app dependencies
RUN npm ci --only=production

# Copy the rest of the application source code
COPY . .

# Expose the port the app runs on
EXPOSE 3000

# Define the command to run the app
CMD ["node", "index.js"]

构建镜像:

docker build -t my-node-app:1.0 .

运行容器:

docker run -d -p 8080:3000 --name my-app my-node-app:1.0

TL;DR

Docker 是一个 小型系统,帮助你打包应用并在任何地方以相同方式运行。通过理解上述概念——容器、镜像、Dockerfile、仓库以及底层内核特性——你就可以在工作流中采用 Docker,并顺利迈向现代云原生架构。

运行容器化的 Node.js 应用

在本节中,你将通过复制粘贴命令实际运行一个容器化的应用。无需任何 Docker 经验。我们将容器化一个非常简单的 Node.js Web 服务器。

前置条件

  • 已安装 Docker(docker --version 能正常运行)
  • 任意操作系统(Windows / macOS / Linux)

1. 创建项目文件夹

mkdir simple-docker-app
cd simple-docker-app

2. 创建应用源码

index.js

const http = require('http');

const PORT = 3000;

const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Hello from Docker Container!');
});

server.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

package.json

{
  "name": "simple-docker-app",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  }
}

3. 编写 Dockerfile

创建一个名为 Dockerfile(无扩展名)的文件,内容如下:

# Use an official Node.js runtime
FROM node:18

# Set working directory inside container
WORKDIR /app

# Copy package files first (for caching)
COPY package*.json ./

# Install dependencies
RUN npm install

# Copy application source code
COPY . .

# Expose application port
EXPOSE 3000

# Start the application
CMD ["npm", "start"]

4. 构建 Docker 镜像

Dockerfile 同一文件夹 中运行以下命令:

docker build -t simple-web-app .

这会创建一个名为 simple-web-app 的 Docker 镜像。

5. 运行容器

docker run -p 3000:3000 simple-web-app
  • 容器内部的 3000 端口被映射到主机的 3000 端口。

6. 验证应用

打开浏览器并访问:

http://localhost:3000

你应该会看到:

Hello from Docker Container!

这到底发生了什么?

  • Docker 将你的应用 + Node.js + 配置打包成一个 镜像
  • 从该镜像创建了一个 容器
  • 容器内部的 3000 端口映射到了你的机器。
  • 应用在任何地方都以相同的方式运行。

为什么这很重要

  • 任何开发者的笔记本 都能运行该应用。
  • 可以在 CI/CD 流水线 中使用。
  • 云服务器 上无需额外配置即可运行。

Docker 不仅是一个工具——它是软件构建和交付方式的根本转变。

容器的优势

  • 消除环境差异。
  • 简化部署。
  • 自信地实现扩展。

如果你已经了解

  • 什么是容器。
  • 为什么会有 Docker。
  • Docker 的内部工作原理。

…那么你已经可以在真实项目中使用 Docker 了!

Back to Blog

相关文章

阅读更多 »

Rapg:基于 TUI 的密钥管理器

我们都有这种经历。你加入一个新项目,首先听到的就是:“在 Slack 的置顶消息里查找 .env 文件”。或者你有多个 .env …

技术是赋能者,而非救世主

为什么思考的清晰度比你使用的工具更重要。Technology 常被视为一种魔法开关——只要打开,它就能让一切改善。新的 software,...

踏入 agentic coding

使用 Copilot Agent 的经验 我主要使用 GitHub Copilot 进行 inline edits 和 PR reviews,让我的大脑完成大部分思考。最近我决定 t...