检索现有 Docker 映像并本地部署

已完成

Docker 是一种使你能够快速轻松地部署应用程序和服务的技术。 Docker 应用使用 Docker 映像运行。 Docker 映像是包含应用程序代码的环境和执行代码的环境。

在前面所述的企业方案中,你想调查使用 Docker 打包和运行应用的可行性。 你决定生成和部署运行测试 Web 应用的 Docker 映像。

在本单元中,你将了解运行 Docker 映像中存储的容器化应用所涉及的关键概念和过程。

Docker 概述

Docker 是用于运行容器化应用的工具。 容器化应用包括应用和文件系统,这些要素组成其运行的环境。 例如,容器化应用可以包含数据库和其他关联的软件以及运行该应用所需的配置信息。

容器化应用通常比配置为运行同一应用的虚拟机拥有更小的内存占用情况。 这是因为虚拟机必须支持整个操作系统和相关的支持环境。 Docker 容器则没有此负担,因为 Docker 使用主计算机的操作系统内核来支持容器。 下载并启动 Docker 映像比下载和运行提供相似功能的虚拟机要更快且更省空间。

通过生成包含 Docker 使用的一组文件和一系列配置信息的映像来创建容器化应用。 通过要求 Docker 启动基于映像的容器来运行应用。 容器启动时,Docker 使用映像配置来决定容器内运行的应用程序。 Docker 提供操作系统资源和必要的安全性。 它确保容器并发运行,并保持 相对隔离

重要

Docker 无法提供虚拟机可以提供的隔离级别。 虚拟机在硬件级别实现隔离。 Docker 容器可以共享基础操作系统资源和库。 但 Docker 容器之间无法相互共享资源,除非配置使然。

如果在本地开发和测试,则可以在台式机或笔记本电脑上运行 Docker。 对于生产系统,Docker 适用于服务器环境,包括 Linux 和 Microsoft Windows Server 2016 的多种变体。 许多供应商也支持云中的 Docker。 例如,可以在 Azure 容器注册表中存储 Docker 映像并使用 Azure 容器实例中运行容器。

在此模块中,你将在本地使用 Docker 来生成和运行映像。 将映像上传到 Azure 容器注册表,并在 Azure 容器实例中运行。 此版本的 Docker 适用于在本地开发和测试 Docker 映像。

Linux 和 Windows Docker 映像

Docker 最初面向 Linux 开发,然后扩展到支持 Windows。 单个 Docker 映像可以基于 Windows,也可以基于 Linux,但不能同时基于两者。 映像的操作系统决定了容器内使用的操作系统环境的类型。

想要在基于 Linux 和基于 Windows 的映像中提供相似功能的 Docker 映像的作者可以单独生成这些映像。 例如,Microsoft 提供包含 ASP.NET Core 环境的 Windows 和 Linux Docker 映像,该环境可用作容器化 ASP.NET Core 应用程序的基础。

已安装 Docker 的 Linux 计算机只能运行 Linux 容器。 已安装 Docker 的 Windows 计算机可以运行这两种类型的容器。 Windows 既使用虚拟机来运行 Linux 系统,也使用虚拟 Linux 系统来运行 Linux 容器。

在此模块中,你将生成和运行基于 Linux 的映像。

Docker 注册表和 Docker 中心

在注册表中可以存储和提供 Docker 映像。 注册表是 Web 服务,Docker 可以连接到它以上传和下载容器映像。 最众所周知的注册表为 Docker 中心,它是一个公共注册表。 许多个人和组织将映像发布到 Docker Hub,你可以使用台式机、服务器和云中运行的 Docker 下载和运行这些映像。 在 Docker Hub 可以免费创建 Docker Hub 帐户和上传自己的映像。

注册表被整理为一系列存储库。 每个存储库都包含多个 Docker 映像,这些映像共享一个公用名,通常具有相同的用途和功能。 这些映像通常具有不同的版本,可通过标记进行识别。 此机制让你可以出于兼容性原因发布和维持多个版本的映像。 下载和运行映像时,必须为映像指定注册表、存储库和版本标记。 标记为文本标签,你可以使用自己的版本号系统(v1.0、v1.1、v1.2、v2.0 等)。

假设要使用 ASP.NET Core 运行时 Docker 映像。 该映像提供有两个版本:

  • mcr.microsoft.com/dotnet/core/aspnet:2.2
  • mcr.microsoft.com/dotnet/core/aspnet:2.1

现在,假设要使用 .NET Core 示例 Docker 映像。 这里有四个版本可供选择:

  • mcr.microsoft.com/dotnet/samples:dotnetapp
  • mcr.microsoft.com/dotnet/samples:aspnetapp

注意

单个映像可以分配有多个标记。 按照约定,最新版本的映像除了分配有描述其版本号的标记外,还分配有 latest 标记。 当发布新版本的映像时,可以重新分配 latest 标记以引用新映像。

存储库也是映像的专用单元。 如果你不想共享映像,可以将存储库设置为专用。 你可以授权给你想要与之共享映像的其他用户。

浏览 Docker 中心并拉取映像

注意

无需完成以下部分中的任何示例或运行任何代码。 你将在下一单元中执行此操作。

通常你会在 Docker Hub 中发现一个映像,它与想要容器化的应用类型极其相近。 可以下载此类映像,并使用你自己的应用程序代码来扩展它。

Docker Hub 包含数以千计的映像。 你可以从命令行或 Docker Hub 网站使用 Docker 搜索和浏览注册表。 可在该网站按类型和发布者搜索、筛选和选择映像。 下图显示了搜索页面的示例。

Docker Hub 搜索页的屏幕截图,其中列出了各种容器映像。

使用带映像名称的 docker pull 命令检索映像。 如果仅指定存储库,默认情况下,Docker 将从 Docker Hub 的该存储库下载带 latest 标记的映像。 请记住,可以通过修改命令从其他存储库拉取不同的标记。 此示例从 mcr.microsoft.com/dotnet/core/samples:aspnetapp 存储库中提取带有 aspnetapp 标记的映像。 该映像包含一个简单的 ASP.NET Core Web 应用。

注意

本单元中的示例旨在显示各种 Docker 命令的语法。 阅读本单元时不需要运行这些命令。 本单元后的练习将指导你直接使用 Docker。

docker pull mcr.microsoft.com/dotnet/samples:aspnetapp

当你提取映像时,Docker 将其存储在本地并使其可用于运行的容器。 可以使用 docker image list 命令查看本地注册表中的映像。

docker image list

输出如下所示:

REPOSITORY TAG IMAGE ID CREATED SIZE
mcr.microsoft.com/dotnet/samples   aspnetapp           6e2737d83726        6 days ago          263MB

使用映像名称 ID 引用许多其他 Docker 命令中的映像。

运行 Docker 容器

使用 docker run 命令启动该容器。 指定映像使用其名称和 ID 运行。 如果你还没有对映像执行 docker pull ,Docker 将为你代劳。

docker run mcr.microsoft.com/dotnet/samples:aspnetapp

在此示例中,该命令将使用以下消息进行响应:

warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
 No XML encryptor configured. Key {d8e1e1ea-126a-4383-add9-d9ab0b56520d} may be persisted to storage in unencrypted form.
Hosting environment: Production
Content root path: /app
Now listening on: http://[::]:80
Application started. Press Ctrl+C to shut down.

此映像包含 Web 映像,所以它现在侦听到达 HTTP 端口 80 的请求。 但是,如果打开 Web 浏览器并导航到 http://localhost:80,则不会看见此应用。

默认情况下,Docker 不允许入站网络请求访问容器。 需要告知 Docker 通过向 docker run 添加 -p 选项,将计算机中的指定端口号分配给容器中的特定端口号。 此指令可启用到指定端口上的容器的网络请求。

此外,我们并不打算从命令行以交互方式使用此映像中的 Web 应用。 启动应用时,我们想让 Docker 在后台启动它并让其运行。 可使用 -d 标志指示 Docker 在后台启动 Web 应用。

按 Ctrl+C 停止该映像,然后重启它,如以下示例所示

docker run -p 8080:80 -d mcr.microsoft.com/dotnet/samples:aspnetapp

该命令将容器中的端口 80 映射到计算机上的端口 8080。 如果访问浏览器中的 http://localhost:8080 页面,将看见示例 Web 应用。

在浏览器中运行的示例 Web 应用的屏幕截图。

容器和文件

如果运行的容器更改了映像中的文件,这些更改仅存在于进行了更改的容器中。 除非采用特定步骤来保持容器的状态,否则删除容器时这些更改将丢失。 同样的,基于同一映像同时运行的多个容器不共享映像中的文件。 每个容器都有自己的独立副本。 一个容器写入其文件系统的任何数据都对其他容器不可见。

可以将可写入卷添加到容器。 卷表示可以由容器装入的文件系统,并且可供容器中运行的应用程序使用。 容器停止时,卷中的数据会保留,多个容器可以共享同一个卷。 创建和使用卷的详细信息不在此模块的范围内。

对于使用 Docker 部署的应用程序,最佳做法是避免对其映像文件系统进行更改。 仅将它用于临时文件,即使丢失也影响不大。

管理 Docker 容器

可以使用 docker ps 命令查看活动容器。

docker ps

输出包括容器状态(运行时为“Up”,终止时为“Exited”)以及其他值,例如启动映像时指定的命令行标记以及其他信息。 Docker 让你可以从同一个映像中同时运行多个容器,所以每一个容器都分配有唯一的 ID 和唯一的易读名称。 用于管理单个容器的大多数 Docker 命令可以使用 ID 或名称来引用特定容器。

在下面的输出中,可以看见两个容器。 PORTS 字段显示 ID 为 的容器是在映射到计算机上端口 8080 的 Docker 主机上的端口 80 开启时运行的映像。 youthful_heisenberg 实例是上次运行映像的容器。 COMMAND 字段显示容器为了启动映像中的应用程序所运行的命令。 在这种情况下,对于这两个容器而言,该命令均为“dotnet aspnetapp.dll”。 请注意,容器的映像 ID 也是相同的,因为这两个容器都执行相同的映像。

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
57b9587583e3        mcr.microsoft.com/dotnet/core/samples:aspnetapp   "dotnet aspnetapp.dll"   42 seconds ago      Up 41 seconds       0.0.0.0:8080->80/tcp   elegant_ramanujan
d27071f3ca27        mcr.microsoft.com/dotnet/core/samples:aspnetapp   "dotnet aspnetapp.dll"   5 minutes ago      Up 5 minutes       0.0.0.0:8081->80/tcp   youthful_heisenberg

注意

docker psdocker container ls 的快捷方式。 这些命令的名称基于 Linux 实用程序 psls,这些实用程序分别列出正在运行的进程和文件。

可以使用 docker stop 命令并指定容器 ID 来停止活动容器。

docker stop elegant_ramanujan

如果再次运行 docker ps,你将看见 elegant_ramanujan 容器不再显示在输出中。 该容器仍然存在,但不再托管正在运行的进程。 可以通过加入 -a 标记,在 docker ps 的输出中加入已停止的容器:

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
57b9587583e3        mcr.microsoft.com/dotnet/core/samples:aspnetapp   "dotnet aspnetapp.dll"   2 minutes ago       Exited (0) 21 seconds ago                       elegant_ramanujan
d27071f3ca27        mcr.microsoft.com/dotnet/core/samples:aspnetapp   "dotnet aspnetapp.dll"   7 minutes ago      Up 7 minutes       0.0.0.0:8081->80/tcp   youthful_heisenberg

可以使用 docker start 命令重启已停止的容器。 容器的主进程将重新启动。

docker start elegant_ramanujan

通常情况下,容器停止后,也应被删除。 删除容器将清理它留下的任何资源。 一旦删除容器,其映像文件系统中所做的任何更改都将永久丢失。

docker rm elegant_ramanujan

不能删除正在运行的容器,但可以通过将 -f 标记用于 docker rm 命令来强制停止和删除容器。 这是停止和删除容器的快速方法,但此方法应仅在容器中的应用无需执行正常关闭时才使用。

docker container rm -f elegant_ramanujan

删除 Docker 映像

可以使用 docker image rm 命令删除本地计算机中的映像。 指定要删除的映像的映像 ID。 以下示例删除示例 Web 应用的映像。

docker image rm mcr.microsoft.com/dotnet/core/samples:aspnetapp

删除映像前,必须终止运行映像的容器。 如果映像仍在被容器使用,将收到如下所示的错误消息。 在此示例中,因为 youthful_heisenberg 容器仍在使用映像,所以发生错误。

Error response from daemon: conflict: unable to delete 575d85b4a69b (cannot be forced) - image is being used by running container c13165988cfe