1. 概述

Docker 是一个用于创建、部署和运行应用程序的工具。它允许我们将应用程序与其所有依赖打包在一起,并作为一个独立的单元进行分发。Docker 的一大优势在于它能确保我们的应用在任何支持 Docker 的环境中都能以相同的方式运行。

在我们开始使用 Docker 时,有两个核心概念必须搞清楚:镜像(Image)容器(Container)

在本教程中,我们会了解它们的定义以及它们之间的区别。

2. Docker 镜像

镜像(Image)是一个包含了运行所需全部依赖的打包文件。简单来说,你可以把它理解为一个 Java 类(Class) —— 它是一个模板,不能直接运行,但可以被用来创建多个实例。

Docker 镜像是由多个 层(Layer) 构成的,每一层都是一个只读的文件系统层。这些层叠加在一起,最终构成了一个完整的镜像。

举个例子,如果我们想为一个 Java 的 Hello World 程序创建一个镜像,我们需要考虑以下几点:

  • 它是一个 Java 应用,因此需要 JVM
  • JVM 又依赖操作系统环境

所以最终我们的镜像结构可能是:操作系统层 + JVM 层 + 应用程序层

Docker 社区非常活跃,我们通常不需要从零开始构建镜像。比如,想使用 PostgreSQL 数据库,我们可以直接从 Docker Hub 搜索官方镜像 postgres 并使用。

我们可以使用 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

每个镜像都有一个 镜像名(REPOSITORY)标签(TAG)镜像ID(IMAGE ID),用于唯一标识。

3. 运行 Docker 镜像

我们可以使用 docker run 命令来运行一个镜像:

docker run -d postgres:11.6

其中 -d 表示 后台运行模式(detached mode)

运行后,我们可以使用 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 容器

容器(Container)是镜像的一个运行实例。就像 Java 中类和对象的关系一样,容器是镜像的实例化

Docker 定义了容器的七种状态:

✅ created
✅ restarting
✅ running
✅ removing
✅ paused
✅ exited
✅ dead

这很重要,因为容器并不一定必须处于运行状态。

当我们使用 docker run 命令时,实际上做了两件事:

  1. 创建容器(create)
  2. 启动容器(start)

也就是说,docker run = docker create + docker start

容器之间是相互隔离的,这意味着你可以运行多个相同镜像的容器实例,每个都可以有不同的状态和数据。这是 Docker 实现应用扩展的重要机制之一。

例如,微服务架构中,每个服务都可以打包为一个镜像,然后根据需求动态创建容器来部署服务。

5. 容器生命周期管理

容器有多个状态,我们可以使用 docker 命令来管理它的整个生命周期。

创建和启动容器

我们可以分别创建和启动容器:

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

也可以一步到位:

docker run <image_name>:<tag>

暂停和恢复容器

docker pause <container_id>
docker unpause <container_id>

暂停后容器状态会变成 Paused,使用 docker ps 即可查看。

停止和重启容器

docker stop <container_id>
docker start <container_id>

删除容器

docker container rm <container_id>

⚠️ 注意:只有处于 stoppedcreated 状态的容器才能被删除。

如需了解更多 Docker 命令,可以参考 Docker 官方命令行文档

6. 总结

在本文中,我们学习了 Docker 中两个核心概念:

  • 镜像(Image):是一个静态模板,包含运行应用所需的所有依赖
  • 容器(Container):是镜像的一个运行实例,可以有多个容器实例同时运行

我们还了解了容器的生命周期以及如何使用命令管理容器的状态。

现在你已经掌握了 Docker 的基本概念,接下来可以深入学习 Docker 的网络、卷、Docker Compose 等高级功能,进一步提升你的容器化技能。


原始标题:Difference Between Docker Images and Containers