Docker(刀克)作为目前最成熟、高效的软件部署技术,通过核心概念、关键功能和操作命令的结合,构建了稳固的软件部署基础。
一、 Docker 的核心概念 (Core Concepts)
Docker 的基础建立在容器化技术上,主要围绕以下几个核心概念展开:
- 容器 (Container):
- 容器是为应用程序封装的独立运行环境。
- 每个容器本质上是一个特殊的进程,但由于 Docker 利用了 Linux 内核的原生功能 Namespaces (用于隔离进程的资源视图) 和 Cgroups (用于限制和隔离进程的资源使用),使得容器内部看起来就像一个独立的操作系统。
- 容器之间共用同一个系统内核,这使得它们比虚拟机(每个虚拟机都包含完整的操作系统内核)更轻量、更小,启动速度更快。
- 镜像 (Image):
- 镜像是容器的母板,可以类比为软件安装包或制作糕点的模具。
- 容器是基于镜像创建并运行的。通过一个镜像,可以创建出多个容器。
- 镜像通常包含四个组成部分:仓库地址(Registry,如
docker.io)、命名空间(Namespace,即作者名)、镜像名称,以及标签名(Tag,即版本号,如latest)。
- Docker 仓库 (Registry/Repository):
- 仓库是用于存放和分享镜像的地方。官方仓库是 Docker Hub。
- 一个镜像库(Repository,由注册表、命名空间和镜像名组成)存放的是同一镜像的不同版本。
二、 Docker 的关键功能 (Key Functionalities)
这些功能保障了软件部署的可靠性、一致性和可维护性:
- 运行环境隔离与资源控制:
- Docker 利用 Namespaces 实现了进程资源视图的隔离,容器只能看到自己的进程 ID、网络资源和文件目录,而看不到宿主机的资源。
- 利用 Cgroups 可以为每个容器设定 CPU、内存、网络带宽等资源的使用上限,确保容器间的资源消耗互不影响。
- 数据持久化 (Data Persistence):
- 由于删除容器时,容器内所有数据会同时被删除,因此 Docker 提供了挂载卷(Volume)的功能。
- 挂载卷将容器内的目录与宿主机的目录进行绑定,从而保证了即使容器被删除,数据也不会丢失。挂载方式包括绑定挂载(指定宿主机目录)和命名卷挂载(Docker 自动创建存储空间)。
- 网络管理与互联互通:
- 容器的内部网络默认与宿主机隔离。
- 端口映射(Port Mapping,使用
-p参数)可以将宿主机的端口转发到容器内的端口,从而使外部能够访问容器内运行的服务。 - Docker 提供了多种网络模式:
- Bridge 模式(默认): 容器被分配内部 IP 地址,同一子网内的容器可以互相通信。
- 自定义子网: 允许在自定义子网内的容器之间通过容器名互相访问,无需使用内部 IP 地址,这得益于 Docker 内部的 DNS 机制。
- Host 模式: 容器直接共享宿主机的网络,使用宿主机的 IP 地址,且无需端口映射。
- 轻量级容器编排 (Docker Compose):
- 对于由前端、后端、数据库等多部分组成的复杂应用,最佳实践是将每个模块打包成独立的容器。
- Docker Compose 是一种轻量级的容器编排技术,通过 YAML 文件来管理多个容器的创建和协同工作,极大地简化了多容器部署的成本和配置。Compose 会为同一文件定义的所有容器自动创建一个子网,并让它们自动加入。
三、 构建部署基础的操作命令 (Operational Commands)
部署流程依赖一系列关键的 Docker 命令,其中
docker run 是最核心的命令,因为它集成了容器的创建、运行及配置。| 部署阶段 | 核心操作命令 | 描述/作用 | 关键参数 |
|---|---|---|---|
| 镜像准备 | docker pull [image] | 从 Docker 仓库下载镜像。如果本地不存在,docker run 会自动执行此操作。 | - |
docker build -t [name] . | 使用 Dockerfile(制作镜像的图纸)构建镜像。 | -t 用于给镜像命名和添加标签。 | |
| 容器运行 | docker run [image] | 从镜像创建并运行容器。 | -d (Detached mode):分离模式,让容器在后台执行。 |
-p [host:container]:端口映射,用于外部访问容器服务。 | |||
-v [host/vol:container]:挂载卷,用于数据持久化保存。 | |||
-e [ENV_VAR]:传递环境变量,常用于设置数据库的账号密码等。 | |||
--name [name]:为容器设置自定义名称,便于记忆和管理。 | |||
--restart always/unless-stopped:配置容器的重启策略。 | |||
| 多容器管理 | docker compose up -d | 根据 docker-compose.yml 文件定义,启动所有容器(-d 后台运行)。 | - |
docker compose down | 停止并删除 Compose 文件中定义的容器。 | - | |
| 故障排查 | docker ps -a | 查看所有容器的状态,包括正在运行的和已停止的。 | - |
docker logs -f [container] | 滚动查看容器的日志输出。 | -f (follow) 表示滚动查看。 | |
docker exec -it [container] bash | 进入正在运行的容器内部,获取交互式命令行环境进行调试。 | -it 允许交互式地进入容器。 |
Docker 通过将应用程序及其所有依赖项封装到可移植的镜像中,并通过容器提供一致、隔离的运行环境,再辅以
docker run 及其参数(如 -p 和 -v)实现网络访问和数据持久化,从而提供了一个标准化、高效的软件部署方案。部署基础的比喻: Docker 及其概念构建的软件部署基础,就像是一套标准化的“预制房屋”系统。镜像是房屋的蓝图和材料包,确保无论在哪里建造,房屋结构都一致。容器是根据蓝图快速建造和运行的独立房屋,它们共享土地(宿主机内核)但彼此隔离(Namespaces/Cgroups)。通过-p端口映射,你为房屋设置了地址和门口(端口),使访客可以进入。通过-v挂载卷,你确保了房屋内的珍贵物品(数据)存放在坚固的地基上,即使房屋重建,物品也不会丢失。
Docker 是一种容器化技术,通常是基于 Linux 的。在 Windows 和 Mac 电脑上,Docker 的运行依赖于虚拟化的 Linux 子系统,因此 Linux 系统的主机是最好的实战环境。
以下是针对不同操作系统的 Docker 安装步骤:
在 Linux 系统上安装 Docker
在 Linux 系统上安装 Docker 时,可以访问
get.docker.com 这个地址,并执行其中的安装步骤。具体来说,您只需要执行该安装步骤中的第一步和第四步的命令:
- 复制并粘贴执行第一步的命令。
- 复制并粘贴执行第四步的命令。
注意: 如果您的 Linux 用户不是 root 用户,例如是 Ubuntu 用户,您需要在所有 Docker 命令前面加上
sudo(代表 super user do,即使用管理员权限执行命令)。等待大约十几秒即可完成安装。在 Windows 系统上安装 Docker
在 Windows 系统上安装 Docker Desktop,需要先启用一些 Windows 功能并安装 WSL(适用于 Linux 的 Windows 子系统)。
步骤:
- 在任务栏搜索功能中,点击“启用或关闭 Windows 功能”。
- 勾选 “Virtual Machine Platform”(有的电脑可能翻译为“虚拟机平台”)。
- 勾选 “适用于 Linux 的 Windows 子系统” (即 WSL) 的功能。
- 按照提示重新启动电脑。
- 电脑重启后,在搜索栏中搜索 cmd,右键以管理员身份打开命令提示符。
- 输入第一个命令
wsl --set-default-version 2,将 WSL 的默认版本设置为 2。 - 执行第二个命令安装或更新 WSL:
wsl --update。如果机器处于国内网络环境,建议在后面加上--web-download以减少因网络问题导致的下载失败。 - 访问指定地址下载 Docker Desktop,根据自己的 CPU 架构选择对应的安装包(Windows 通常是 amd64 架构)。
- 安装过程通常非常简单,一路点击“下一步”即可。如果需要指定安装目录,可以使用命令行方式添加参数
start /w "" "Docker Desktop Installer.exe" install --installation-dir=D:\Docker
验证和使用:
- 您需要在 Windows 上保持 Docker Desktop 软件一直开启才能使用 Docker。
- 打开 Windows 终端,输入
docker --version,如果能打印出版本号,则表示安装成功。
在 Mac 系统上安装 Docker
Mac 电脑上的安装过程最为简单:
- 根据自己的芯片(CPU 架构)下载对应的安装包。
- 然后进行安装即可。
安装后的网络配置(解决国内网络问题)
如果遇到网络问题影响镜像下载,可以在 Docker Desktop 中配置镜像站:
- 打开 Docker Desktop,找到设置(Settings)中的
Docker Engine。 - 将配置文件的
registry-mirrors部分复制,并将其粘贴到设置中,然后点击右下角的 Apply and restart。配置好镜像站后,使用docker pull命令拉取镜像就不会报错了。
Docker pull命令
Docker pull 命令主要用于从 Docker 仓库(或称注册表 Registry)中下载 Docker 镜像。
以下是关于
docker pull 命令的详细解释:核心功能与概念
- 下载镜像:
docker pull命令的作用是从 Docker 仓库(如官方的 Docker Hub)下载所需的镜像。镜像是容器的“母板”,可以类比为软件安装包,而容器是使用该镜像安装出来的软件。 - 镜像仓库: Docker 仓库(Registry)是用于存放和分享镜像的地方。
镜像命名的结构
在使用
docker pull 命令时,您需要指定要下载的镜像名称。一个完整的 Docker 镜像名称通常由四个部分组成,例如:[Registry 地址]/[命名空间]/[镜像名称]:[标签名]。- Registry 地址(注册表): 指向 Docker 仓库的地址。如果从 Docker 官方仓库 Docker Hub 下载,
hub.docker.com - 命名空间(Namespace): 由于 Docker Hub 是公共仓库,要求上传镜像时在镜像名前加上作者的名字,即命名空间。如果镜像是 Docker 官方仓库维护的(使用
library命名空间),这部分也可以省略不写。 - 镜像名称: 镜像是软件的名称,例如
nginx。 - 标签名(Tag): 通常是镜像的版本号。您可以指定下载特定的版本,例如
:1.28.0。
简化示例:
在简化命令中,例如
docker pull nginx,它表示从 Docker 官方仓库的官方命名空间里下载最新版本的 nginx 镜像。如果不指定标签名,则默认获取最新版本 (:latest)。与 Docker Run 的关系
虽然您可以使用
docker pull 命令提前下载镜像,但执行 docker run 命令时,第一步也可以省略。如果 Docker 发现本地不存在所需的镜像,它会先自动拉取(即执行了 pull 操作)一份,然后再创建并运行容器。实用选项和配置
- CPU 架构: 默认情况下,
docker pull命令会自动选择最适合当前宿主机 CPU 架构的镜像版本。如果需要拉取特定 CPU 架构的镜像(例如在树莓派等迷你主机上运行),可以使用--platform选项。 - 网络配置: 在中国国内网络环境下执行
docker pull命令时,可能会因网络问题报错。这可以通过在 Docker Desktop 或 Linux 配置文件中设置**镜像站(registry-mirrors)**来解决,配置好后,再次使用docker pull命令就不会报错了。
Linux配置镜像站
sudo vi /etc/docker/daemon.json
输入下列内容,最后按ESC,输入 :wq! 保存退出。
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://docker.1panel.live",
"https://hub.rat.dev"
]
}
重启docker
sudo service docker restart
简而言之,
docker pull 命令就像您去图书馆的目录(Docker Hub)里,找到您想要的一本特定版本的书(镜像),然后下载到您的本地书架(宿主机)上。Docker 镜像(Image)是 Docker 技术中最核心的基础概念之一。
相关的操作命令
在命令行中,
docker images 也可以指代一个命令,它的作用是列出所有已下载到本地的 Docker 镜像。同时,您可以使用以下命令管理镜像:
docker pull:从仓库下载镜像。docker rmi:用于删除镜像(其中rm代表 remove,i是 images 的缩写)。
docker pull --platform 命令中的 --platform 选项用于在下载 Docker 镜像时,指定要拉取(下载)的特定 CPU 架构的镜像。以下是关于该命令的详细说明:
- 默认行为: 在默认情况下,
docker pull命令会自动选择最适合当前宿主机 CPU 架构的镜像版本进行下载。 - 指定架构: 尽管大多数情况下我们不需要关注镜像的 CPU 架构,但在某些特殊情况下,例如在使用树莓派(Raspberry Pi)这类微型主机运行 Docker 时,就需要使用
--platform。- 树莓派通常是低功耗小型主机,其 CPU 架构一般是
arm64。 - 如果宿主机是
arm64架构,而您需要拉取一个适用于该架构的镜像,但该镜像通常默认是为amd64架构构建的,此时就需要显式地使用--platform选项来指定。
- 树莓派通常是低功耗小型主机,其 CPU 架构一般是
- 兼容性考虑: 不同的 CPU 架构需要不同的镜像版本。例如,某些应用(如
reagflow)可能只提供amd64架构的镜像,这意味着它不能在树莓派上运行。 - Mac 电脑的兼容性: 值得注意的是,Mac 电脑虽然也是
arm64架构,但 Docker Desktop 有一个优势,它可以自动使用 QEMU 来模拟 x86_64 指令集,从而可以兼容部分amd64镜像。不过,这样做可能会带来一些兼容性问题或额外的开销。
简而言之,
--platform 选项赋予用户下载非默认或特定 CPU 架构镜像的能力,以确保其软件能够在不同的硬件平台上正确运行。docker run
docker run 命令是 Docker 中最重要和最核心的命令,它的主要作用是从镜像创建并运行容器。这个命令的执行过程,就好比使用“模具”(镜像)来制作一个“糕点”(容器)。每次执行
docker run 命令,都会创建一个全新的容器。一、 docker run 命令的核心功能
- 创建与运行容器: 它是将静态的镜像转换为动态运行的容器实例的关键步骤。
- 镜像拉取(可选): 如果本地宿主机上不存在指定的镜像,
docker run命令会自动先执行拉取(pull)操作,然后再创建并运行容器。因此,使用docker run命令可以省略事先执行docker pull的步骤。
二、 docker run 的常用参数和作用
docker run 命令通常会配合一系列参数使用,以配置容器的运行环境、网络、数据持久化和管理方式。| 参数 | 英文全称/含义 | 作用描述 | 示例 |
|---|---|---|---|
-d | Detached mode(分离模式) | 让容器在后台执行。运行后,控制台只打印一个容器 ID,后续容器的日志不会打印在控制台,也不会影响控制台的使用。这是一种更常见的启动方式。 | docker run -d nginx |
-p | Port mapping(端口映射) | 端口映射,用于将宿主机的端口与容器内部的端口进行绑定或转发。这是因为容器的网络与宿主机是隔离的,默认无法直接访问容器内部网络。格式是:宿主机端口:容器内端口。 | docker run -p 80:80 nginx |
-v | Volume(挂载卷) | 文件目录绑定,用于将宿主机的目录或创建的命名卷与容器内部的文件目录进行绑定。主要作用是数据持久化保存,确保删除容器时数据不会丢失。 | docker run -v /host/path:/container/path nginx |
-e | Environment(环境变量) | 传递环境变量给容器。常用于配置数据库的账号名、密码等敏感信息,使得容器在启动时预设这些配置。 | docker run -e MONGO_INITDB_ROOT_USERNAME=mongo |
--name | Name(自定义名称) | 为容器起一个自定义的名称,方便记忆和管理。该名称在整个宿主机上必须是唯一的,不能重复。容器名称的功能与容器 ID 等价。 | docker run --name my_web_server nginx |
-it | Interactive TTY | 允许控制台进入容器内部进行交互式操作,常用于临时调试。i 代表交互,t 代表分配一个伪终端(TTY)。 | docker run -it alpine sh |
--rm | Remove | 当容器停止运行时,自动将其从宿主机上删除。通常与 -it 连在一起用于临时调试。 | docker run --rm -it alpine sh |
--restart | Restart policy(重启策略) | 用于配置容器在停止时的重启策略。常用的选项包括:always(只要停止就立即重启)或 unless-stopped(除手动停止外,因意外原因停止都会重启)。 | docker run --restart unless-stopped nginx |
三、 docker run 的重要应用场景
- 端口映射 (
-p): 容器网络与宿主机网络隔离,要从宿主机或外部访问容器内运行的服务(如 Nginx 网页),必须通过端口映射将宿主机的端口转发到容器内的端口。 - 数据持久化 (
-v): 容器删除时,容器内的数据也会被删除。使用挂载卷(-v)可以将容器内的数据目录映射到宿主机上,实现数据的持久化保存。挂载方式包括绑定挂载(指定宿主机目录)和命名卷挂载(Docker 自动创建存储空间)。 - 传递配置 (
-e): 启动数据库等应用时,通过-e参数传递环境变量,可以在启动时为应用设置必要的配置,如账户名和密码。
四、 与其他命令的区别
docker runvsdocker start:docker run:每次执行都会创建一个全新的容器。docker start:用于重新启动一个已经创建但已停止的容器。启动时,之前通过docker run配置的端口映射、挂载卷和环境变量等参数都会被保留和沿用,无需重新编写。
docker runvsdocker create:docker run:创建容器并立即启动。docker create:只创建容器,但不立即启动。如果想启动,后续还需要执行docker start命令。
创建 Docker 挂载卷(Volume)的目的是实现数据的持久化保存,因为容器被删除时,容器内部的所有数据也会被同时删除。挂载卷将容器内部的目录与宿主机的文件目录紧密地联系在一起。
根据来源,创建和使用 Docker 挂载卷主要有两种方式:绑定挂载(Bind Mounts)*和*命名卷挂载(Named Volume Mounts)。
方式一:使用 docker run -v 进行绑定挂载(Bind Mounts)
绑定挂载允许您直接指定宿主机上的特定目录与容器内的目录进行绑定。这种方式不需要提前创建挂载卷,而是在运行容器时通过
-v 参数直接指定。操作命令: 使用
docker run 命令,配合 -v 参数,格式为:宿主机目录:容器内目录,。示例: 如果您想将宿主机上的
/host/path/ 目录与容器内的 /container/path/ 目录绑定:docker run -d -v /host/path:/container/path <镜像名称>
宿主机目录会覆盖掉容器内原有对应目录的内容。- 在宿主机上对该目录的修改,会同步影响容器内的文件;反之,在容器内对该目录的修改,也会影响宿主机的文件。
限制: 绑定挂载的一个限制是,如果宿主机的目录是空的,它会覆盖掉容器内对应的目录,导致容器内的目录也是空的,可能引发服务访问错误(例如 Nginx 出现 403 错误)。绑定挂载也不具备自动同步容器文件到宿主机的初始化功能。
方式二:使用 docker volume create 进行命名卷挂载(Named Volume Mounts)
命名卷挂载是 Docker 推荐的持久化数据方式,它允许 Docker 自动在宿主机上创建存储空间,并给这个存储空间起一个名称,简化了后续容器的配置。
1. 创建命名卷
使用
docker volume create 命令来创建一个新的挂载卷,并为其指定一个名称:操作命令:
docker volume create <卷的名称>
示例:
docker volume create ngxhtml
2. 使用命名卷运行容器
创建卷后,在运行容器时,直接使用卷的名称进行挂载,而不是使用宿主机的具体目录:
操作命令: 使用
docker run -v 参数,格式为:卷的名称:容器内目录。示例:
docker run -d -v ngxhtml:/usr/share/nginx/html nginx
3. 命名卷的特殊功能
命名卷有一个特别的功能:在第一次使用的时候,Docker 会将容器内对应文件目录的内容同步到命名卷里面,进行一个初始化。这解决了绑定挂载中宿主机目录为空可能导致的问题,。
4. 查看命名卷信息
您可以使用
docker volume inspect 命令来查看命名卷在宿主机上的真实目录位置(通常在 /var/lib/docker/volumes/ 目录下)。操作命令:
docker volume inspect <卷的名称>
5. 管理命名卷的其他命令
- 列出所有已创建的卷:
docker volume list - 删除指定的卷:
docker volume remove <卷的名称> - 删除所有没有被任何容器使用的卷:
docker volume prune
调试 Docker 容器
要调试 Docker 容器,您可以使用以下几种关键的 Docker 命令和技巧,这些方法允许您进入正在运行的容器内部环境、查看日志或检查容器配置:
1. 进入容器内部进行交互式调试
最直接的调试方法是使用
docker exec 命令进入容器内部,获得一个交互式的命令行环境,这就像容器内部是一个独立的操作系统:- 命令结构:
docker exec -it [容器 ID 或名称] bashdocker exec: 用于在容器内部执行 Linux 命令。-it: 允许控制台进入容器内部进行交互式操作,i代表交互,t代表分配一个伪终端(TTY)。bash或sh: 是要在容器内执行的 Shell 命令。bash提供了更完整的命令行环境,如果容器是极简的 Linux 发行版(如 Alpine),可能需要使用sh。
调试流程:
- 进入容器内部后,您可以执行各种 Linux 命令,例如查看文件系统、管理容器内的进程,或者进行更深入的调试。
- 在容器内部,您可以看到容器只显示自己的进程 ID、网络资源和文件目录,而看不到宿主机的资源,因为 Docker 利用了 Namespaces 实现了资源视图的隔离。
注意:
- 为了最大限度地压缩镜像大小,容器内部通常是一个极简的操作系统,很多系统工具(比如
vi命令或ip addr命令)可能是缺失的。 - 如果缺少常用工具,您可能需要先在容器内安装这些工具,例如:如果是 Debian 镜像,需要先执行
apt update,再执行apt install vim等命令来安装所需的软件。
2. 临时调试容器并自动清理
如果您只是想临时进入容器进行一次性调试,并希望容器停止后自动删除,可以使用
docker run 配合以下参数:- 命令结构:
docker run --rm -it [镜像名称] sh--rm: 指的是当容器停止时,自动将其从宿主机上删除。-it: 用于提供交互式终端。
使用这套命令,当您用
exit 命令退出容器后,该容器会立即被从宿主机上删除,非常适合临时调试。3. 查看容器日志
如果容器没有在前台运行(使用了
-d 分离模式启动),您可以通过查看日志来排查问题:- 查看日志:
docker logs [容器 ID 或名称] - 滚动查看日志: 在
logs命令后面加上-f(follow),可以实时滚动查看容器的日志输出,方便观察程序运行的动态情况。
4. 检查容器状态和配置信息
有时调试需要检查容器的运行状态、端口映射、挂载卷等配置:
- 查看正在运行的容器:
docker ps(Process Status 的缩写)。 - 查看所有容器(包括已停止的):
docker ps -a。 - 查看容器的详细配置:
docker inspect [容器 ID 或名称]。- 这个命令会打印出非常详细和复杂的 JSON 格式信息,但其中包含了容器启动时设置的全部参数,例如是否做了端口映射(
-p)、是否做了挂载卷(-v)等。
- 这个命令会打印出非常详细和复杂的 JSON 格式信息,但其中包含了容器启动时设置的全部参数,例如是否做了端口映射(
Dockerfile制作镜像
在 Docker 容器内部安装工具的步骤如下:
- 进入容器的交互式环境: 您需要使用
docker exec命令进入正在运行的容器内部,以获取一个交互式的命令行环境。- 命令格式:
docker exec -it [容器 ID 或名称] bash。如果容器是极简系统,可能需要使用sh。
- 命令格式:
- 确认容器的 Linux 发行版: 进入容器后,首先需要执行命令来查看容器内部的 Linux 是什么发行版。这是因为不同的 Linux 发行版(如 Debian、Alpine 等)使用不同的包管理器(如
apt或apk)来安装软件。 - 安装所需的工具: 一旦确认了发行版,就可以使用对应的包管理器来安装工具。
- 例如,如果是 Debian 发行版:
- 首先,需要执行
apt update命令来更新包管理器的索引。 - 然后,执行
apt install [工具名称]来安装所需的工具,例如安装vi编辑器,可以使用apt install vim。
- 首先,需要执行
- 例如,如果是 Debian 发行版:
背景说明: Docker 容器为了尽量压缩镜像的大小,其内部通常是一个极简的操作系统,这意味着很多系统工具(比如
vi 命令)可能是缺失的。因此,在进行容器内部调试时,如果发现缺少常用工具,就需要像上面这样手动安装。例如,在调试 Nginx 容器时,如果尝试使用
vi 命令修改文件,可能会提示找不到 vi 命令,这时就需要确认容器的发行版并安装该工具。使用 Dockerfile 制作(或称构建)一个 Docker 镜像,需要以下几个核心步骤:准备 Dockerfile 文件、定义基础镜像、写入构建指令、以及执行
docker build 命令。一、 准备 Dockerfile 文件
- 创建文件: 首先,您需要创建一个名为
Dockerfile的文件。需要注意的是,这个文件名中的D必须大写,且文件没有任何后缀名。 - 作用: Dockerfile 就像是制作镜像的“图纸”。它是一个文本文件,里面详细地列出了镜像应该如何制作。
二、 Dockerfile 的核心指令
Dockerfile 中的每一行指令都定义了镜像构建过程中的一个步骤。
FROM(指定基础镜像):- 作用: 所有的 Dockerfile 都必须以
FROM指令开头,用于指定基础镜像。这意味着您的新镜像将基于哪个已存在的镜像来构建。 - 示例: 如果您需要 Python 环境,您可以在 Docker Hub 上搜索 Python 镜像,并将其作为基础镜像,例如:
FROM python:3.13-slim。
- 作用: 所有的 Dockerfile 都必须以
WORKDIR(设置工作目录):- 作用: 类似于 Linux 命令
cd,它用于切换到镜像内部的一个目录,并将该目录设置为后续命令的工作目录。 - 示例:
WORKDIR /app。后续的所有命令都将在/app目录下执行。
- 作用: 类似于 Linux 命令
COPY(复制文件):- 作用: 用于将宿主机上的文件(即您的代码或其他资源文件)拷贝到镜像内的指定工作目录。
- 示例:
COPY . .。第一个.代表您的电脑的当前目录(即代码所在的目录);第二个.代表镜像内的当前工作目录(即前面设置的/app目录)。
RUN(执行构建命令):- 作用: 用于在镜像构建过程中执行一些需要在镜像内部运行的命令,例如安装依赖或配置环境。
- 示例: 如果您的项目依赖于
requirements.txt文件中的 Python 包,可以使用RUN来安装这些依赖:RUN pip install -r requirements.txt。
EXPOSE(声明服务端口):- 作用: 用于声明镜像提供的服务端口是哪一个。
- 示例: 如果您的 Fast API 程序运行在 8000 端口,可以声明:
EXPOSE 8000。 - 注意:
EXPOSE只是一个声明,给其他使用镜像的人一个提示,它并不具有强制性。实际使用时,容器是否能够通过该端口访问,仍取决于docker run命令中的-p端口映射参数。
CMD(容器默认启动命令):- 作用: 这是容器运行时的默认启动命令。每当容器启动时,容器内部会自动执行此命令,以确保容器内的程序(例如 Python 程序)能够运行起来。
- 限制: 一个 Dockerfile 文件中只能写入一个
CMD命令。 - 格式: 建议将命令写成数组的形式,中间最好不要使用空格。
- 示例: 如果启动项目的命令是
python main.py,则写为:CMD ["python", "main.py"]。
三、 构建镜像的操作命令
Dockerfile 准备好之后,您就可以在 Dockerfile 所在的目录下执行构建命令:
- 命令结构:
docker build -t [镜像名称] .docker build: 执行镜像构建操作。-t: 用于给镜像起一个名字(tag)。[镜像名称]: 您可以指定名称,例如docker_test。名称后面可以接冒号:来输入一个版本号,也可以省略不写。.(点): 指的是在当前文件夹中构建镜像。
示例:
docker build -t docker_test:v1.0 .
执行该命令后,镜像即构建完成。您可以使用
docker images 命令来查看本地是否成功生成了该镜像。随后,您就可以使用 docker run 命令,基于这个新构建的镜像来创建并运行容器。将镜像推送到 Docker Hub 上是一个三步走的过程:登录您的 Docker Hub 账户、重新标记(Tag)您的本地镜像以包含您的用户名(命名空间)、最后执行推送命令。
以下是具体的步骤:
步骤一:登录 Docker Hub
在推送镜像之前,您必须先在命令行中登录您的 Docker Hub 账户。
-
准备账号: 如果您还没有 Docker Hub 账号,需要先访问 Docker Hub 首页进行注册(signup)。
-
执行登录命令: 在命令行终端中输入以下命令:
docker login -
验证: 按照提示进行验证(来源提到可能需要输入一个英文验证码并在特定网站上完成操作),直到命令行显示
login succeed,表示登录成功。
步骤二:重新标记镜像(Re-tag)
因为 Docker Hub 是一个公共仓库,要求用户在上传镜像时,必须在镜像名称前加上作者的名字,即命名空间(Namespace)。您的 Docker Hub 用户名就是您的命名空间。
您需要使用新的名称(包含您的用户名)来重新标记您的本地镜像:
-
重新构建或标记: 推送镜像时,必须在镜像名称前面带上您自己的用户名。
-
标记格式: 完整的镜像名称格式应该是:
[您的 Docker Hub 用户名]/[镜像名称]:[版本号]。-
示例: 假设您的用户名为
techshrimp,镜像名为docker_test,您可以执行命令重新标记(来源示例中直接在构建时加上了用户名):# 假设原镜像名为 docker_test:v1.0,现在重新标记 docker tag docker_test:v1.0 [您的用户名]/docker_test:v1.0 -
然后使用包含您用户名的名称作为推送的依据。
-
步骤三:执行推送命令
标记完成后,使用
docker push 命令将镜像推送到 Docker Hub。-
推送命令:
docker push [您的用户名]/[镜像名称]:[版本号]- 注意: 这里的镜像名称必须带着您自己的用户名。
-
推送结果: 推送成功后,该镜像即存储在 Docker Hub 上,其地址为:
[仓库地址]/[您的用户名]/[镜像名称]。其他用户可以使用docker pull命令,通过您的命名空间和镜像名称来下载和使用您推送的镜像。
Docker 网络
Docker 网络是容器化技术中非常重要的一部分,它主要用于管理容器之间的通信以及容器与宿主机(Host)之间的通信。Docker 提供了多种网络模式来满足不同的部署需求。
以下是关于 Docker 网络的介绍,主要包括其默认模式、自定义子网、Host 模式和 None 模式:
1. 默认网络模式:Bridge(桥接模式)
- 默认连接: Docker 网络的默认模式是 Bridge(桥接模式)。
- 连接方式: 所有容器默认都连接到这个网络。
- IP 地址: 在 Bridge 模式下,每个容器都会被分配一个内部 IP 地址,通常以
172.17开头。 - 通信能力: 在这个内部网络中,容器可以通过内部 IP 地址互相访问。
- 网络隔离: 容器网络与宿主机(Host)的网络是隔离的。这意味着默认情况下,您不能直接从宿主机访问到容器的内部网络服务。
要允许从宿主机或外部访问容器内部的服务,必须使用
docker run 命令中的 -p 参数(端口映射),将宿主机的端口转发到容器内的端口。2. 自定义子网(Bridge 模式的一种)
您可以主动创建自定义子网,这也是 Bridge 模式的一种。
- 创建命令: 使用
docker network create命令可以创建出子网。 - 通信能力:
- 同子网通信: 同一子网内的容器可以互相通信。
- 跨子网隔离: 跨子网的容器则不能互相通信。
- 使用容器名称互相访问: 创建子网还有一个重要的好处是,同一子网内的容器可以使用容器的名称互相访问,而不必使用内部 IP 地址。
- Docker 借助内部的 DNS 机制,可以将容器名称转换为 IP 地址,实现基于名称的互相访问。
- 例如,您可以在启动一个依赖服务的容器(如
mongoexpress)时,直接传递另一个容器(如mongodb)的名称作为其连接目标,而不需要知道它的内部 IP 地址。
3. Host 模式
Host 模式是一种不同的网络配置,它允许 Docker 容器直接共享宿主机的网络。
- 网络共享: 容器直接使用宿主机的 IP 地址。
- 无需端口映射: 在 Host 模式下,无需使用
-p参数进行端口映射。容器内部运行的服务会直接运行在宿主机的端口上。 - 访问方式: 通过宿主机的 IP 和端口就可以直接访问到容器内的服务。
- 应用场景: Host 模式可以解决一些棘手的网络问题。
使用 Host 模式启动容器,需要添加启动参数
--network host。例如,启动 Nginx 容器:docker run --network host nginx
4. None 模式
None 模式指的是不联接网络。在这种模式下,容器将没有网络连接。
5. 网络管理命令
- 列出所有 Docker 网络:
docker network list,该命令会展示出默认的 Bridge 模式、Host 模式和 None 模式。这些默认网络是不能删除的。 - 删除自定义子网:
docker network remove [子网名称]可以删除您自定义创建的子网。
Docker Compose
Docker Compose 是一种轻量级容器编排技术,旨在用于管理多个容器应用,尤其适用于个人使用和单机运行的场景。
以下是关于 Docker Compose 的详细介绍:
核心目的和作用
- 解决多容器管理问题: 当一个完整的应用程序由多个部分组成时(例如,前端、后端、数据库等),最佳实践是将每个模块都打包成一个独立的容器。然而,管理多个容器(多次执行
docker run命令、手动配置网络等)会增加使用成本并容易出错。 - 简化部署流程: Docker Compose 通过使用 YAML(yml)文件来管理这些复杂的应用。这个文件列出了所有容器的创建方式以及它们如何协同工作。
- 批量执行命令: 您可以简单地将 Docker Compose 文件理解为一个或多个
docker命令行按照特定格式排列在一个文件里。
Docker Compose 的工作原理
Docker Compose 使用一个 YAML 文件来定义应用程序的服务(Service)配置,包括镜像名称、端口映射、挂载卷、环境变量等。
与
docker run 命令的对应关系:Docker Compose 文件中的元素与传统的
docker run 命令行参数有着工整的对应关系:docker run 命令行参数(左侧) | Docker Compose YAML 元素(右侧) | 含义 |
|---|---|---|
--name(容器名) | service 名称 | 对应一个容器服务。 |
image(镜像名) | image | 指定用于构建容器的镜像。 |
-e(环境变量) | environments | 用于传递环境变量。 |
-v(挂载卷) | volume | 用于数据持久化和文件目录绑定。 |
-p(端口映射) | ports | 用于将宿主机端口映射到容器端口。 |
Docker Compose 的优势和特点
- 自动创建子网: 相比于手动使用
docker network create创建子网并将容器加入其中,Docker Compose 会为每一个 Compose 文件自动创建一个子网。 - 容器间的名称访问: 在同一个 Compose 文件中定义的所有容器都会自动加入到这个子网中。这意味着这些容器可以使用彼此的容器名称互相访问,而无需知道内部 IP 地址。
- 启动顺序控制(
depends_on): Docker Compose 允许您自定义容器的启动顺序。例如,您可以在mongoexpress服务下面添加depends_on指令,使其依赖于数据库服务,程序就会先启动数据库容器,再启动mongoexpress容器。 - 易于使用和生成: 在 AI 时代,您甚至不需要自己手动编写 Compose 文件,只需将您想要执行的
docker命令告诉 AI,让它生成一个等价的 Docker Compose 文件即可。
相关的操作命令
在使用 Docker Compose 文件时,常用的命令包括:
- 启动容器:
docker compose up可以启动文件中定义的所有容器。- 通常会配合
-d参数(分离模式)让容器在后台运行。 - 重复执行
compose up命令并不会启动新的容器。
- 通常会配合
- 停止并删除容器:
docker compose down会停止并删除 Compose 文件中定义的所有容器。 - 仅停止容器:
docker compose stop只停止容器,但不删除它们。 - 重新启动已停止的容器:
docker compose start可以重新启动被stop命令停止的容器。 - 指定非标准文件名: Docker Compose 默认识别当前目录下的
docker-compose文件。如果文件使用了非标准名称,可以使用-f参数来指定文件名或路径。
适用性
Docker Compose 是一种轻量级的容器编排技术,适合个人使用和单机运行。对于企业级的服务器集群和大规模的容器编排需求,则需要使用更复杂的 Kubernetes 等软件。
总结类比:
如果说单独的 Docker 命令行(如
docker run)是您在做饭时手动操作每个食材(容器),那么 Docker Compose 就像是一份详尽的菜谱(YAML 文件),您只需交给它,它就能自动协调所有食材(容器),确保它们按照正确的步骤和顺序被准备好,最终形成一道完整的菜肴(应用)。创建一个 Docker Compose 文件主要是通过编写一个 YAML(yml)文件来实现的,这个文件定义了应用程序中所有容器服务的配置以及它们之间的协作方式。
1. Docker Compose 文件的核心结构
Docker Compose 文件本质上是一个或多个
docker 命令行按照特定格式排列在一个文件里。它使用 services 顶层元素来定义应用程序中的每个容器服务。文件格式(YAML)示例:
version: '3.8'
services:
# 服务1:对应一个容器
mongodb:
image: mongo:latest
environment:
# 对应 docker run -e 参数
MONGO_INITDB_ROOT_USERNAME: user
MONGO_INITDB_ROOT_PASSWORD: password
volumes:
# 对应 docker run -v 参数
- mongo-data:/data/db
# 服务2:对应另一个容器
mongoexpress:
image: mongo-express:latest
ports:
# 对应 docker run -p 参数
- "8081:8081"
environment:
# 传递环境变量配置连接信息
ME_CONFIG_MONGODB_SERVER: mongodb # 可以使用容器名称互相访问
ME_CONFIG_MONGODB_ADMINUSERNAME: user
ME_CONFIG_MONGODB_ADMINPASSWORD: password
depends_on:
# 自定义启动顺序
- mongodb
# 定义挂载卷
volumes:
mongo-data:
2. 将 docker run 参数转化为 Compose 元素
在创建 Docker Compose 文件时,你需要将原本用于启动单个容器的
docker run 命令参数,转换为 YAML 文件中的对应元素:docker run 命令行参数 | Docker Compose YAML 元素 | 作用 |
|---|---|---|
容器名称 (--name) | Service 名称 (如 mongodb) | 定义容器的名称和标识。 |
镜像名 (image) | image | 指定用于创建容器的镜像。 |
环境变量 (-e) | environment | 用于传递环境变量,如数据库账号密码。 |
挂载卷 (-v) | volumes | 用于数据持久化和目录绑定。 |
端口映射 (-p) | ports | 用于将宿主机端口映射到容器端口。 |
3. 创建 Compose 文件的步骤
- 确定文件名: 默认情况下,Docker Compose 会识别当前目录下的
docker-compose.yml文件。 - 定义服务(Services): 在
services元素下,为应用程序的每个独立模块(如数据库、前端、后端)定义一个服务名称。 - 配置服务细节:
- 在每个服务下,通过
image指定使用的镜像。 - 通过
ports定义端口映射(注意格式为列表)。 - 通过
environment定义环境变量。 - 通过
volumes定义挂载卷。
- 在每个服务下,通过
- 配置依赖和网络(可选):
- 启动顺序: 使用
depends_on指令可以自定义容器的启动顺序,例如让一个前端服务等待数据库服务启动完毕后再启动。 - 网络: 同一 Compose 文件中定义的所有容器都会自动加入 Docker Compose 为该文件创建的自动子网中,它们可以使用彼此的容器名称互相访问,无需手动配置网络。
- 启动顺序: 使用
4. 优势:自动管理子网
手动运行多个
docker run 命令时,你需要使用 docker network create 创建子网,并使用 --network 参数将容器加入。而使用 Docker Compose 时,它会为每一个 Compose 文件都自动创建一个子网,同一文件中的所有容器都会自动加入,无需额外的网络配置。在 AI 时代,您甚至可以将您想要执行的
docker 命令告诉 AI,让它生成一个等价的 Docker Compose 文件,以简化编写过程。5. 文件创建命令(示例)
您可以先在服务器上使用文本编辑器(如
vi)创建并编辑该文件:vi docker-compose.yml
然后将配置内容粘贴进去并保存(在
vi 中保存退出::wq)。创建文件后,使用
docker compose up 命令即可启动文件中定义的所有容器。