什么是 Docker 容器以及它们如何工作

DockerBeginner
立即练习

简介

Docker 容器彻底改变了应用程序的开发、部署和管理方式。在本全面教程中,你将了解什么是 Docker 容器、它们如何工作,以及如何利用它们来简化软件开发和部署流程。从安装和配置 Docker 到构建和管理 Docker 镜像与容器,本指南涵盖了使用 Docker 容器的关键方面。

Docker 容器简介

Docker 是一个广受欢迎的开源平台,它使用容器来实现应用程序的开发、部署和管理。容器是轻量级、独立且可执行的软件包,其中包含运行应用程序所需的所有必要组件,例如代码、运行时环境、系统工具和库。

容器提供了一种一致且可靠的方式来打包和分发应用程序,确保它们无论在何种底层基础设施上运行,方式都是相同的。这使得开发、测试和部署应用程序变得更加容易,同时也便于在生产环境中进行扩展和管理。

Docker 的一个主要优势在于其创建和管理容器的能力。容器是从 Docker 镜像创建而来的,Docker 镜像本质上是定义容器内容的模板,包括操作系统、软件和应用程序代码。Docker 镜像可以构建、共享,并用于在任何安装了 Docker 的系统上创建容器。

要开始使用 Docker,你需要在系统上安装 Docker 软件。安装完成后,你可以使用 Docker 命令行界面 (CLI) 来创建、管理 Docker 容器并与之交互。Docker CLI 提供了广泛的命令,用于构建、运行和管理容器,以及管理 Docker 镜像和网络。

graph TD A[开发者] --> B[Docker 镜像] B --> C[Docker 容器] C --> D[应用程序] D --> E[基础设施]

在接下来的部分中,我们将更深入地探讨 Docker 架构和组件,并探索如何使用 Docker 来构建、运行和管理容器。

Docker 架构与组件

Docker 引擎

Docker 平台的核心组件是 Docker 引擎,它负责构建、运行和管理 Docker 容器。Docker 引擎由以下主要组件组成:

  • Docker 守护进程:管理 Docker 容器和镜像的后台进程。
  • Docker API:允许客户端与 Docker 守护进程进行交互的 API。
  • Docker CLI:允许用户与 Docker 守护进程进行交互的命令行界面。

Docker 镜像

Docker 镜像是 Docker 容器的构建模块。它们是只读模板,定义了容器的内容,包括操作系统、软件和应用程序代码。可以使用 Dockerfile 创建 Docker 镜像,Dockerfile 是一个文本文件,用于指定构建镜像的指令。

以下是一个使用 Nginx 网络服务器创建简单 Web 服务器的 Dockerfile 示例:

FROM nginx:latest
COPY index.html /usr/share/nginx/html/
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Docker 容器

Docker 容器是 Docker 镜像的运行时实例。它们是轻量级、可移植且自包含的环境,可以运行应用程序和服务。容器与主机系统以及彼此相互隔离,确保它们可以在不同环境中一致地运行。

要从 Docker 镜像创建容器,可以使用 docker run 命令:

docker run -d -p 80:80 --name my-web-server nginx

此命令从 nginx 镜像创建一个新容器,将主机上的端口 80 映射到容器中的端口 80,并以分离模式启动容器。

Docker 网络

Docker 提供了一个内置的网络系统,允许容器相互通信以及与主机系统通信。Docker 支持多种网络驱动程序,包括桥接、主机和覆盖网络,可用于为你的应用程序创建自定义网络配置。

graph TD A[Docker 主机] --> B[Docker 引擎] B --> C[容器 1] B --> D[容器 2] C --> E[桥接网络] D --> E

在接下来的部分中,我们将探讨如何安装和配置 Docker,以及如何构建、运行和管理 Docker 容器。

安装与配置 Docker

在 Ubuntu 22.04 上安装 Docker

要在 Ubuntu 22.04 上安装 Docker,请执行以下步骤:

  1. 更新软件包索引:

    sudo apt-get update
  2. 安装必要的软件包,以便 apt 能够通过 HTTPS 使用软件源:

    sudo apt-get install -y \
      apt-transport-https \
      ca-certificates \
      curl \
      gnupg \
      lsb-release
  3. 添加官方 Docker GPG 密钥:

    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
  4. 设置 Docker 软件源:

    echo \
      "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
      $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
  5. 安装 Docker 引擎、containerd 和 Docker Compose 软件包:

    sudo apt-get update
    sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
  6. 通过运行 docker version 命令验证安装:

    docker version

配置 Docker

安装 Docker 之后,你可以根据自己的需求对其进行配置。一些常见的配置任务包括:

  • 调整 Docker 守护进程选项:你可以通过编辑 /etc/docker/daemon.json 文件来自定义 Docker 守护进程的行为。
  • 管理 Docker 容器和镜像:你可以使用 docker 命令行界面来管理你的容器和镜像。
  • 保障 Docker 安全:你可以配置 Docker 安全设置,例如启用 TLS 进行远程访问并设置用户权限。

按照这些步骤操作后,你的 Ubuntu 22.04 系统上应该就有一个可正常工作的 Docker 安装,准备好开始构建和运行 Docker 容器了。

构建 Docker 镜像

Dockerfile 基础

Docker 镜像是使用 Dockerfile 创建的,Dockerfile 是一个文本文件,其中包含一组用于构建镜像的指令。Dockerfile 指定了基础镜像、应用程序代码以及运行该应用程序所需的任何依赖项或配置。

以下是一个使用 Nginx 网络服务器创建简单 Web 服务器的 Dockerfile 示例:

## 使用最新的 Nginx 镜像作为基础
FROM nginx:latest

## 将 index.html 文件复制到容器的 Web 服务器目录
COPY index.html /usr/share/nginx/html/

## 将端口 80 暴露给主机
EXPOSE 80

## 容器启动时启动 Nginx Web 服务器
CMD ["nginx", "-g", "daemon off;"]

构建 Docker 镜像

要从 Dockerfile 构建 Docker 镜像,可以使用 docker build 命令:

docker build -t my-web-server.

此命令使用当前目录中的 Dockerfile 构建一个带有标签 my-web-server 的新 Docker 镜像。

你还可以使用 --build-arg 标志指定其他构建参数:

docker build -t my-web-server --build-arg APP_VERSION=1.0.0.

此命令在镜像构建过程中将 APP_VERSION 构建参数设置为 1.0.0

将 Docker 镜像推送到镜像仓库

构建好 Docker 镜像后,可以将其推送到 Docker 镜像仓库,如 Docker Hub 或私有镜像仓库,以便其他人可以共享和使用。要将镜像推送到镜像仓库,可以使用 docker push 命令:

docker push my-web-server:latest

此命令将 my-web-server:latest 镜像推送到默认的 Docker 镜像仓库。

通过了解如何构建和管理 Docker 镜像,你可以将应用程序创建并分发为可移植、一致且可扩展的容器。

运行和管理 Docker 容器

启动和停止容器

构建好 Docker 镜像后,你可以使用 docker run 命令基于该镜像创建并启动一个新容器:

docker run -d -p 80:80 --name my-web-server my-web-server

此命令从 my-web-server 镜像创建一个名为 my-web-server 的新容器,将主机上的端口 80 映射到容器中的端口 80,并以分离模式启动容器。

要停止正在运行的容器,可以使用 docker stop 命令:

docker stop my-web-server

管理容器

Docker 提供了几个用于管理正在运行的容器的命令:

  • docker ps:列出所有正在运行的容器
  • docker logs:显示容器的日志
  • docker exec:在正在运行的容器内执行命令
  • docker rm:删除已停止的容器

例如,要查看正在运行的容器的日志:

docker logs my-web-server

以及在正在运行的容器内执行命令:

docker exec -it my-web-server bash

此命令在 my-web-server 容器内打开一个交互式 shell 会话。

容器生命周期管理

Docker 容器具有一个生命周期,包括以下状态:

  • created:容器已创建但未启动。
  • running:容器当前正在运行。
  • paused:容器的进程已暂停。
  • stopped:容器已停止。
  • deleted:容器已被删除。

你可以使用 Docker 命令来管理容器的生命周期,例如 docker startdocker pausedocker unpausedocker rm

通过了解如何运行和管理 Docker 容器,你可以在容器化环境中有效地部署和维护你的应用程序。

使用 Docker 容器进行网络配置

Docker 网络驱动程序

Docker 提供了几种网络驱动程序,可让你为容器配置网络连接:

  • 桥接(Bridge):默认的网络驱动程序,它创建一个虚拟桥接网络,允许容器相互通信以及与主机系统通信。
  • 主机(Host):此驱动程序消除了容器与主机系统之间的网络隔离,允许容器直接使用主机的网络堆栈。
  • 覆盖(Overlay):此驱动程序创建一个多主机网络,允许在不同 Docker 主机上运行的容器相互通信。
  • Macvlan:此驱动程序允许你为容器分配一个 MAC 地址,使其在主机上看起来像一个物理网络接口。

你可以使用这些驱动程序创建自定义网络,并根据应用程序的要求将容器分配到特定的网络。

暴露端口和映射端口

运行容器时,可以使用 -p--publish 标志将容器中的端口暴露给主机系统。这允许外部系统访问容器内运行的服务。

例如,要运行一个 Web 服务器容器,并将主机上的端口 80 映射到容器中的端口 80:

docker run -d -p 80:80 --name my-web-server my-web-server

你还可以将主机上的特定端口映射到容器中的不同端口:

docker run -d -p 8080:80 --name my-web-server my-web-server

这将主机上的端口 8080 映射到容器中的端口 80。

容器到容器的网络通信

容器可以使用内置的 Docker 网络系统相互通信。默认情况下,同一网络上的容器可以使用它们的容器名称或 IP 地址相互通信。

你可以使用 docker network 命令创建自定义网络并将容器分配到这些网络。这使你能够控制容器化应用程序的网络拓扑和安全性。

graph TD A[Docker 主机] --> B[Docker 引擎] B --> C[容器 1] B --> D[容器 2] C --> E[自定义网络] D --> E

通过了解 Docker 网络配置,你可以有效地配置和管理容器化应用程序的网络连接。

Docker 卷与数据管理

理解 Docker 卷

Docker 卷是一种持久化容器所生成数据的方式。卷存储在容器文件系统之外,并且可以在容器之间共享或挂载到主机系统。这使你能够独立于容器的生命周期来存储和管理数据。

Docker 中有三种主要类型的卷:

  1. 命名卷:这些卷被分配一个唯一的名称,并由 Docker 管理。它们存储在主机系统上由 Docker 管理的一个目录中。
  2. 绑定挂载:这些卷将主机系统上的一个目录映射到容器内的一个目录。数据存储在主机系统上。
  3. 匿名卷:这些卷在容器启动时自动创建,但它们没有被分配名称,也不由 Docker 管理。

创建和管理卷

你可以使用 docker volume create 命令创建一个命名卷:

docker volume create my-data-volume

然后,你可以使用 -v--mount 标志将这个卷挂载到一个容器:

docker run -d -v my-data-volume:/data my-app

这会将 my-data-volume 卷挂载到容器内的 /data 目录。

要管理卷,你可以使用以下命令:

  • docker volume ls:列出所有卷
  • docker volume inspect:显示有关一个卷的详细信息
  • docker volume rm:删除一个卷

备份和恢复卷

要备份一个 Docker 卷,你可以使用 docker run 命令创建一个容器,该容器将卷数据导出到一个 tar 存档:

docker run --rm -v my-data-volume:/data -v /tmp:/backup busybox tar cvf /backup/backup.tar /data

此命令创建 my-data-volume 卷的备份,并将其存储在主机系统上的 /tmp/backup.tar 文件中。

要从备份中恢复一个卷,你可以使用 docker run 命令从 tar 存档中提取数据:

docker run --rm -v my-data-volume:/data -v /tmp:/backup busybox tar xvf /backup/backup.tar -C /data

此命令从 /tmp/backup.tar 文件中提取数据,并将其恢复到 my-data-volume 卷。

通过了解如何使用 Docker 卷,你可以确保你的容器化应用程序能够有效地持久化和管理它们的数据。

用于多容器应用的 Docker Compose

Docker Compose 简介

Docker Compose 是一个工具,它允许你使用 YAML 配置文件来定义和管理多容器应用程序。借助 Docker Compose,你可以轻松定义构成应用程序的服务、网络和卷,然后使用单个命令来启动、停止和管理整个应用程序堆栈。

创建 Docker Compose 文件

以下是一个 Docker Compose 文件的示例,它定义了一个包含 Web 服务器和数据库的简单 Web 应用程序:

version: "3"

services:
  web:
    build:.
    ports:
      - "80:80"
    depends_on:
      - db
    environment:
      - DB_HOST=db
      - DB_USER=myapp
      - DB_PASSWORD=secret

  db:
    image: mysql:5.7
    environment:
      - MYSQL_DATABASE=myapp
      - MYSQL_USER=myapp
      - MYSQL_PASSWORD=secret
      - MYSQL_ROOT_PASSWORD=root
    volumes:
      - db-data:/var/lib/mysql

volumes:
  db-data:

此 Compose 文件定义了两个服务:一个 Web 服务器和一个 MySQL 数据库。Web 服务器是从当前目录中的 Dockerfile 构建的,并且它依赖于数据库服务。数据库服务使用官方 MySQL 镜像,并将其数据持久保存到一个命名卷中。

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

创建 Compose 文件后,你可以使用 docker-compose 命令来管理你的应用程序:

  • docker-compose up:启动应用程序
  • docker-compose down:停止应用程序
  • docker-compose ps:列出正在运行的容器
  • docker-compose logs:显示应用程序的日志
  • docker-compose exec:在正在运行的容器中执行命令

例如,要启动上一个 Compose 文件中定义的应用程序:

docker-compose up -d

此命令以分离模式启动应用程序,允许你继续使用终端。

通过使用 Docker Compose,你可以轻松管理复杂的多容器应用程序,并确保所有必要的服务和依赖项都得到正确配置和部署。

Docker 容器的最佳实践

优化镜像大小

Docker 的一个关键优势在于能够创建小巧、轻量级的镜像。为了优化镜像大小,可参考以下最佳实践:

  • 尽可能使用最小化的基础镜像,例如 alpinescratch
  • 避免在 Dockerfile 中安装不必要的软件包或依赖项。
  • 使用多阶段构建来分离构建和运行时依赖项。
  • 利用 Docker 的构建缓存来加速镜像构建。

保障容器安全

为确保 Docker 容器的安全性,请遵循以下最佳实践:

  • 使 Docker 守护进程和容器保持更新,安装最新的安全补丁。
  • 使用可信赖的基础镜像,并验证依赖项的完整性。
  • 通过使用 --user 标志或以非 root 用户身份运行容器,来限制容器的权限。
  • 启用 AppArmor 或 SELinux 等安全功能,进一步限制容器的能力。
  • 监控容器是否存在安全漏洞,并定期进行更新。

管理容器日志

正确的日志记录对于排查 Docker 容器故障和进行监控至关重要。可考虑以下最佳实践:

  • 使用默认的 json-file 日志驱动,以结构化格式存储容器日志。
  • 轮转并归档容器日志,防止它们填满主机存储。
  • 使用日志管理解决方案,如 Elasticsearch、Fluentd 或 Splunk,来集中管理和分析容器日志。

优化容器启动时间

为确保容器能够快速高效地启动,可参考以下最佳实践:

  • 使用最小化的基础镜像,仅安装必要的依赖项。
  • 优化你的 Dockerfile,以利用 Docker 的构建缓存。
  • 使用轻量级的初始化系统,如 tinidumb-init,来管理容器进程。
  • 避免在容器内部运行不必要的服务或进程。

借助 LabEx 管理容器化应用

LabEx 是一个强大的平台,可帮助你构建、部署和管理容器化应用。通过利用 LabEx,你可以受益于其最佳实践和功能,例如:

  • 自动化镜像构建和部署
  • 可扩展且高可用的容器编排
  • 集成式监控和日志记录
  • 与云平台和 CI/CD 工具的无缝集成

要了解有关在容器化应用中使用 LabEx 的更多信息,请访问 LabEx 网站

通过遵循这些最佳实践,你可以确保你的 Docker 容器安全、高效且易于管理,从而能够构建和部署高质量、可扩展的应用程序。

总结与后续步骤

在本指南中,我们涵盖了使用 Docker 容器的基本概念和实践方面。我们探讨了 Docker 架构,学习了如何安装和配置 Docker,并深入研究了构建、运行和管理 Docker 容器的过程。

我们还讨论了 Docker 网络、卷和数据管理,以及使用 Docker Compose 来管理多容器应用程序。最后,我们提供了一组最佳实践,以帮助你优化和保障 Docker 容器的安全。

既然你已经对 Docker 有了扎实的理解,以下是一些你可以采取的后续步骤,以进一步提升你的技能和知识:

探索高级 Docker 概念

  • 了解用于容器编排的 Docker Swarm 和 Kubernetes
  • 理解 Docker 安全功能,如内容信任(Content Trust)和公证(Notary)
  • 探索 Docker 与云平台以及 CI/CD 工具的集成

实践与实验

  • 构建并部署你自己的容器化应用程序
  • 探索开源 Docker 项目并为社区做出贡献
  • 参加在线 Docker 教程、工作坊和挑战

紧跟 Docker 生态系统

  • 关注最新的 Docker 新闻、更新和最佳实践
  • 参加本地的 Docker 聚会或会议,建立人脉并向社区学习
  • 探索 LabEx 平台以进行高级容器管理和部署

通过持续扩展你的 Docker 知识和技能,你将有充分的准备来应对各种应用程序开发和部署挑战,并为不断发展的容器化解决方案生态系统做出贡献。

总结

在本教程中,你已经了解了 Docker 容器的基本概念、其架构以及它们的工作方式。你探索了安装和配置 Docker 的过程、构建 Docker 镜像、运行和管理 Docker 容器,以及在多容器应用程序中利用 Docker Compose。通过理解 Docker 容器的强大功能,你现在可以自信地将它们纳入你的软件开发和部署工作流程中,从而提高效率、可扩展性和可移植性。