15%

全场主机优惠15%

测试技能,享折扣

使用代码:

Skills
开始使用
01.11.2024

Docker 是什么以及它如何工作?开发人员和系统管理员完整指南

Docker 从根本上改变了现代应用程序的构建、交付和部署方式。无论您是厌倦了环境不一致的开发人员,还是管理多台服务器上数十个服务的系统管理员,Docker 都提供了一个干净、高效和可移植的解决方案。在这份综合指南中,我们将详细介绍 Docker 是什么、它的工作原理以及为什么它已成为当今 DevOps 领域不可或缺的工具。

什么是 Docker?

Docker 是一个开源平台,使用容器化技术自动化应用程序的部署、扩展和管理。Docker 的核心是将应用程序及其所有依赖项(库、配置文件、运行时环境和环境变量)打包到一个称为容器的自包含单元中。

这里的关键优势是一致性。Docker 容器的行为完全相同,无论它在开发人员的笔记本电脑、暂存服务器还是云中的生产环境上运行。这消除了困扰软件团队数十年的臭名昭著的”在我的机器上可以运行”问题。

Docker 与传统虚拟机的比较

要真正理解 Docker,了解它与传统虚拟机 (VM) 的区别会很有帮助:

功能Docker 容器虚拟机
操作系统开销共享主机操作系统内核需要完整的客户操作系统
启动时间分钟
资源使用轻量级重量级
可移植性高度可移植可移植性有限
隔离进程级隔离完整的硬件级隔离

传统 VM 虚拟化整个硬件堆栈,每个实例都需要一个完整的操作系统。相比之下,Docker 容器共享主机操作系统的内核,同时保持严格的进程隔离。结果是启动时间大幅加快、内存消耗降低,以及服务器资源的使用效率大幅提高。

如果您在 VPS 托管计划上运行容器化工作负载,这种效率会直接转化为成本节省和更好的性能投资回报率。

Docker 的关键组件

理解 Docker 需要熟悉其核心构建块。每个组件在容器生命周期中都发挥特定的作用。

1. Docker 引擎

Docker 引擎是整个平台的核心。它是一个客户端-服务器应用程序,负责构建、运行和管理容器。引擎包括两个主要部分:

  • Docker 守护进程 (dockerd):一个持久的后台服务,侦听 Docker API 请求并管理 Docker 对象,如镜像、容器、网络和卷。守护进程完成繁重的工作——它构建镜像、启动容器并处理所有编排任务。
  • Docker CLI(命令行界面):开发人员和管理员用来与 Docker 守护进程交互的命令行工具。诸如 docker run、docker build 和 docker push 之类的命令都通过 CLI 执行,CLI 通过 REST API 与守护进程通信。

2. Docker 镜像

Docker 镜像是一个只读的、不可变的模板,用于创建容器。可以将其视为应用程序在特定时间点的快照或蓝图。镜像包含:

  • 应用程序源代码或编译的二进制文件
  • 所有必需的运行时库和依赖项
  • 环境变量和配置设置
  • 文件系统结构和元数据

镜像是按构建的。Dockerfile 中的每条指令都在前一层的基础上添加新层。这种分层架构使 Docker 能够缓存中间构建步骤,使后续构建速度大幅加快。当您仅更新应用程序代码时,Docker 会重用所有缓存的依赖项层,只重新构建已更改的部分。

3. Dockerfile

Dockerfile 是一个纯文本脚本,包含 Docker 遵循的一系列指令来组装镜像。它定义了基础镜像、工作目录、要复制的文件、要运行的命令以及要公开的端口。Dockerfile 是如何构建应用程序镜像的唯一真实来源,使构建完全可重现且可版本控制。

4. Docker Hub 和容器注册表

Docker Hub 是 Docker 镜像的默认云端公共注册表。它充当中央存储库,开发人员可以在其中发布、共享和拉取镜像。Docker Hub 托管数千个流行软件堆栈的官方镜像——包括 Node.js、Python、Nginx、MySQL、Redis 等——您可以将其用作自己应用程序的基础镜像。

除了 Docker Hub 之外,组织通常运行私有注册表来安全地存储专有镜像。这在生产环境中尤其重要,您不希望暴露内部应用程序逻辑。

5. Docker 容器

容器是 Docker 镜像的运行实例。虽然镜像是静态的和只读的,但容器是一个实时的、可执行的环境。您可以同时从同一镜像运行多个容器,每个容器都在完全隔离的环境中运行,拥有自己的文件系统、网络接口和进程空间。

容器在设计上是临时的——它们可以启动、停止、移动和删除,而不会影响底层镜像或其他容器。这使它们非常适合微服务架构和水平扩展。

Docker 如何工作:分步演练

让我们从编写第一个 Dockerfile 到运行实时容器,完整地演练 Docker 工作流程。

步骤 1:编写 Dockerfile

该过程从在项目的根目录中创建 Dockerfile 开始。以下是 Node.js Web 应用程序的实际示例:

# Use the official Node.js 18 LTS image as the base
FROM node:18-alpine

# Set the working directory inside the container
WORKDIR /usr/src/app

# Copy dependency manifests first (leverages layer caching)
COPY package*.json ./

# Install production dependencies
RUN npm install --only=production

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

# Expose the port the application listens on
EXPOSE 8080

# Define the default command to start the application
CMD ["node", "app.js"]

为什么在代码的其余部分之前复制 package.json?这是一个最佳实践,利用了 Docker 的层缓存。由于 npm install 很耗时,在复制应用程序代码之前放置它意味着 Docker 只在您的依赖项实际更改时重新运行安装步骤——而不是每次修改源文件时。

步骤 2:构建 Docker 镜像

有了 Dockerfile,使用 docker build 命令构建镜像:

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

分解此命令:

  • docker build — 指示 Docker 引擎构建新镜像
  • -t myapp:1.0 — 使用名称 myapp 和版本 1.0 标记镜像
  • . — 指定构建上下文(当前目录),Docker 将其发送到守护进程

Docker 逐行读取 Dockerfile,执行每条指令并将结果作为新镜像层提交。在后续构建中,未更改的层从缓存中拉取,使过程快得多。

步骤 3:运行 Docker 容器

构建镜像后,从它启动一个容器:

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

标志分解:

  • -d — 在分离模式下运行容器(在后台)
  • -p 8080:8080 — 将主机机器上的端口 8080 映射到容器内的端口 8080
  • –name myapp-container — 为容器分配一个人类可读的名称
  • myapp:1.0 — 指定要使用的镜像

您的应用程序现在可以在 http://localhost:8080 访问。

步骤 4:管理运行中的容器

Docker 提供了一套丰富的命令来管理容器生命周期:

# List all running containers
docker ps

# View logs from a container
docker logs my-running-app

# Stop a running container
docker stop my-running-app

# Remove a stopped container
docker rm my-running-app

# List all locally available images
docker images

步骤 5:将镜像推送到注册表

要共享您的镜像或将其部署到远程服务器,请将其推送到 Docker Hub 或私有注册表:

# Log in to Docker Hub
docker login

# Tag the image with your Docker Hub username
docker tag my-node-app:1.0 yourusername/my-node-app:1.0

# Push the image to the registry
docker push yourusername/my-node-app:1.0

从任何安装了 Docker 的服务器——包括专用服务器——您可以使用单个命令拉取并运行您的镜像。

Docker Compose:管理多容器应用程序

真实世界的应用程序很少由单个服务组成。典型的 Web 应用程序可能包括 Node.js API 服务器、PostgreSQL 数据库、Redis 缓存和 Nginx 反向代理。单独管理所有这些容器会很繁琐且容易出错。

Docker Compose 通过允许您使用单个 docker-compose.yml 文件定义和运行多容器应用程序来解决这个问题:

version: '3.8'

services:
  web:
    build: .
    ports:
      - "8080:8080"
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgres://user:password@db:5432/mydb
    depends_on:
      - db
      - redis

  db:
    image: postgres:15-alpine
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=mydb

  redis:
    image: redis:7-alpine

volumes:
  postgres_data:

有了这个文件,您可以使用一个命令启动整个应用程序堆栈:

docker-compose up -d

Docker Compose 自动处理容器之间的网络——每个服务都可以通过其服务名称到达其他服务(例如,Web 服务在主机名 db 处连接到数据库)。

使用 Docker 的关键优势

✅ 跨环境的可移植性

Docker 容器封装了应用程序运行所需的一切。这意味着在开发人员的 macOS 工作站上构建的容器将在 Linux 生产服务器或 Windows CI/CD 管道上完全相同地运行。不再有依赖项冲突或特定于环境的错误。

✅ 一致且可重现的构建

由于整个环境都在代码中定义(Dockerfile),构建是完全可重现的。任何团队成员都可以检出存储库并从头开始构建相同的环境。这对于新开发人员的入职和在受监管行业中维护审计跟踪非常宝贵。

✅ 进程隔离和安全性

每个容器在其自己的隔离命名空间中运行,拥有自己的文件系统、网络堆栈和进程树。这种隔离意味着一个容器中的崩溃或安全漏洞不会自动影响同一主机上运行的其他容器。结合适当的网络策略和只读文件系统,Docker 显著减少了应用程序的攻击面。

✅ 卓越的资源效率

与传统虚拟机相比,Docker 容器非常轻量级。它们在几秒钟内启动,而不是几分钟,并且消耗的内存和 CPU 开销仅为传统虚拟机的一小部分。在单个 VPS 托管实例上,您可以轻松运行数十个容器化微服务,这在过去需要多个 VM。

✅ 简化的依赖项管理

Docker 消除了应用程序之间的依赖项冲突。两个需要不同版本的 Python、Node.js 或任何其他运行时的服务可以在同一主机上和平共存,因为每个容器都携带自己的隔离依赖项堆栈。

✅ 加速的 CI/CD 管道

Docker 与现代 CI/CD 工具(如 GitHub Actions、GitLab CI、Jenkins 和 CircleCI)无缝集成。容器提供干净、隔离的构建环境,确保您的测试针对与生产部署完全相同的堆栈运行,大幅降低了与环境相关的发布失败风险。

✅ 轻松的水平扩展

由于容器在设计上是无状态且可丢弃的,水平扩展应用程序就像在负载均衡器后面启动额外的容器实例一样简单。Kubernetes 和 Docker Swarm 等编排平台完全自动化了这个过程。

Docker 安全最佳实践

在生产环境中运行容器需要注意安全性。以下是每个系统管理员应该遵循的最重要的实践:

  1. 使用最小基础镜像:基于 Alpine 的镜像(alpine、python:3.9-alpine)的攻击面比完整操作系统镜像小得多。
  2. 以非 root 用户身份运行容器:在 Dockerfile 中添加 USER 指令,以避免在容器内以 root 身份运行进程。
  3. 扫描镜像以查找漏洞:使用 docker scan、Trivy 或 Snyk 等工具定期扫描镜像以查找已知的 CVE。
  4. 保持镜像更新:定期重建镜像以包含来自基础镜像更新的安全补丁。
  5. 使用只读文件系统:在可能的情况下,将容器文件系统挂载为只读以防止篡改。
  6. 限制资源消耗:使用 –memory 和 –cpus 标志防止单个容器垄断主机资源。
  7. 保护您的注册表:将敏感镜像存储在具有访问控制的私有注册表中,而不是在公共 Docker Hub 上。

对于生产部署,将 Docker 与配置正确的服务器配对至关重要。AlexHost 的专用服务器提供了大规模运行容器化工作负载所需的原始性能和完全 root 访问权限,而VPS 托管计划为较小的部署提供了经济高效的入口点。

Docker 在您的托管基础设施背景下

理解 Docker 只是难题的一部分。要有效地部署容器化应用程序,您需要可靠的底层基础设施。

  • 对于小型项目和暂存环境:共享 Web 托管非常适合静态网站和简单的 PHP 应用程序,尽管 Docker 通常在 VPS 或专用环境中使用。
  • 对于容器化 Web 应用程序:VPS 托管计划为您提供完全的 root 访问权限、专用资源以及安装 Docker 和任何编排工具的自由。
  • 对于大规模微服务:专用服务器提供最大性能,消除了共享环境中常见的”嘈杂邻居”效应。
  • 对于容器中的机器学习和 AI 工作负载:GPU 托管支持 GPU 加速的 Docker 容器,用于深度学习、模型训练和推理工作负载。
  • 为了保护容器化 Web 服务:将您的部署与 SSL 证书配对,以加密用户与 Dockerized 应用程序之间的流量。

关于 Docker 的常见问题

问:Docker 可以免费使用吗?

Docker 引擎是开源的,可免费用于个人和小型企业。Docker Desktop 对于较大的组织需要付费订阅。Docker Hub 提供免费的公共存储库,但拉取次数有限制。

问:Docker 和 Kubernetes 有什么区别?

Docker 是一个容器运行时——它构建和运行单个容器。Kubernetes 是一个容器编排平台,可自动化大量容器在机器集群中的部署、扩展和管理。它们是互补的技术;Kubernetes 通常在幕后使用 Docker(或另一个容器运行时)。

问:Docker 可以在 Windows 上运行吗?

可以。Docker Desktop for Windows 使用 WSL 2(Windows Subsystem for Linux)或 Hyper-V 在 Windows 上运行 Linux 容器。也支持本机 Windows 容器。

问:Docker 与虚拟机有什么不同?

如前所述,VM 虚拟化硬件并需要完整的客户操作系统,使其更重且启动速度更慢。Docker 容器共享主机操作系统内核,轻量级得多,尽管隔离程度略低于完整 VM。

问:对于单容器应用程序,我需要 Docker Compose 吗?

不需要。Docker Compose 对多容器应用程序最有价值。对于单个容器,标准 docker run 命令完全足够。

结论

Docker 已成为现代软件开发和系统管理中的基石技术。通过将应用程序及其依赖项打包到可移植、隔离的容器中,Docker 消除了环境不一致,加速了部署管道,与传统虚拟化相比大幅改进了资源利用。

无论您是部署简单的 Web 应用程序还是构建复杂的微服务平台,掌握 Docker 都将从根本上改进您构建和运营软件的方式。本指南中涵盖的概念——Dockerfile、镜像、容器、Docker Compose 和安全最佳实践——构成了您需要自信开始的基础。

准备好将 Docker 付诸实践了吗?AlexHost 的 VPS 托管计划开箱即用地支持完全

15%

全场主机优惠15%

测试技能,享折扣

使用代码:

Skills
开始使用