Docker核心技术详解与简单实战

全文19974字,耐心观看,原文链接https://ai.feishu.cn/wiki/M3dFwp2Q8ivABfkTFOCcavNVnSg?from=from_copylink

  1. 了解 Docker 镜像的基础知识

1.1 什么是 Docker 镜像?(image)

简单来说,Docker 镜像就是一个只读的"软件安装包"。

  • 生活类比:
  • 如果不理解镜像,可以把它想象成 Windows 的 .iso 安装光盘,或者是 手机里的 APP 安装包(.apk/.ipa)。
  • 它里面包含了程序运行所需要的一切:代码、依赖库、环境变量、配置文件,甚至是一个微型的 Linux 操作系统(如 Alpine 或 Debian)。
  • 不管你把这个"安装包"拿到哪台电脑上(只要装了 Docker),它跑起来的样子都是一模一样的。

1.1.1 核心原理:为什么它叫"镜像"?(分层存储)

Docker 镜像最大的特点是 "分层" (Layered)。它不是一个单一的大文件,而是像"千层饼"一样,由很多层只读文件叠加而成的。

1.1.2 镜像的结构

  • Base Image(基础层):最底层通常是一个操作系统引导层(bootfs),上面是操作系统的根文件系统(rootfs),比如 Ubuntu、CentOS 或 Alpine。
  • Layer(中间层):在基础层之上,每安装一个软件(比如 install nginx)、每修改一个配置、每复制一个文件,都会生成一个新的"层"。
  • Image(最终镜像):所有这些层叠加在一起,对外展示为一个完整的文件系统。

1.1.3 为什么要分层?(知其所以然)

这是 Docker 最天才的设计,主要为了 资源共享 和 节省空间。

  • 举个例子:
  • 假设你有 10 个不同的镜像(比如 Nginx、Redis、Node.js),它们底层的系统都是 Debian。
  • 如果不分层:你需要下载 10 个 Debian 系统,硬盘里存 10 份,既浪费带宽又浪费硬盘。
  • 分层后:Docker 只需要下载一次 Debian 基础层。这 10 个镜像会共用这同一份底层文件。当你下载 Redis 时,如果 Docker 发现你本地已经有 Debian 层了,它就只下载 Redis 独有的那几兆文件。

1.1.4 镜像的关键特性

只读(Read-Only)

所有的镜像层都是只读的,不能修改。

  • 问题:如果我想改镜像里的代码怎么办?
  • 答案:你不能直接改原镜像。你只能基于原镜像启动一个容器,修改后生成一个新的镜像层;或者修改构建脚本(Dockerfile)重新构建一个新的镜像。
  • 好处:这保证了环境一致性。测试环境测好的镜像,推送到生产环境时,绝对不会因为"被人误改了"而出现 Bug。

唯一标识(Image ID)

每个镜像都有一个全球唯一的身份证号(Image ID),通常是一串长长的哈希值(SHA256)。为了方便人类记忆,我们通常用 仓库名:标签 来称呼它,例如 nginx:latest 或 mysql:5.7。

1.1.5 小结(复习用)

  • 它是啥:一个只读的、包含运行环境的软件包。
  • 结构:像千层饼一样的分层结构。
  • 优点:分层共享,节省空间;只读不可变,安全稳定。
  1. 了解 Docker 容器的基础知识

如果说镜像是"静止的模具",那么容器就是"鲜活的生命"。

2.1 什么是 Docker 容器?

简单来说,容器就是镜像运行起来后的一个"实例"。

  • 生活类比:
  • 类与对象:如果你熟悉编程,镜像就是 Class(类),容器就是 Object(对象/实例)。
  • 程序与进程:镜像就像躺在硬盘里的 QQ.exe(可执行文件),容器就像是你双击打开后,正在内存里跑着的 QQ 进程。
  • 房子与住户:镜像是一个精装修的样板房(空的),容器就是你拎包入住后的家(有了你的私人物品、生活痕迹)。
  • 游戏光盘(镜像) vs 运行中的游戏(容器):镜像就像一张《魔兽世界》的光盘,它是静止的。容器就像是你把它插进电脑、运行起来后的游戏画面,你在里面打怪升级(产生数据和变化),这些都是发生在容器里的。
  • 户型图(镜像) vs 样板间(容器):镜像是一张画好的装修图纸(只读)。容器是根据这张图纸盖出来的真实房间,你可以往里面搬家具、住人(可读写)。

2.2 核心原理:容器是怎么"跑"起来的?

初学者容易把容器当成一个"轻量级虚拟机",但它们本质完全不同。

2.2.1 容器 = 进程 + 隔离 (Isolation)

容器本质上只是宿主机上的一个 特殊进程。

  • 普通进程:你运行一个 python app.py,它能看到电脑里所有的文件,能看到其他进程,能随便用 CPU。
  • 容器进程:Docker 给这个进程戴上了"VR 眼镜"和"手铐脚镣",让它以为自己拥有一台独立的电脑,但实际上它只是被隔离了。

2.2.2 实现隔离的三大黑科技(知其所以然)

Docker 用 Linux 内核的三大技术来实现这种"欺骗":

  1. Namespaces(命名空间)------实现"欺骗视觉"

|-------------------|
| 作用:让容器看不见外面的世界。 |

  • PID Namespace进程隔离。容器里的进程看自己的 ID 是 1(老大),但其实它在宿主机上可能是一个 ID 为 12345 的普通小弟。
  • Mount Namespace挂载点隔离 。容器只能看到自己目录下的文件(比如 /app),根本看不到宿主机的 C 盘 D 盘。
  • Network Namespace网络隔离。容器有独立的网卡、IP 地址、路由表,感觉自己插着独立的网线。
  • 类比:VR 眼镜。戴上它,你虽然身体在客厅,但你眼里只有虚拟世界,完全看不见客厅里的沙发和电视。戴上它,容器以为自己住在一个大别墅里(有独立的 IP、独立的文件系统、独立的进程 ID),其实它只是挤在宿主机的一个小角落里。它看不见外面的宿主机,也看不见别的容器。
  1. Cgroups(控制组)------ 实现"资源限制"

|---------------------|
| 作用:限制容器"不能抢"太多资源。 |

  • 限制 CPU:规定这个容器只能用 0.5 个核,超了就慢下来。
  • 限制内存:规定只能用 512MB 内存,超了就杀掉(OOM)。
  • 类比:配额水表/电表。虽然大家住同一栋楼,共用一个水管,但给你的房间装了智能水表,超过配额就断水,防止你一个人把整栋楼的水都用光。
  • 场景:你可以限制某个容器最多只能用 10% 的 CPU,或最多用 512MB 内存。如果超了,系统会把它杀掉,保证不影响宿主机和其他容器。
  1. UnionFS(联合文件系统)& chroot------ 实现"写时复制" (Copy-on-Write) "文件"隔离

|---------------------|
| 作用:给容器一个独立的"系统盘"。 |

  • 问题:镜像(Image)是只读的,那容器里产生的日志、修改的文件存在哪?
  • 机制:Docker 会在只读的镜像层之上,盖一层薄薄的 "读写层" (Writable Layer)。
  • 原理:
  • 读文件:直接读底层的镜像。
  • 写文件:当你在这个"只读"文件上写字时,Docker 会瞬间把这个文件复制一份到顶部的"读写层",你修改的其实是这个副本。
  • 结果:底下的镜像永远不会被破坏。容器一删,这层"读写层"就丢了,数据也就没了(所以要用数据卷 Volume 来持久化)。

换句话说

chroot / pivot_root:它可以把某个进程的"根目录"锁定在指定文件夹里(比如 /var/lib/docker/overlay2/xxx)。在这个进程看来,这个文件夹就是它的 /(根目录),它永远走不出这个圈。

UnionFS:它把只读的镜像层和可读写的容器层"联合"挂载在一起,形成一个完整的文件系统给容器看。

  • 类比:全息投影的房间。
  • chroot 就像把你关进了一个空房间,锁上门,你出不去。
  • UnionFS 就像是在这个空房间里,用全息投影投射出了家具、墙纸(镜像层)。你看着很真实,也可以在里面画画(读写层),但其实你并没有真的改变这个房间的结构。

2.2.3 为什么需要"写时复制" (Copy-on-Write)?

  • 问题:镜像(图纸)是不能改的,那我在容器(房间)里产生的垃圾(日志)或者新买的家具(新文件)放哪?
  • 机制:Docker 会在只读的镜像层上面,盖一层透明的"读写层"。
  • 类比:描红纸。
  • 底下的字帖(镜像)是不能涂改的。
  • Docker 在字帖上蒙了一张透明的纸(读写层)。
  • 你想改哪个字,就把它抄到透明纸上再修改。
  • 你看上去是改了,其实底下的字帖完好无损。
  • 后果:这张透明纸(容器)一扔,你修改的内容就全没了(除非你用了数据卷保存)。

++++总结++++

  • Namespaces = 围墙(看不见外面)
  • Cgroups = 限额(抢不到资源)
  • UnionFS = 幻象(独立的文件环境)

(容器的唯一标识容器ID与镜像ID一样采用UUID形式表示,是由64个十六进制字符组成的字符串。

通过容器名称来代替容器ID引用容器。)

2.3 容器 vs 虚拟机 (VM):为什么 Docker 这么快?

  • 比喻:
  • 虚拟机:像是一栋大楼里,给每家每户都配了独立的水电站、独立的锅炉房(资源浪费)。
  • 容器:像是一栋胶囊公寓,大家共享大楼的水电、地基(内核),但每个人住在自己的独立胶囊房间里(互不干扰)。

容器 vs 虚拟机 (VM)

  • 虚拟机 (VM):
  • 类比:独栋别墅。每家每户都有独立的地基、供暖系统(独立的操作系统内核)。
  • 缺点:太重了,建起来慢(启动慢),占地面积大(占用内存大)。
  • 容器 (Container):
  • 类比:胶囊公寓。大家共享大楼的地基和供暖(共享宿主机内核)。
  • 优点:轻便,拎包入住(秒级启动),省空间(占用内存小)。

2.4 容器的生命周期(Lifecycle)

容器是短暂的(Ephemeral)。设计理念是"用完即焚"。

  • Created:刚造出来,还没跑。
  • Running:正在干活。
  • Paused:暂停(类似电脑睡眠)。
  • Exited (Stopped):干完活了,或者报错退出了。注意:停止不等于删除,它的尸体(文件系统)还在。
  • Deleted:彻底销毁,渣都不剩。

小结:

容器就是一个被隔离的进程,它利用 Namespace 欺骗视觉,利用 Cgroups 限制资源,利用 写时复制 来保护镜像。

小结

  • 容器 = 镜像 + 读写层。
  • 容器本质是隔离的进程。
  • 容器比虚拟机轻量,是因为共享内核。
  1. 了解Docker仓库基础知识(Repository)

3.1 什么是 Docker 仓库?

简单来说,仓库是集中存放镜像的地方。

  • 生活类比:
  • 代码界:如果镜像是代码,仓库就是 GitHub。
  • 手机界:如果镜像是 APP,仓库就是 App Store(应用商店)。
  • 物流界:如果镜像是货物,仓库就是 亚马逊/京东的大型物流中心。

3.2 核心概念辨析:Registry vs Repository

初学者经常搞混这两个词,它们虽然都叫"仓库",但层级不同。

3.2.1 Registry(注册中心)------ "大商场"

  • 定义:存放很多个仓库的服务器。
  • 例子:
  • Docker Hub:Docker 官方运营的全球最大的 Registry。
  • 阿里云容器镜像服务:阿里云搭建的 Registry。
  • Google Container Registry:谷歌搭建的 Registry。
  • 类比:Registry 就像是一个具体的 "沃尔玛超市" 或 "7-11 便利店"。

3.2.2 Repository(仓库)------ "货架"

  • 定义:Registry 里的一个具体的项目,里面存放了同一种软件的不同版本(Tags)。
  • 例子:
  • nginx:这是一个仓库,里面有 nginx:latest、nginx:1.19、nginx:alpine 等不同版本的镜像。
  • mysql:这是一个仓库,里面有 mysql:5.7、mysql:8.0 等。
  • 类比:Repository 就像是超市里的 "薯片货架"。这个货架上全都是薯片(同一个软件),但是有原味、番茄味、黄瓜味(不同 Tag 版本)。

3.2.3 完整的镜像地址结构

当我们执行docker pull时,其实我们是再写一个完整的地址:

|------------------------------------------------------------------------------------------|
| Plain Text 【Registry 地址】/【项目组/用户名】/【Repository名】:【Tag】 例如:docker.io/library/nginx:latest |

  • docker.io:Registry地址(默认是Docker Hub,通常省略)。
  • library:项目组(官方镜像都在library组,通常省略)
  • nginx:Repository名字(必须写)
  • latest:标签(不写默认是latest)

3.3 仓库的分类

3.3.1 共有仓库(public)

  • 特点:任何人都可以拉取
  • 场景:你需要下载Nginx、Redis、Python等基础软件时,直接去公有仓库拉取。绝大多数开源软件都托管在这里。

3.3.2 私有仓库(Private)

  • 代表:
  • 企业自建:使用Docker Registry镜像或Harbor软件自己搭建的Registry
  • 云厂商托管:阿里云、腾讯云提供的私有镜像服务(通常要付费或有配额)
  • 特点:只有通过认证(Login)的人才能拉取和推送
  • 场景:公司开发的业务代码(比如"双11大促支付系统"),里面有商业机密,绝对不能传到公网。只能传到公司内网的私有仓库里,供公司内部服务器部署使用。
  1. docker三大核心组件(镜像、容器、仓库)之间的关系及工作流程

4.1 三个核心角色(Locations & Objects)

这张图被分为左右两个大框,分别代表了两个物理位置:

  1. 左边大框:本地(Local Host)
  • 这里是你自己的电脑或服务器。
  • 角色 A:镜像(Image):
  • 位置:左上角。
  • 比喻:它是 "模具" 或 "类"。它是静态的、只读的。它是用来创建容器的模板。
  • 角色 B:容器(Container):
  • 位置:左下角。
  • 比喻:它是 "蛋糕" 或 "对象"。它是动态的、正在运行的。它是真正干活的程序实体。
  1. 右边大框:注册中心(Registry)
  • 这里是远程服务器(如 Docker Hub 或 阿里云镜像仓库)。
  • 角色 C:仓库(Repository):
  • 位置:右侧灰色方块。
  • 比喻:它是 "超市货架" 或 "代码仓库"。这里存放着各种打包好的镜像,供大家下载使用。

4.2 四个核心动作(Actions)

图中的箭头代表了数据流向,也对应了Docker最常用的四个命令:

4.2.1 拉取(pull)

  • 路径:仓库(Registry)->镜像(image)
  • 命令:docker pull nginx
  • 含义:"进货"。
  • 你从远程的仓库里,把别人做好的镜像下载到你本地的硬盘里
  • 场景:场景:你要安装某个软件(如 MySQL),第一步就是去仓库把它拉下来。

4.2.2 推送(push)

  • 路径:镜像(image)->仓库(Registry)
  • 命令:docker push my-app:v1
  • 含义:"发货"。
  • 你在本地做好了自己的镜像,想分享给同事,或者存到服务器上备份,就把它上传到远程仓库。
  • 场景:开发完代码,打包成镜像后,发布到公司的私有仓库里。

4.2.3 实例化/运行(run)

  • 路径:镜像(image)->容器(Container)
  • 命令:docker run nginx
  • 含义:"做蛋糕"
  • 利用本地的镜像(模具),创建一个运行中的容器(蛋糕)
  • 关键点:这是一个1对N的关系。一个镜像可以启动无数个容器(就像一个模具可以做无数个一模一样的蛋糕)
  • 场景:软件下载(pull)好了,现在要启动它开始服务。

4.2.4 提交(commit)

  • 路径:容器(container)->镜像(image)
  • 命令:docker commit<容器ID><新镜像名>
  • 含义:"定型"
  • 你进入容器里修改了配置文件、安装了新软件,现在的容器和原来的镜像不一样了。你想保存这个状态,就把它反向打包成一个新的镜像。
  • 场景:你在一个基础 Ubuntu 容器里装好了 Java 和 Tomcat,想把它保存下来,下次直接用这个环境,不用再重装一遍。
  • 注:虽然图里画了这个,但实际工作中我们更推荐用 Dockerfile 来构建镜像,而不是用 commit ,因为 Dockerfile 更透明、可维护。

4.3 总结串讲

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| "大家看这张图,它完美解释了 Docker 的工作流: 一切从右边的 仓库(Registry) 开始。我们通过 pull (拉取) 命令,像逛超市一样把需要的软件镜像下载到 本地(Local)。 拿到 镜像(Image) 后,它是静态的,不能直接用。我们需要通过 run (运行) 命令,把它变成一个活生生的 容器(Container),这时候服务才真正跑起来。 如果我们在容器里修修补补,想保存劳动成果,可以用 commit (提交) 命令把它变成一个新的镜像。 最后,为了防止本地硬盘坏了丢失数据,或者为了分发给其他同事,我们通过 push (推送) 命令,把这个新镜像上传回远程 仓库。 这就是 Docker 的生命周期循环。" |

|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 由于怕初学者绕晕,这里开一个小知识点 * 镜像分类 * 操作系统:ubuntu, centos, alpine(基础底座)。 * 数据库:mysql, redis, mongo, postgres。 * 中间件:nginx, tomcat, rabbitmq。 * 应用软件:wordpress, jenkins, gitlab。 这四类(操作系统、数据库、中间件、应用软件)指的是 镜像的类型(分类),但它们存放在仓库里。 在 Docker 命令里,我们常说"去仓库拉个 Nginx"。 * 这句话严谨的翻译是:去 Docker Hub(注册中心) 的 library/nginx(仓库/货架) 里,拉取 nginx:latest(镜像/商品)。 |

  1. 命令详解

5.1 镜像基本信息与查看(实战)

5.1.1 镜像基本信息与查看实战

  1. 查看本地镜像列表

|--------------------------------------------------------|
| Plain Text 操作命令: [root@docker_dev ~]# docker images |

|----------------------------------------------------------------------------------------------------------------------------------------------------------|
| Plain Text 输出示例: REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu latest a8780b506fa4 4 weeks ago 77.8MB hello-world latest feb5d9fea6a5 14 months ago 13.3kB |

  1. 输出字段详解

|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| * REPOSITORY(仓库源): * 表示这个镜像是什么软件。例如 ubuntu 表示这是一个 Ubuntu 操作系统的镜像,redis 表示这是 Redis 数据库的镜像。 * TAG(标签): * 表示镜像的版本。例如 latest(最新版)、18.04、alpine 等。 * 知识点:REPOSITORY:TAG 共同构成了一个完整的镜像名(如 ubuntu:latest)。如果只写 ubuntu,Docker 默认去找 ubuntu:latest。 * IMAGE ID(镜像 ID): * 核心身份:这是镜像的全球唯一身份证号。 * 格式:它是一个 SHA256 哈希值,全长 64 个十六进制字符(为了方便显示,通常只截取前 12 位,如 a8780b506fa4)。 * 作用:当你对同一个镜像打不同的 Tag 时(比如把 my-app:v1 改名为 my-app:latest),它们的 Image ID 是一样的,说明它们本质上是同一个文件。 * CREATED(创建时间): * 镜像被打包构建的时间(注意:不是你下载的时间,是官方发布这个版本的时间)。 * SIZE(大小): * 镜像占用的逻辑大小。 * 注意:由于镜像有"分层共享"机制,如果你有 10 个镜像,它们加起来的 SIZE 显示是 5GB,但实际占用的硬盘空间可能只有 2GB(因为它们共用了底层的 Debian 系统层)。 |

  1. 如何引用一个镜像?

在使用 Docker 命令(如运行、删除)时,我们有三种方式来指定一个镜像:

  • 使用完整名称:ubuntu:latest(推荐,最清晰)
  • 使用镜像 ID:a8780b506fa4(精确,只要输入前几位能区分即可,不用输全)
  • 使用摘要值 (Digest):一种更长、更精确的哈希值(通常用于自动化脚本,手动操作很少用)。

5.1.2 镜像描述文件Dockerfile---镜像的图纸

既然镜像是分层的,那这些层是怎么堆叠起来的呢?这就需要提到 Dockerfile。

  • 定义:Dockerfile 是一个文本文件,它就像一张施工图纸。
  • 作用:它包含了一系列指令,告诉 Docker 引擎:"第一步装系统,第二步考文件,第三步运行程序......",Docker 照着这张图纸,一步步把镜像构建(Build)出来。
  1. 举例 hello-world 为例

所有的 Docker 教程第一步都是运行 hello-world,我们看看这张图纸里写了什么

|-------------------------------------------------------|
| Plain Text FROM scratch COPY hello / CMD ["/hello"] |

  1. 行代码深度解析
  • 第一行:FROM scratch
  • 含义:从零开始。
  • 深度解析:
  • FROM 指令必须是第一行,它指定了基础镜像(Base Image)。通常我们会写 FROM ubuntu 或 FROM python。
  • scratch 是 Docker 中一个特殊的、保留的空镜像。它里面什么都没有,连最基本的 Linux 命令行工具(ls, cd)都没有。
  • 为什么要用它? 因为 hello-world 程序是用 C/Go 语言写好的二进制文件,它不需要操作系统环境就能直接在内核上跑。为了让镜像尽可能小(只有 13KB),所以用了这个空底座。
  • 第二行:COPY hello /
  • 含义:复制文件。
  • 深度解析:
  • COPY 指令的作用是把宿主机(你的电脑)里的文件拷贝到镜像里。
  • 这句话的意思是:把当前目录下的 hello 可执行文件,复制到镜像的根目录 / 下。
  • 第三行:CMD ["/hello"]
  • 含义:默认启动命令。
  • 深度解析:
  • CMD 指定了当这个镜像变成容器并启动时,默认要干什么事。
  • 这里的意思是:容器一启动,就执行根目录下的 /hello 程序。
  • 这个程序执行完打印几行字后就会结束,所以容器也会随之停止(Exited)。

5.1.3 镜像常用操作命令(速查与实战)

在 Docker 中,管理镜像的命令通常以 docker image 开头,但为了方便,Docker 也提供了简写形式(如 docker pull)。建议大家在日常使用中优先记忆简写形式,效率更高。

Docker核心技术详解与简单实战

  1. 了解 Docker 镜像的基础知识

1.1 什么是 Docker 镜像?(image)

简单来说,Docker 镜像就是一个只读的"软件安装包"。

  • 生活类比:
  • 如果不理解镜像,可以把它想象成 Windows 的 .iso 安装光盘,或者是 手机里的 APP 安装包(.apk/.ipa)。
  • 它里面包含了程序运行所需要的一切:代码、依赖库、环境变量、配置文件,甚至是一个微型的 Linux 操作系统(如 Alpine 或 Debian)。
  • 不管你把这个"安装包"拿到哪台电脑上(只要装了 Docker),它跑起来的样子都是一模一样的。

1.1.1 核心原理:为什么它叫"镜像"?(分层存储)

Docker 镜像最大的特点是 "分层" (Layered)。它不是一个单一的大文件,而是像"千层饼"一样,由很多层只读文件叠加而成的。

1.1.2 镜像的结构

  • Base Image(基础层):最底层通常是一个操作系统引导层(bootfs),上面是操作系统的根文件系统(rootfs),比如 Ubuntu、CentOS 或 Alpine。
  • Layer(中间层):在基础层之上,每安装一个软件(比如 install nginx)、每修改一个配置、每复制一个文件,都会生成一个新的"层"。
  • Image(最终镜像):所有这些层叠加在一起,对外展示为一个完整的文件系统。

1.1.3 为什么要分层?(知其所以然)

这是 Docker 最天才的设计,主要为了 资源共享 和 节省空间。

  • 举个例子:
  • 假设你有 10 个不同的镜像(比如 Nginx、Redis、Node.js),它们底层的系统都是 Debian。
  • 如果不分层:你需要下载 10 个 Debian 系统,硬盘里存 10 份,既浪费带宽又浪费硬盘。
  • 分层后:Docker 只需要下载一次 Debian 基础层。这 10 个镜像会共用这同一份底层文件。当你下载 Redis 时,如果 Docker 发现你本地已经有 Debian 层了,它就只下载 Redis 独有的那几兆文件。

1.1.4 镜像的关键特性

只读(Read-Only)

所有的镜像层都是只读的,不能修改。

  • 问题:如果我想改镜像里的代码怎么办?
  • 答案:你不能直接改原镜像。你只能基于原镜像启动一个容器,修改后生成一个新的镜像层;或者修改构建脚本(Dockerfile)重新构建一个新的镜像。
  • 好处:这保证了环境一致性。测试环境测好的镜像,推送到生产环境时,绝对不会因为"被人误改了"而出现 Bug。

唯一标识(Image ID)

每个镜像都有一个全球唯一的身份证号(Image ID),通常是一串长长的哈希值(SHA256)。为了方便人类记忆,我们通常用 仓库名:标签 来称呼它,例如 nginx:latest 或 mysql:5.7。

1.1.5 小结(复习用)

  • 它是啥:一个只读的、包含运行环境的软件包。
  • 结构:像千层饼一样的分层结构。
  • 优点:分层共享,节省空间;只读不可变,安全稳定。
  1. 了解 Docker 容器的基础知识

如果说镜像是"静止的模具",那么容器就是"鲜活的生命"。

2.1 什么是 Docker 容器?

简单来说,容器就是镜像运行起来后的一个"实例"。

  • 生活类比:
  • 类与对象:如果你熟悉编程,镜像就是 Class(类),容器就是 Object(对象/实例)。
  • 程序与进程:镜像就像躺在硬盘里的 QQ.exe(可执行文件),容器就像是你双击打开后,正在内存里跑着的 QQ 进程。
  • 房子与住户:镜像是一个精装修的样板房(空的),容器就是你拎包入住后的家(有了你的私人物品、生活痕迹)。
  • 游戏光盘(镜像) vs 运行中的游戏(容器):镜像就像一张《魔兽世界》的光盘,它是静止的。容器就像是你把它插进电脑、运行起来后的游戏画面,你在里面打怪升级(产生数据和变化),这些都是发生在容器里的。
  • 户型图(镜像) vs 样板间(容器):镜像是一张画好的装修图纸(只读)。容器是根据这张图纸盖出来的真实房间,你可以往里面搬家具、住人(可读写)。

2.2 核心原理:容器是怎么"跑"起来的?

初学者容易把容器当成一个"轻量级虚拟机",但它们本质完全不同。

2.2.1 容器 = 进程 + 隔离 (Isolation)

容器本质上只是宿主机上的一个 特殊进程。

  • 普通进程:你运行一个 python app.py,它能看到电脑里所有的文件,能看到其他进程,能随便用 CPU。
  • 容器进程:Docker 给这个进程戴上了"VR 眼镜"和"手铐脚镣",让它以为自己拥有一台独立的电脑,但实际上它只是被隔离了。

2.2.2 实现隔离的三大黑科技(知其所以然)

Docker 用 Linux 内核的三大技术来实现这种"欺骗":

  1. Namespaces(命名空间)------实现"欺骗视觉"

|-------------------|
| 作用:让容器看不见外面的世界。 |

  • PID Namespace进程隔离。容器里的进程看自己的 ID 是 1(老大),但其实它在宿主机上可能是一个 ID 为 12345 的普通小弟。
  • Mount Namespace挂载点隔离 。容器只能看到自己目录下的文件(比如 /app),根本看不到宿主机的 C 盘 D 盘。
  • Network Namespace网络隔离。容器有独立的网卡、IP 地址、路由表,感觉自己插着独立的网线。
  • 类比:VR 眼镜。戴上它,你虽然身体在客厅,但你眼里只有虚拟世界,完全看不见客厅里的沙发和电视。戴上它,容器以为自己住在一个大别墅里(有独立的 IP、独立的文件系统、独立的进程 ID),其实它只是挤在宿主机的一个小角落里。它看不见外面的宿主机,也看不见别的容器。
  1. Cgroups(控制组)------ 实现"资源限制"

|---------------------|
| 作用:限制容器"不能抢"太多资源。 |

  • 限制 CPU:规定这个容器只能用 0.5 个核,超了就慢下来。
  • 限制内存:规定只能用 512MB 内存,超了就杀掉(OOM)。
  • 类比:配额水表/电表。虽然大家住同一栋楼,共用一个水管,但给你的房间装了智能水表,超过配额就断水,防止你一个人把整栋楼的水都用光。
  • 场景:你可以限制某个容器最多只能用 10% 的 CPU,或最多用 512MB 内存。如果超了,系统会把它杀掉,保证不影响宿主机和其他容器。
  1. UnionFS(联合文件系统)& chroot------ 实现"写时复制" (Copy-on-Write) "文件"隔离

|---------------------|
| 作用:给容器一个独立的"系统盘"。 |

  • 问题:镜像(Image)是只读的,那容器里产生的日志、修改的文件存在哪?
  • 机制:Docker 会在只读的镜像层之上,盖一层薄薄的 "读写层" (Writable Layer)。
  • 原理:
  • 读文件:直接读底层的镜像。
  • 写文件:当你在这个"只读"文件上写字时,Docker 会瞬间把这个文件复制一份到顶部的"读写层",你修改的其实是这个副本。
  • 结果:底下的镜像永远不会被破坏。容器一删,这层"读写层"就丢了,数据也就没了(所以要用数据卷 Volume 来持久化)。

换句话说

chroot / pivot_root:它可以把某个进程的"根目录"锁定在指定文件夹里(比如 /var/lib/docker/overlay2/xxx)。在这个进程看来,这个文件夹就是它的 /(根目录),它永远走不出这个圈。

UnionFS:它把只读的镜像层和可读写的容器层"联合"挂载在一起,形成一个完整的文件系统给容器看。

  • 类比:全息投影的房间。
  • chroot 就像把你关进了一个空房间,锁上门,你出不去。
  • UnionFS 就像是在这个空房间里,用全息投影投射出了家具、墙纸(镜像层)。你看着很真实,也可以在里面画画(读写层),但其实你并没有真的改变这个房间的结构。

2.2.3 为什么需要"写时复制" (Copy-on-Write)?

  • 问题:镜像(图纸)是不能改的,那我在容器(房间)里产生的垃圾(日志)或者新买的家具(新文件)放哪?
  • 机制:Docker 会在只读的镜像层上面,盖一层透明的"读写层"。
  • 类比:描红纸。
  • 底下的字帖(镜像)是不能涂改的。
  • Docker 在字帖上蒙了一张透明的纸(读写层)。
  • 你想改哪个字,就把它抄到透明纸上再修改。
  • 你看上去是改了,其实底下的字帖完好无损。
  • 后果:这张透明纸(容器)一扔,你修改的内容就全没了(除非你用了数据卷保存)。

++++总结++++

  • Namespaces = 围墙(看不见外面)
  • Cgroups = 限额(抢不到资源)
  • UnionFS = 幻象(独立的文件环境)

(容器的唯一标识容器ID与镜像ID一样采用UUID形式表示,是由64个十六进制字符组成的字符串。

通过容器名称来代替容器ID引用容器。)

2.3 容器 vs 虚拟机 (VM):为什么 Docker 这么快?

  • 比喻:
  • 虚拟机:像是一栋大楼里,给每家每户都配了独立的水电站、独立的锅炉房(资源浪费)。
  • 容器:像是一栋胶囊公寓,大家共享大楼的水电、地基(内核),但每个人住在自己的独立胶囊房间里(互不干扰)。

容器 vs 虚拟机 (VM)

  • 虚拟机 (VM):
  • 类比:独栋别墅。每家每户都有独立的地基、供暖系统(独立的操作系统内核)。
  • 缺点:太重了,建起来慢(启动慢),占地面积大(占用内存大)。
  • 容器 (Container):
  • 类比:胶囊公寓。大家共享大楼的地基和供暖(共享宿主机内核)。
  • 优点:轻便,拎包入住(秒级启动),省空间(占用内存小)。

2.4 容器的生命周期(Lifecycle)

容器是短暂的(Ephemeral)。设计理念是"用完即焚"。

  • Created:刚造出来,还没跑。
  • Running:正在干活。
  • Paused:暂停(类似电脑睡眠)。
  • Exited (Stopped):干完活了,或者报错退出了。注意:停止不等于删除,它的尸体(文件系统)还在。
  • Deleted:彻底销毁,渣都不剩。

小结:

容器就是一个被隔离的进程,它利用 Namespace 欺骗视觉,利用 Cgroups 限制资源,利用 写时复制 来保护镜像。

小结

  • 容器 = 镜像 + 读写层。
  • 容器本质是隔离的进程。
  • 容器比虚拟机轻量,是因为共享内核。

|---|
| |

  1. 了解Docker仓库基础知识(Repository)

3.1 什么是 Docker 仓库?

简单来说,仓库是集中存放镜像的地方。

  • 生活类比:
  • 代码界:如果镜像是代码,仓库就是 GitHub。
  • 手机界:如果镜像是 APP,仓库就是 App Store(应用商店)。
  • 物流界:如果镜像是货物,仓库就是 亚马逊/京东的大型物流中心。

3.2 核心概念辨析:Registry vs Repository

初学者经常搞混这两个词,它们虽然都叫"仓库",但层级不同。

3.2.1 Registry(注册中心)------ "大商场"

  • 定义:存放很多个仓库的服务器。
  • 例子:
  • Docker Hub:Docker 官方运营的全球最大的 Registry。
  • 阿里云容器镜像服务:阿里云搭建的 Registry。
  • Google Container Registry:谷歌搭建的 Registry。
  • 类比:Registry 就像是一个具体的 "沃尔玛超市" 或 "7-11 便利店"。

3.2.2 Repository(仓库)------ "货架"

  • 定义:Registry 里的一个具体的项目,里面存放了同一种软件的不同版本(Tags)。
  • 例子:
  • nginx:这是一个仓库,里面有 nginx:latest、nginx:1.19、nginx:alpine 等不同版本的镜像。
  • mysql:这是一个仓库,里面有 mysql:5.7、mysql:8.0 等。
  • 类比:Repository 就像是超市里的 "薯片货架"。这个货架上全都是薯片(同一个软件),但是有原味、番茄味、黄瓜味(不同 Tag 版本)。

3.2.3 完整的镜像地址结构

当我们执行docker pull时,其实我们是再写一个完整的地址:

|------------------------------------------------------------------------------------------|
| Plain Text 【Registry 地址】/【项目组/用户名】/【Repository名】:【Tag】 例如:docker.io/library/nginx:latest |

  • docker.io:Registry地址(默认是Docker Hub,通常省略)。
  • library:项目组(官方镜像都在library组,通常省略)
  • nginx:Repository名字(必须写)
  • latest:标签(不写默认是latest)

3.3 仓库的分类

3.3.1 共有仓库(public)

  • 特点:任何人都可以拉取
  • 场景:你需要下载Nginx、Redis、Python等基础软件时,直接去公有仓库拉取。绝大多数开源软件都托管在这里。

3.3.2 私有仓库(Private)

  • 代表:
  • 企业自建:使用Docker Registry镜像或Harbor软件自己搭建的Registry
  • 云厂商托管:阿里云、腾讯云提供的私有镜像服务(通常要付费或有配额)
  • 特点:只有通过认证(Login)的人才能拉取和推送
  • 场景:公司开发的业务代码(比如"双11大促支付系统"),里面有商业机密,绝对不能传到公网。只能传到公司内网的私有仓库里,供公司内部服务器部署使用。
  1. docker三大核心组件(镜像、容器、仓库)之间的关系及工作流程

4.1 三个核心角色(Locations & Objects)

这张图被分为左右两个大框,分别代表了两个物理位置:

  1. 左边大框:本地(Local Host)
  • 这里是你自己的电脑或服务器。
  • 角色 A:镜像(Image):
  • 位置:左上角。
  • 比喻:它是 "模具" 或 "类"。它是静态的、只读的。它是用来创建容器的模板。
  • 角色 B:容器(Container):
  • 位置:左下角。
  • 比喻:它是 "蛋糕" 或 "对象"。它是动态的、正在运行的。它是真正干活的程序实体。
  1. 右边大框:注册中心(Registry)
  • 这里是远程服务器(如 Docker Hub 或 阿里云镜像仓库)。
  • 角色 C:仓库(Repository):
  • 位置:右侧灰色方块。
  • 比喻:它是 "超市货架" 或 "代码仓库"。这里存放着各种打包好的镜像,供大家下载使用。

4.2 四个核心动作(Actions)

图中的箭头代表了数据流向,也对应了Docker最常用的四个命令:

4.2.1 拉取(pull)

  • 路径:仓库(Registry)->镜像(image)
  • 命令:docker pull nginx
  • 含义:"进货"。
  • 你从远程的仓库里,把别人做好的镜像下载到你本地的硬盘里
  • 场景:场景:你要安装某个软件(如 MySQL),第一步就是去仓库把它拉下来。

4.2.2 推送(push)

  • 路径:镜像(image)->仓库(Registry)
  • 命令:docker push my-app:v1
  • 含义:"发货"。
  • 你在本地做好了自己的镜像,想分享给同事,或者存到服务器上备份,就把它上传到远程仓库。
  • 场景:开发完代码,打包成镜像后,发布到公司的私有仓库里。

4.2.3 实例化/运行(run)

  • 路径:镜像(image)->容器(Container)
  • 命令:docker run nginx
  • 含义:"做蛋糕"
  • 利用本地的镜像(模具),创建一个运行中的容器(蛋糕)
  • 关键点:这是一个1对N的关系。一个镜像可以启动无数个容器(就像一个模具可以做无数个一模一样的蛋糕)
  • 场景:软件下载(pull)好了,现在要启动它开始服务。

4.2.4 提交(commit)

  • 路径:容器(container)->镜像(image)
  • 命令:docker commit<容器ID><新镜像名>
  • 含义:"定型"
  • 你进入容器里修改了配置文件、安装了新软件,现在的容器和原来的镜像不一样了。你想保存这个状态,就把它反向打包成一个新的镜像。
  • 场景:你在一个基础 Ubuntu 容器里装好了 Java 和 Tomcat,想把它保存下来,下次直接用这个环境,不用再重装一遍。
  • 注:虽然图里画了这个,但实际工作中我们更推荐用 Dockerfile 来构建镜像,而不是用 commit ,因为 Dockerfile 更透明、可维护。

4.3 总结串讲

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| "大家看这张图,它完美解释了 Docker 的工作流: 一切从右边的 仓库(Registry) 开始。我们通过 pull (拉取) 命令,像逛超市一样把需要的软件镜像下载到 本地(Local)。 拿到 镜像(Image) 后,它是静态的,不能直接用。我们需要通过 run (运行) 命令,把它变成一个活生生的 容器(Container),这时候服务才真正跑起来。 如果我们在容器里修修补补,想保存劳动成果,可以用 commit (提交) 命令把它变成一个新的镜像。 最后,为了防止本地硬盘坏了丢失数据,或者为了分发给其他同事,我们通过 push (推送) 命令,把这个新镜像上传回远程 仓库。 这就是 Docker 的生命周期循环。" |

|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 由于怕初学者绕晕,这里开一个小知识点 * 镜像分类 * 操作系统:ubuntu, centos, alpine(基础底座)。 * 数据库:mysql, redis, mongo, postgres。 * 中间件:nginx, tomcat, rabbitmq。 * 应用软件:wordpress, jenkins, gitlab。 这四类(操作系统、数据库、中间件、应用软件)指的是 镜像的类型(分类),但它们存放在仓库里。 在 Docker 命令里,我们常说"去仓库拉个 Nginx"。 * 这句话严谨的翻译是:去 Docker Hub(注册中心) 的 library/nginx(仓库/货架) 里,拉取 nginx:latest(镜像/商品)。 |

  1. 命令详解

5.1 镜像基本信息与查看(实战)

5.1.1 镜像基本信息与查看实战

  1. 查看本地镜像列表

|--------------------------------------------------------|
| Plain Text 操作命令: [root@docker_dev ~]# docker images |

|----------------------------------------------------------------------------------------------------------------------------------------------------------|
| Plain Text 输出示例: REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu latest a8780b506fa4 4 weeks ago 77.8MB hello-world latest feb5d9fea6a5 14 months ago 13.3kB |

  1. 输出字段详解

|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| * REPOSITORY(仓库源): * 表示这个镜像是什么软件。例如 ubuntu 表示这是一个 Ubuntu 操作系统的镜像,redis 表示这是 Redis 数据库的镜像。 * TAG(标签): * 表示镜像的版本。例如 latest(最新版)、18.04、alpine 等。 * 知识点:REPOSITORY:TAG 共同构成了一个完整的镜像名(如 ubuntu:latest)。如果只写 ubuntu,Docker 默认去找 ubuntu:latest。 * IMAGE ID(镜像 ID): * 核心身份:这是镜像的全球唯一身份证号。 * 格式:它是一个 SHA256 哈希值,全长 64 个十六进制字符(为了方便显示,通常只截取前 12 位,如 a8780b506fa4)。 * 作用:当你对同一个镜像打不同的 Tag 时(比如把 my-app:v1 改名为 my-app:latest),它们的 Image ID 是一样的,说明它们本质上是同一个文件。 * CREATED(创建时间): * 镜像被打包构建的时间(注意:不是你下载的时间,是官方发布这个版本的时间)。 * SIZE(大小): * 镜像占用的逻辑大小。 * 注意:由于镜像有"分层共享"机制,如果你有 10 个镜像,它们加起来的 SIZE 显示是 5GB,但实际占用的硬盘空间可能只有 2GB(因为它们共用了底层的 Debian 系统层)。 |

  1. 如何引用一个镜像?

在使用 Docker 命令(如运行、删除)时,我们有三种方式来指定一个镜像:

  • 使用完整名称:ubuntu:latest(推荐,最清晰)
  • 使用镜像 ID:a8780b506fa4(精确,只要输入前几位能区分即可,不用输全)
  • 使用摘要值 (Digest):一种更长、更精确的哈希值(通常用于自动化脚本,手动操作很少用)。

5.1.2 镜像描述文件Dockerfile---镜像的图纸

既然镜像是分层的,那这些层是怎么堆叠起来的呢?这就需要提到 Dockerfile。

  • 定义:Dockerfile 是一个文本文件,它就像一张施工图纸。
  • 作用:它包含了一系列指令,告诉 Docker 引擎:"第一步装系统,第二步考文件,第三步运行程序......",Docker 照着这张图纸,一步步把镜像构建(Build)出来。
  1. 举例 hello-world 为例

所有的 Docker 教程第一步都是运行 hello-world,我们看看这张图纸里写了什么

|-------------------------------------------------------|
| Plain Text FROM scratch COPY hello / CMD ["/hello"] |

  1. 行代码深度解析
  • 第一行:FROM scratch
  • 含义:从零开始。
  • 深度解析:
  • FROM 指令必须是第一行,它指定了基础镜像(Base Image)。通常我们会写 FROM ubuntu 或 FROM python。
  • scratch 是 Docker 中一个特殊的、保留的空镜像。它里面什么都没有,连最基本的 Linux 命令行工具(ls, cd)都没有。
  • 为什么要用它? 因为 hello-world 程序是用 C/Go 语言写好的二进制文件,它不需要操作系统环境就能直接在内核上跑。为了让镜像尽可能小(只有 13KB),所以用了这个空底座。
  • 第二行:COPY hello /
  • 含义:复制文件。
  • 深度解析:
  • COPY 指令的作用是把宿主机(你的电脑)里的文件拷贝到镜像里。
  • 这句话的意思是:把当前目录下的 hello 可执行文件,复制到镜像的根目录 / 下。
  • 第三行:CMD ["/hello"]
  • 含义:默认启动命令。
  • 深度解析:
  • CMD 指定了当这个镜像变成容器并启动时,默认要干什么事。
  • 这里的意思是:容器一启动,就执行根目录下的 /hello 程序。
  • 这个程序执行完打印几行字后就会结束,所以容器也会随之停止(Exited)。

5.1.3 镜像常用操作命令(速查与实战)

在 Docker 中,管理镜像的命令通常以 docker image 开头,但为了方便,Docker 也提供了简写形式(如 docker pull)。建议大家在日常使用中优先记忆简写形式,效率更高。

5.2 容器操作常用命令(速查与实战)

容器是动态的,所以它的命令比镜像更多,涵盖了从"出生"到"死亡"的全过程。同样,我们推荐使用简写命令。

5.2.1 生命周期管理(生与死)

5.2.2 状态查询与交互(看与管)

点击图片可查看完整电子表格

5.2.3 文件与备份(存与取)

5.2.4 进阶操作(老司机必备)

这里需要补充辨析一下:

docker exec vs docker attach(面试常问)

  • docker exec (推荐):
  • 像是给房间新开了一扇后门进去。
  • 你进去做了什么,不会影响房间里原本正在干活的人。
  • 你退出(exit)时,房间里的人继续干活,容器不会停。
  • docker attach (不推荐):
  • 像是直接夺舍了房间里正在干活的那个人。
  • 你和它是同一个视线。
  • 你按 Ctrl+C 结束,那个人也就死了,容器会挂掉。

5.3 学会Docker注册中心的建立和使用

5.3.1 基于容器快速搭建本地Registry

|-----------------------------------------------------------------------------------------------------------------------------------------------------|
| Plain Text 1启动Registry容器 docker run -d -p 5000:5000 \ --restart=always \ --name myregistry \ -v /opt/data/registry:/var/lib/registry \ registry |

|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| * registry:这是Docker官方提供的"仓库服务"镜像,虚拟一个迷你版Docker Hub。 * -p 5000:5000:把一台机器的5000端口映射到容器内部的5000端口,以后的访问http://宿主机IP:5000就是在访问这个仓库。 * --restart=always:开机自动重启,避免服务器重启后仓库忘记启动。 * -v /opt/data/registry:/var/lib/registry:把镜像数据持久化到下一机/opt/data/registry,防止容器掉掉后仓库数据丢失。 |

|----------------------------------------------------------------|
| Plain Text 2验证注册表是否工作正常 curl http://127.0.0.1:5000/v2/_catalog |

|-----------------------------------------------------------------------------------------------------------------|
| * 如果是新建的仓库,返回:{"repositories":[]}表示当前还没有任何仓库。 * 稍后上传镜像后,这里会推出类似{"repositories":["hello-world"]}的内容 |

|-------------------------------------------------------------------------------------------------------------------------------------------|
| 127.0.0.1 什么? * 127.0.0.1是标准的Loopback地址,又叫localhost,永远指向"本机"。 * 无论你的主机真实IP是192.168.1.100还是10.0.0.5,访问127.0.0.1都表示"访问自己"。 |

5.3.2 向自建注册中心主动镜像

|------------------------------------------------------------------------------|
| Plain Text 1给镜像打标签(tag) docker tag hello-world 127.0.0.1:5000/hello-world:v1 |

|---------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 为什么要改名字? * Docker通过镜像中的另一项判断要推到哪一个仓库。 * hello-world→ 默认指向 Docker Hub。 * 127.0.0.1:5000/hello-world:v1→ 明确告诉 Docker:目标是本机 5000 端口上的Registry。 |

|-------------------------------------------------------------------|
| Plain Text 2自适应镜像(push) docker push 127.0.0.1:5000/hello-world:v1 |

|----------------------------------------|
| 第一个动作时,终端会显示分层上传的日志,最后出现的Pushed字样表示成功。 |

|------------------------------------------------------------|
| Plain Text 再次验证仓库内容 curl http://127.0.0.1:5000/v2/_catalog |

|------------------------------------------------------------------------------|
| * 现在应该看到:{"repositories":["hello-world"]},说明你的仓库仓库里已经有一个名为hello-world的仓库了。 |

5.3.3 从自建注册中心拉取镜像

在同一台机器上测试拉取(或者在交换机内的其他主机上,只需把IP换成本机IP):

|------------------------------------------------------|
| Plain Text docker pull 127.0.0.1:5000/hello-world:v1 |

|------------------------------------------------------------------------------------------------------|
| * 终端会显示Pulling from hello-world,并拉取成功。 * 说明您的本地Registry→push/pull整个仓库已经打通,可以作为后续企业仓库章节的基础示例 |

5.4 综合实战演练:从拉取到运行的全流程

这一节我们将通过一个真实的任务,把前面学到的命令全部串联起来。请打开你的终端,跟随以下 8 个步骤操作。

5.4.1 拉取镜像------进货

我们要运行一个Nginx网页服务器。首先,去Docker Hub进货。

狂欢

docker pull nginx:latest

  • 现象:屏幕会出现下载资料条,显示Pulling fs layer,最终显示Status: Downloaded newer image for nginx:latest。

5.4.2 显示本地的镜像列表------盘点库存

确认货还没到。

docker images

  • 预期结果:你应该能在列表中看到nginx,标签为latest。

5.4.3 查看镜像的建设历史 ------ 查验说明书

看看这个 Nginx 镜像是怎么做出来的。

docker history nginx:latest

  • 预期结果:你会看到很多行记录,每一行代表 Dockerfile 中的一个指令(如 CMD、EXPOSE、COPY),展示了分层构建的过程。

5.4.4 启动容器并让其以守护进程的形式在后台运行后台运行 ------ 开工生产

这是最关键的一步。我们要启动Nginx,让在后台匿名工作( -d),并将其80端口暴露出来。

docker run -d --name my-nginx -p 8080:80 nginx:latest

  • 命令解析:
  • -d:后台运行。
  • --name my-nginx:给容器起名叫my-nginx。
  • -p 8080:80:把电脑的8080端口映射到容器的80端口。
  • 验证:打开浏览器访问http://localhost:8080,你应该能看到"Welcome to nginx!" 的页面。

5.4.5 显示容器列表------查岗

看看刚才启动的容器状态不正常。

docker ps

  • 预期结果:看到一条记录,状态显示Up X seconds,说明它活得好好的。

5.4.6 获取容器的日志信息------听它说话

如果网页打不开,我们需要看日志排错。

docker logs my-nginx

  • 预期结果:你会看到 Nginx 的启动日志,或者刚才浏览器访问时留下的访问记录(Access Log)。

5.4.7 进入容器------进厂维修

假设我们修改 Nginx 的首页文字,需要钻容器进里。

狂欢

docker exec -it my-nginx /bin/bash

  • 现象:你的命令行提示符会变(通常变成root@容器ID:/#容器),说明你已经进入内部了。输入ls可以看到容器里的文件。输入exit退出。

5.4.8 删除集装箱------清理现场

任务结束,装载。

# 1. 先停止
docker stop my-nginx
# 2. 再删除
docker rm my-nginx

  • 注意:如果不先停止,直接rm会报错(否则-f加强制删除)。删除后,用docker ps -a确认集装箱已经消失。

恭喜!做完这8步,你已经掌握了Docker最核心的操作闭环。

相关推荐
苦逼IT运维2 小时前
VMware Horizon 与 Docker 冲突排错记录
linux·运维·docker·容器·自动化
小李独爱秋2 小时前
Linux操作系统实验报告单(13) 显示进程列表
linux·运维·服务器·操作系统·实验报告单
凸凹恼3 小时前
【每天一个小笔记】01 Docker 部署项目
笔记·docker
艾莉丝努力练剑3 小时前
Al Ping免费上新:GLM-4.7 && MiniMaxM2.1重磅上线,附独家使用教程
java·大数据·linux·运维·人工智能·python
莫渊博-天下无病3 小时前
node高版本安装
运维·node.js
人工智能训练3 小时前
Ubuntu 系统安装 VSCode 超全指南(3 种方法,适配 20.04/22.04 LTS)
linux·运维·服务器·vscode·ubuntu
facaixxx20243 小时前
GPU算力租赁:3080Ti、Tesla P40和RTX40服务器配置整理
运维·服务器·gpu算力
bing_feilong3 小时前
ubuntu网络命令详解
linux·运维·网络
木二_3 小时前
附056.Kubernetes_v1.34.3三节点集群-CentOS版
云原生·容器·kubernetes·centos·containerd·ingress·longhorn