本篇文章旨在刨析 Docker 的核心要素: 容器 镜像 Dockerfile,而不是简单地背诵一堆命令。通过理解docker核心原理,我们将能够更有效地运用 Docker,避免在操作中迷失方向,并真正掌握这项强大的技术
本文涉及的技术名词: ContainerImageDockerfileDocker命令
在开始探讨 Docker 的细节之前,让我们先确认四个非常重要的要点,以便正确且快速地理解 Docker。(这些分类是我个人的总结)
- 三个基本元素
- 三个基本命令
- 注意命令格式
- 区分 Docker 与周边工具
如果学习Docker只是一味的背诵一堆命令和选项 最终可能无法真正掌握 Docker 的基础知识。
我认为与其只是机械地复制一堆命令,最后迷惑地想着“这是什么...?”,不如花点时间扎实地掌握基本概念,才是快速上手 Docker 的捷径。
三个基本元素
当使用 Docker 构建开发环境时,实际上涉及的元素并不多。在本文中,我们将以下三个元素视为基本要素:
- 容器(Container)
- 镜像(Image)
- Dockerfile
掌握这三个基本元素将帮助我们更简单地理解和使用 Docker,构建出高效且稳定的开发环境。
Container
容器是在主机上创建的一个用于运行特定命令的隔离区域。
在刚开始接触 Docker 时,我们可能会把容器想象成运行在主机上的虚拟操作系统,但实际上,容器只是通过 Linux 中的 Namespace 功能与其他进程隔离开的一个单独进程。Linux Namespace 本身是一项已经存在近 20 年的技术,而 Docker 则是一种通过容器和镜像让这项技术更易于使用的工具。
如下图, 在主机和每个容器中,可能会有类似 Process ID 1
或 /etc/hosts
这样重复的同名文件,但通过 Namespace 技术映射隔离区域,避免了这些文件的冲突。
Docker 允许我们从镜像创建这个 Namespace,使其对不同的操作系统可见,并提供了方便的命令来创建和删除这些 Namespaces。
小提示: 容器仅仅是主机上的一个进程,而不是一个虚拟服务器, 利用Linux命名空间的强大的隔离机制,允许系统资源在不同进程之间独立存在和管理。
容器具有以下几个特点:
- 容器是基于镜像创建的:每个容器都是从一个镜像开始,通过镜像定义了容器内的环境和应用程序。
- 可以使用 Docker CLI 或 API 来创建、启动和停止容器:Docker 提供了简便的命令行工具和 API 来管理容器的生命周期。
- 多个容器彼此独立,互不干扰:每个容器都是独立运行的,它们之间无法相互影响,因此能够独立操作。
- Docker Engine 可以运行在本地机器、虚拟机或云环境中:这使得容器化应用能够在各种环境中部署和运行,无论是在开发、测试,还是生产环境中。
Image
镜像是一个包含了运行容器所需的所有文件和元信息的包。它并不是一个单独的文件,而是由多层信息构成的集合。这些层次的信息包括:
- 基础镜像:定义了容器运行的基本环境,比如操作系统版本。
- 已安装的软件:镜像中包含了应用程序及其所有依赖项。
- 环境变量:配置了容器在运行时所需的环境变量。
- 配置文件:包含了运行应用程序所需的各种配置文件。
- 默认启动命令:指定了容器启动时要执行的命令。
这些层次的信息共同构成了一个完整的镜像,使得容器能够在启动时拥有预期的运行环境。
Dockerfile
Dockerfile 是一个文本文件,它可以在现有的镜像上添加新的层。
假设我们从 Docker Hub 获取了一个基于 Debian 的 Node.js 镜像(node:16
),但发现该镜像缺少 git
命令,并且我们需要部署一个 Vue 单页应用(SPA)。此时,我们可以通过以下 Dockerfile 添加 git
,安装项目依赖并构建应用,同时配置必要的环境变量,生成一个符合需求的自定义镜像。
# 使用官方的 Node.js 镜像作为基础镜像
FROM node:16-buster
# 安装必要的工具和依赖
RUN apt-get update && apt-get install -y git
# 设置工作目录
WORKDIR /usr/src/app
# 复制 package.json 和 package-lock.json 到工作目录
COPY package*.json ./
# 安装项目依赖
RUN npm install
# 复制应用程序代码到工作目录
COPY . .
# 构建 Vue 应用
RUN npm run build
# 安装一个轻量级的 HTTP 服务器来提供应用
RUN npm install -g serve
# 暴露应用运行的端口
EXPOSE 5000
# 使用 serve 提供构建后的应用
CMD ["serve", "-s", "dist", "-l", "5000"]
小提示: 在 Dockerfile 中,应用程序代码通常是从构建 Docker 镜像的上下文目录复制到容器内的工作目录。Dockerfile 中的
COPY . .
指令将当前目录(即运行docker build
命令时所在的目录)下的所有文件复制到容器内的工作目录
这个 Dockerfile 基于 Debian 的 Node.js 镜像,安装了 git
,复制并安装了项目依赖,构建了 Vue 单页应用,然后使用 serve
提供构建后的应用,最终在 5000 端口运行。
三个基本命令
当我们理解了 Docker 的三个基本元素(容器、镜像、Dockerfile)后,可以发现,Docker 的基本命令形式其实也可以归纳为三种类型:
- 启动容器:通过已有的镜像启动并运行一个容器。
- 创建镜像:使用 Dockerfile 或其他方法生成一个新的镜像,满足特定需求。
- 管理容器:对已经运行的容器进行操作,比如停止、重启或者查看状态。
启动一个容器
docker container run
命令用于从镜像运行一个容器, 这个命令会基于指定的镜像启动一个新的容器,并在其中执行指定的命令或应用程序。
其拥有大量参数选项,根据容器的用途,我们可以配置相应的参数来定制容器的行为。归根结底,这个命令的核心功能还是从镜像创建一个容器,这是最基础的操作。
创建镜像
docker image build
命令用于从 Dockerfile 创建一个镜像; 如下图:
上图中我们看到Docker Desktop 还包括 Docker Compose、Kubernetes 等组件。
这意味着,除了 Docker Engine 和 Linux 内核之外,还可以使用 Docker Desktop 轻松管理多容器应用(通过 Docker Compose)以及容器编排(通过 Kubernetes)。这些功能使得 Docker Desktop 成为一个功能强大的工具,适合在 Windows 和 Mac 上进行复杂的开发和部署任务。
管理容器
docker container exec
命令用于向已经运行的容器发送指令。
由于它的目标是一个正在运行的容器,因此必须在执行 docker container run
之后使用。这个命令不能用于操作镜像或 Dockerfile,只能在容器已经启动后进行交互。如下图:
新旧命令对比
使用过Docker命令的同学可能已经注意到, 上面使用的都是docker container run
而非 docker run
命令; 这是因为Docker 命令在 2017 年 1 月发布的 v1.13 版本中经历了一次重大变化,旧的 docker run
命令被替换为新的 docker container run
命令。这是因为之前的命令过于直接,如 docker run
和 docker build
等,使得用户很难区分各个命令的用途。因此,从 v1.13 版本开始,Docker 推荐使用子命令格式,这样可以更清楚地指定每个命令的目标,例如容器、镜像等。
小提示: 这种命令变化旨在提高命令的可读性和可理解性,让用户在使用 Docker 时能够更轻松地掌握各个命令的具体作用和使用场景。
老命令 | 新命令 |
---|---|
docker build | docker image build |
docker run | docker container run |
docker pull | docker image pull |
docker create | docker container create |
docker start | docker container start |
docker images | docker image ls |
docker ps | docker container ls |
Docker Compose
Docker Compose 是一个强大的容器编排工具,通过编写 Yaml 文件可以定义并一次性启动和管理多个容器。使用 Compose,我们可以轻松设置容器之间的网络、共享存储以及依赖关系,从而简化了复杂应用的部署和管理。
Kubernetes
Kubernetes 是一款编排软件,它通过编写 JSON 或 Yaml 文件,方便轻松地运行多个相同的容器来构建集群、监控容器,并在容器出现故障时自动重启容器。Kubernetes 的强大之处在于它能够高效管理和扩展大规模的容器化应用程序,确保系统的稳定性和可用性。无论是在开发环境还是生产环境,Kubernetes 都为容器管理提供了高度自动化和灵活的解决方案。
总结
本篇文章涉及的新名词较多,所以在结尾我来简要总结一下:
基本元素
- 容器:容器是主机上一个隔离的进程。
- 镜像:镜像是由称为层的元信息集合构成的,可以发布在 Docker Hub 等平台上。
- Dockerfile:Dockerfile 是一个用于向镜像添加层的文本文件,可以在 GitHub 等平台上共享。
基本命令
- 启动容器
- 创建镜像
- 操作容器
命令形式
- 最重要的是清楚自己想要实现什么。
- 新命令更加易懂,而旧命令则书写简短。