Contents

Docker镜像和容器之间的区别

1. 概述

Docker 是一种用于轻松创建、部署和运行应用程序的工具。它允许我们将应用程序与所有依赖项打包在一起,并将它们作为单独的包分发。Docker 保证我们的应用程序将在每个 Docker 实例上以相同的方式运行。

当我们开始使用 Docker 时,我们需要明确两个主要概念——镜像和容器

在本教程中,我们将了解它们是什么以及它们有何不同。

2. Docker 镜像

映像是一个文件,它代表一个打包的应用程序,其中包含正确运行所需的所有依赖项。换句话说,我们可以说Docker 镜像就像一个 Java 类

镜像被构建为一系列层。层被组装在彼此的顶部。那么,什么是层?简单地说,一个层就是一个镜像。

假设我们要创建一个 Hello World Java 应用程序的 Docker 映像。我们需要考虑的第一件事是我们的应用程序需要什么。

首先,它是一个 Java 应用程序,所以我们需要一个 JVM。好的,这看起来很简单,但是 JVM 需要运行什么?它需要一个操作系统。因此,我们的 Docker 镜像将有一个操作系统层、一个 JVM 和我们的 Hello World 应用程序

Docker 的一个主要优势是其庞大的社区。如果我们想在镜像上构建,我们可以去Docker Hub 并搜索我们需要的镜像是否可用。

假设我们要创建一个数据库,使用PostgreSQL 数据库。我们不需要从头开始创建新的 PostgreSQL 映像。我们只要去 Docker Hub,搜索postgres,这是 PostgresSQL 的 Docker 官方镜像名称,选择我们需要的版本,然后运行它。

我们从 Docker Hub 创建或提取的每个镜像都存储在我们的文件系统中,并通过其名称和标签进行标识。它也可以通过它的镜像 id来识别。

使用docker images命令,我们可以查看文件系统中可用的镜像列表:

$ docker images
REPOSITORY           TAG                 IMAGE ID            CREATED             SIZE
postgres             11.6                d3d96b1e5d48        4 weeks ago         332MB
mongo                latest              9979235fc504        6 weeks ago         364MB
rabbitmq             3-management        44c4867e4a8b        8 weeks ago         180MB
mysql                8.0.18              d435eee2caa5        2 months ago        456MB
jboss/wildfly        18.0.1.Final        bfc71fe5d7d1        2 months ago        757MB
flyway/flyway        6.0.8               0c11020ffd69        3 months ago        247MB
java                 8-jre               e44d62cf8862        3 years ago         311MB

3. 运行 Docker 镜像

使用带有镜像名称和标签的docker run命令运行镜像。假设我们要运行 postgres 11.6 映像:

docker run -d postgres:11.6

请注意,我们提供了*-d*选项。这告诉 Docker 在后台运行映像——也称为分离模式。

使用docker ps命令我们可以检查我们的镜像是否正在运行,我们应该使用这个命令:

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
3376143f0991        postgres:11.6       "docker-entrypoint.s…"   3 minutes ago       Up 3 minutes        5432/tcp            tender_heyrovsky

请注意上面输出中的CONTAINER ID。让我们来看看容器是什么以及它与镜像的关系。

4. Docker 容器

容器是镜像的一个实例。每个容器都可以通过它的 ID 来识别。回到我们的 Java 开发类比,我们可以说容器就像一个类的实例

Docker 为容器定义了七种状态:createdrestartingrunningremovingpausedexiteddead。了解这一点很重要。由于容器只是镜像的一个实例,它不需要运行。

现在让我们再想想上面看到的运行命令。我们已经说过它用于运行镜像,但这并不完全准确。事实上,run命令用于create * 和start * 镜像的新容器。

一大优势是容器就像轻量级虚拟机。他们的行为彼此完全隔离。这意味着我们可以运行同一个镜像的多个容器,每个容器都处于不同的状态,具有不同的数据和不同的 ID。

能够同时运行同一镜像的多个容器是一个很大的优势,因为它使我们能够轻松地扩展应用程序。例如,让我们考虑一下微服务。如果每个服务都打包为 Docker 镜像,那么这意味着新服务可以按需部署为容器。

5. 容器生命周期

前面我们提到了容器的七种状态,现在我们来看看如何使用docker命令行工具来处理不同的生命周期状态。

启动一个新容器需要我们创建它然后启动它。这意味着它必须经过创建状态才能运行。我们可以通过显式创建和启动容器来做到这一点:

docker container create <image_name>:<tag>
docker container start <container_id>

或者我们可以使用run命令轻松地做到这一点:

docker run <image_name>:<tag>

我们可以暂停一个正在运行的容器,然后再次将其置于运行状态:

docker pause <container_id>
docker unpause <container_id>

当我们检查进程时,暂停的容器将显示“暂停”作为状态:

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                  PORTS               NAMES
9bef2edcad7b        postgres:11.6       "docker-entrypoint.s…"   5 minutes ago       Up 4 minutes (Paused)   5432/tcp            tender_heyrovsky

我们也可以停止一个正在运行的容器,然后重新运行它:

docker stop <container_id>
docker start <container_id>

最后,我们可以移除一个容器:

docker container rm <container_id>

只有处于停止或创建状态的容器才能被移除。

有关 Docker 命令的更多信息,我们可以参考Docker 命令行参考