如何高效配置和运行 Docker 容器

DockerDockerBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

介绍

本教程是一份全面的 Docker 指南,旨在为开发者和 IT 专业人士提供对容器技术的深入了解。从理解核心 Docker 概念到实际的安装和管理技术,本指南涵盖了利用 Docker 强大的容器化能力进行现代软件开发和部署所需的一切。

Docker 基础

容器技术介绍

Docker 是一个强大的容器技术平台,它使开发者能够高效地打包、分发和运行应用程序。容器提供轻量级、可移植的环境,封装了软件及其依赖项。

核心 Docker 概念

graph TD A[Docker Engine] --> B[Container] A --> C[Image] A --> D[Dockerfile]
概念 描述
Docker Image 包含应用程序代码和依赖项的只读模板
Container Docker 镜像的可运行实例
Docker Engine 用于创建和管理容器的运行时环境

验证 Docker 安装

你的 LabEx 环境已预装 Docker。让我们验证 Docker 版本,以确保它已准备就绪。

docker --version

输出应显示 Docker 版本,例如 Docker version 20.10.21, build baeda1f。这证实 Docker 已正确安装并可访问。

拉取你的第一个 Docker 镜像

Docker 镜像是一个只读模板,其中包含创建容器的一系列指令。我们将拉取 hello-world 镜像,这是一个用于测试 Docker 安装的最小镜像。

docker pull hello-world

此命令将 Docker Hub 中的 hello-world 镜像下载到你的本地机器。你应该会看到指示下载进度和镜像已拉取的确认信息。

运行你的第一个 Docker 容器

现在我们有了镜像,让我们从中运行一个容器。运行容器意味着创建一个镜像的实例。

docker run hello-world

当你运行 hello-world 时,Docker 会执行以下操作:

  1. 它会检查 hello-world 镜像是否已存在于本地。如果不存在,它会将其拉取(我们已经完成了这一步)。
  2. 它会从镜像创建一个新容器。
  3. 它会在容器内运行可执行文件。
  4. 容器会打印一条 "Hello from Docker!" 消息,然后退出。

这演示了 Docker 容器的基本生命周期:拉取镜像,运行容器,然后容器执行其定义的任务。

列出 Docker 镜像

要查看你已下载的镜像,请使用 docker images 命令。

docker images

此命令会列出存储在你本地系统上的所有 Docker 镜像,包括我们刚刚拉取的 hello-world 镜像。你将看到诸如仓库、标签、镜像 ID、创建日期和大小等详细信息。

理解容器生命周期

容器提供隔离的环境,拥有自己的文件系统、进程和网络接口。它们可以被快速地启动、停止、移动和删除,这使得它们成为微服务和云原生应用程序的理想选择。

Dockerfile 文件管理

Dockerfile 基础

Dockerfile 是一个文本文档,其中包含用户在命令行中可以调用的所有指令,用于构建镜像。它定义了容器化应用程序的环境、依赖项和配置。

graph TD A[Dockerfile] --> B[Build Command] B --> C[Docker Image] C --> D[Container]

创建你的第一个 Dockerfile

导航到 docker_app 目录,该目录在设置阶段已创建。这将是我们本次实验的工作目录。

cd /home/labex/project/docker_app

现在,让我们在此目录中创建一个名为 Dockerfile 的简单 Dockerfile。此 Dockerfile 将创建一个基于 Ubuntu 的镜像,并向其中添加一个简单的文本文件。

nano Dockerfile

Dockerfile 添加以下内容:

## 使用官方 Ubuntu 基础镜像
FROM ubuntu:22.04

## 设置容器内的工作目录
WORKDIR /app

## 创建一个简单的文本文件
RUN echo "Hello from Dockerfile!" > /app/message.txt

## 容器启动时执行的命令
CMD ["cat", "/app/message.txt"]
  • FROM ubuntu:22.04: 此指令指定了我们新镜像的基础镜像。我们使用的是 Ubuntu 22.04。
  • WORKDIR /app: 此指令设置了 Dockerfile 中后续所有 RUNCMDENTRYPOINTCOPYADD 指令的工作目录。如果 /app 不存在,它将被创建。
  • RUN echo "Hello from Dockerfile!" > /app/message.txt: 此指令在构建过程中在镜像内执行一个命令。在这里,它在 /app 目录中创建了一个名为 message.txt 的文件,内容为 "Hello from Dockerfile!"。
  • CMD ["cat", "/app/message.txt"]: 此指令为正在运行的容器提供了默认命令。当从该镜像运行容器时,它将执行 cat /app/message.txt,显示我们消息文件的内容。

Ctrl+S 保存文件,然后按 Ctrl+X 退出 nano

构建你的 Docker 镜像

现在我们有了 Dockerfile,让我们从中构建 Docker 镜像。docker build 命令会读取 Dockerfile 并创建一个 Docker 镜像。

docker build -t my-ubuntu-app .
  • docker build: 构建 Docker 镜像的命令。
  • -t my-ubuntu-app: 这将我们的镜像标记为 my-ubuntu-app。你可以选择任何你喜欢的名称。
  • .: 这指定了构建上下文,即指定路径或 URL 处的文件的集合。. 表示当前目录 (/home/labex/project/docker_app) 是构建上下文。Docker 将在此目录中查找 Dockerfile

你将看到显示构建过程每一步的输出,对应于 Dockerfile 中的指令。

运行你的自定义 Docker 容器

成功构建镜像后,让我们从中运行一个容器来查看 message.txt 的内容。

docker run my-ubuntu-app

此命令将从你的 my-ubuntu-app 镜像创建一个新容器并运行它。你的 Dockerfile 中的 CMD 指令将被执行,你应该会在终端看到 "Hello from Dockerfile!" 被打印出来。

检查容器的文件系统

为了进一步了解容器内文件的管理方式,让我们运行一个交互式会话并检查我们创建的文件。

docker run -it my-ubuntu-app /bin/bash
  • -it: 此标志分配一个伪终端(pseudo-TTY)并保持 STDIN 打开,允许你与容器进行交互。
  • my-ubuntu-app: 我们想要运行的镜像名称。
  • /bin/bash: 这会覆盖 Dockerfile 中的 CMD 指令,转而在容器内运行 Bash shell,为你提供一个命令提示符。

进入容器后,你将看到一个新的命令提示符(例如 root@<container_id>:/app#)。现在,你可以列出文件并查看 message.txt 的内容。

ls -l
cat message.txt

你应该会看到 message.txt 被列出,并且其内容被显示出来。要退出容器,只需键入 exit

exit

这个交互式会话表明文件 message.txt 已成功创建,并且可以在容器的文件系统中访问。

高级 Docker 技术

多阶段构建策略

多阶段构建是一项强大功能,它允许你在 Dockerfile 中使用多个 FROM 语句。每个 FROM 指令都可以使用不同的基础镜像,并且每个 FROM 指令都会启动一个新的构建阶段。通过分离构建和运行时环境,这有助于优化 Dockerfile 的复杂性并减小最终镜像的大小。

graph TD A[Build Stage] --> B[Compile/Build] B --> C[Runtime Stage] C --> D[Minimal Production Image]

为多阶段构建做准备

在本示例中,我们将模拟一个需要构建步骤的简单应用程序。我们将创建一个 build_script.sh 和一个 final_app.txt 文件。

首先,请确保你位于 docker_app 目录:

cd /home/labex/project/docker_app

现在,创建一个简单的构建脚本:

nano build_script.sh

build_script.sh 添加以下内容:

#!/bin/bash
echo "Running build process..."
echo "This is the final application output." > /app/output/final_app.txt
echo "Build complete."

保存文件(Ctrl+S)并退出(Ctrl+X)。

接下来,为我们的最终应用程序内容创建一个占位符。在实际场景中,这会由构建过程生成。

nano final_app.txt

final_app.txt 添加以下内容:

This is a placeholder for the final application.

保存文件(Ctrl+S)并退出(Ctrl+X)。

实现多阶段 Dockerfile

现在,让我们修改我们的 Dockerfile 以使用多阶段构建。我们将有一个“构建器”阶段来运行我们的 build_script.sh,然后是一个“生产”阶段,它只从构建器阶段复制必要的输出。

nano Dockerfile

将现有内容替换为以下内容:

## Stage 1: Builder stage
FROM ubuntu:22.04 AS builder

## 安装 bash 以运行脚本
RUN apt-get update && apt-get install -y bash

## 设置构建器阶段的工作目录
WORKDIR /build

## 复制构建脚本并使其可执行
COPY build_script.sh .
RUN chmod +x build_script.sh

## 创建一个输出目录
RUN mkdir -p /build/output

## 运行构建脚本
RUN ./build_script.sh

## Stage 2: Production stage
FROM ubuntu:22.04

## 设置生产阶段的工作目录
WORKDIR /app

## 只从构建器阶段复制必要的产物
COPY --from=builder /build/output/final_app.txt .

## 容器启动时执行的命令
CMD ["cat", "final_app.txt"]
  • FROM ubuntu:22.04 AS builder: 这启动了第一个阶段并将其命名为 builder
  • RUN apt-get update && apt-get install -y bash: 在构建器阶段安装 bash,这是运行我们的脚本所必需的。
  • WORKDIR /build: 设置构建器阶段的工作目录。
  • COPY build_script.sh .: 将我们的构建脚本复制到构建器阶段。
  • RUN chmod +x build_script.sh: 使脚本可执行。
  • RUN mkdir -p /build/output: 在构建器阶段创建一个输出目录。
  • RUN ./build_script.sh: 执行构建脚本,该脚本在 /build/output 中生成 final_app.txt
  • FROM ubuntu:22.04: 这启动了第二个阶段(生产阶段)。它使用了一个新的 ubuntu:22.04 镜像,这意味着它默认不会继承 builder 阶段的任何内容。
  • WORKDIR /app: 设置生产阶段的工作目录。
  • COPY --from=builder /build/output/final_app.txt .: 这是多阶段构建的关键指令。它将 builder 阶段的 /build/output 目录中的 final_app.txt 复制到生产阶段的当前目录(/app)。这确保了只包含最终产物,从而使生产镜像保持较小。
  • CMD ["cat", "final_app.txt"]: 生产容器启动时要执行的命令,显示复制文件的内容。

保存文件(Ctrl+S)并退出(Ctrl+X)。

构建和运行多阶段镜像

现在,让我们使用我们的多阶段 Dockerfile 构建新镜像。

docker build -t multi-stage-app .

观察构建输出。你将看到 builder 阶段和最终阶段的步骤。

构建完成后,运行容器以验证是否显示了 final_app.txt 的内容。

docker run multi-stage-app

你应该会看到 "This is the final application output." 被打印出来,这证实了多阶段构建已成功将产物从构建阶段复制到最终镜像。

清理 Docker 资源

清理不再需要的 Docker 资源(容器和镜像)以释放磁盘空间是一个好习惯。

首先,列出所有容器(包括已退出的):

docker ps -a

你可以通过容器的 ID 或名称删除特定容器:

docker rm $(docker ps -aq)

此命令会删除所有已退出的容器。docker ps -aq 列出所有容器 ID,docker rm 则删除它们。

接下来,列出所有镜像:

docker images

你可以通过镜像的 ID 或名称删除特定镜像。请注意不要删除仍被运行中的容器使用的镜像。

docker rmi my-ubuntu-app multi-stage-app hello-world ubuntu:22.04

此命令会删除我们在本次实验中创建和使用的镜像。如果镜像仍被容器使用,你需要先删除该容器。

docker images

此命令将显示镜像已被删除。

至此,关于 Docker 基础和高级技术的实验结束。你已经学会了如何创建 Dockerfile、构建镜像、运行容器以及使用多阶段构建优化镜像大小。

总结

通过掌握 Docker 基础知识、Dockerfile 管理和高级技术,开发者可以创建更高效、可移植且可扩展的软件环境。本教程为你提供了容器创建、镜像管理和部署策略方面的实践技能,使你能够简化开发工作流程并拥抱云原生应用程序架构。