Docker学习笔记

一、Docker镜像

1.1 核心定义

Docker 镜像 是一个只读的模板,它包含了运行一个应用程序所需的所有内容:代码、运行时环境、系统工具、系统库和设置。

1.2 关键特性与原理

1.2.1 分层存储(Layer)

这是 Docker 镜像最核心、最精妙的设计。

  • 只读层 :镜像由一系列只读层 叠加而成。每一层代表 Dockerfile 中的一条指令(例如:COPYRUNADD)。例如:

    • 第一层:基础操作系统(如 Ubuntu

    • 第二层:安装 Python

    • 第三层:复制项目代码 app.py

    • 第四层:设置环境变量

  • 联合文件系统 :当您启动一个容器时,Docker 会在所有只读层之上,添加一个可写的容器层。所有对运行中容器的修改(如写入日志、创建临时文件)都只发生在这个可写层。底层的镜像内容始终保持不变。

  • 好处

    • 高效存储 :多个镜像可以共享相同的基础层。例如,如果你有10个基于 Ubuntu 的镜像,你的硬盘上只存储一份 Ubuntu 基础层。

    • 快速分发:传输镜像时,只需要传输本地没有的层,大大加快了下载速度。

    • 可复用性:可以基于一个镜像轻松创建出新的、功能更丰富的镜像。

1.2.2 内容寻址存储

每个镜像和每一层都有一个基于其内容计算出的唯一加密哈希值(ID)。这保证了镜像内容的完整性和一致性。

1.3 镜像的生命周期与操作

1.3.1 创建镜像

  • 从 Registry 拉取 :最常用的是从 Docker 官方的公共仓库 Docker Hub 拉取。命令:docker search nginx(搜索镜像) docker pull nginx:latest(拉取镜像)

  • 使用 Dockerfile 。Dockerfile 是一个文本文件,里面包含了一条条构建镜像所需的指令。执行**docker build -t my-app:1.0 .** 命令,Docker 引擎会读取当前目录下的 Dockerfile 并逐步执行指令,最终生成一个新的镜像,镜像名为my-app,镜像标签为1.0。

  • 从文件载入 :可以将别人导出的镜像文件加载到本地。命令:docker load -i my_image.tar

  • 从容器提交 (不推荐用于生产):对一个运行中的容器进行修改后,可以将其提交为一个新镜像。命令:docker commit <container_id> my-new-image。这种方式不利于追溯和自动化,通常只用于临时调试。

1.3.2 查看与管理本地镜像

  • docker images:列出本地所有镜像。

  • docker rmi <image_id>:删除本地不需要的镜像。

  • docker image prune:清理未被使用的镜像(悬空镜像)。

1.3.3 分发与共享镜像

  • 推送至 Registry :可以将本地构建的镜像推送到 Docker Hub 或私有的镜像仓库(如 Harbor、GitLab Registry)。命令:docker push my-username/my-app:1.0

  • 导出为文件 :可以将镜像保存为一个 tar 归档文件,方便离线分享。命令:docker save -o my_image.tar my-app:1.0

二、Docker容器

2.1 核心定义

Docker容器Docker镜像的一个运行实例 。你可以把它理解为一个轻量级、隔离的进程沙箱,这个沙箱里运行着由镜像定义好的应用程序及其所有依赖。

2.2 关键特性与原理

2.2.1 从镜像到容器

当你执行 docker run nginx:latest 时,Docker引擎会:

  1. 检查本地是否存在 nginx:latest 镜像,若没有则从仓库拉取。

  2. 在镜像的只读层 之上,创建一个薄薄的可写层(容器层)。

  3. 分配一个唯一的容器ID,设置网络、存储等命名空间。

  4. 执行镜像中定义的启动命令(如 CMD ["nginx", "-g", "daemon off;"]),启动容器进程。

2.2.2 核心特性

  • 轻量级

容器直接共享宿主机的操作系统内核,无需像虚拟机(VM)一样模拟完整的操作系统,因此启动极快(秒级甚至毫秒级)、资源开销极小(只占用进程本身的内存和CPU)。

  • 隔离性
  • 通过 Linux 内核的 Namespaces 技术实现隔离。每个容器拥有独立的:

    • 进程空间(PID):容器内的进程ID从1开始,看不到宿主机或其他容器的进程。

    • 网络空间(Net):容器可以有自己独立的虚拟网卡、IP地址、端口空间。

    • 文件系统挂载点(Mnt) :容器看到的是自己的根目录 /

    • 用户和用户组(User):可以在容器内建立独立的用户体系。

  • 通过 cgroups 技术实现资源限制与核算,可以限制容器使用的CPU、内存、磁盘I/O等资源。

  • 可移植性(一致性环境)

容器内包含了应用运行所需的所有库和依赖,确保了 "一次构建,到处运行"。在开发机、测试环境、生产环境,只要使用同一个镜像启动容器,运行行为就是一致的。

  • 临时性(无状态/易失)

默认情况下,容器内的文件系统是临时的。容器的生命周期与其内部运行的进程一致,进程结束,容器就停止。对容器可写层的所有修改(如写入的数据、产生的日志),在容器删除后也会消失。这是理解容器存储的关键。

2.3 容器的生命周期与核心操作

容器的生命周期通常围绕以下几个核心命令和状态:

复制代码
创建(Create) -> 运行(Running) -> 暂停(Paused)/停止(Stopped) -> 删除(Removed)

2.3.1 创建容器

docker run [OPTIONS] IMAGE [COMMAND]最核心的命令。它会创建并启动一个新容器。常用选项:

  • -d:后台运行(守护态)。

  • -it:交互式运行,分配一个伪终端,通常与 /bin/bash 结合使用进入容器内部。

  • --name:为容器指定一个名字。

  • -p:端口映射(主机端口:容器端口)。

  • -v:挂载数据卷(主机目录:容器目录)。

2.3.2 管理容器

  • docker ps:查看正在运行 的容器列表。加 -a 查看所有容器(包括已停止的)。

  • docker stop <容器名/ID>:优雅地停止运行中的容器(发送 SIGTERM 信号)。

  • docker start <容器名/ID>:启动一个已停止的容器。

  • docker restart <容器名/ID>:重启容器。

  • docker pause/unpause <容器名/ID>:暂停/恢复容器内所有进程。

  • docker exec -it <容器名/ID> /bin/bash进入一个正在运行的容器内部执行命令,这是调试和排查问题的关键命令。

  • docker rm <容器名/ID>:删除一个已停止 的容器。加 -f 可以强制删除一个运行中的容器(不推荐)。

2.3.3 查看容器信息与日志

  • docker logs <容器名/ID>:查看容器的标准输出日志(即应用打印到控制台的信息)。加 -f 可以实时跟踪。

  • docker inspect <容器名/ID>:获取容器的底层详细信息(配置、状态、网络、数据卷等),以JSON格式返回。

  • docker stats:实时查看容器的资源使用情况(CPU、内存、网络IO等)。

2.4 容器数据持久化

由于容器的临时性,重要数据必须持久化存储,主要有两种方式:

2.4.1 数据卷(Volumes)

  • 由Docker管理、存在于宿主机文件系统(通常在 /var/lib/docker/volumes/ 下)的存储区域。

  • 生命周期独立于容器,即使容器被删除,数据卷依然保留。

  • 用法:docker run -v my_volume:/app/data nginx

2.4.2 绑定挂载(Bind Mounts)

  • 将宿主机上的一个指定目录或文件直接挂载到容器中。

  • 常用于开发环境,实现主机代码与容器代码的实时同步。

  • 用法:docker run -v /home/user/project:/app nginx

2.4.3 临时文件系统(tmpfs mount)

将数据存储在宿主机的内存中,速度极快,但容器停止即消失。用于存储非持久化的敏感数据或临时文件。

2.5 容器网络

Docker为容器提供了多种网络模式,实现容器间、容器与外部世界的通信:

bridge(桥接)默认模式 。容器连接到名为 docker0 的虚拟网桥,通过NAT与外部通信。同一桥接网络内的容器可以通过容器名互访。
host:容器直接使用宿主机的网络命名空间,没有隔离。性能最好,但端口冲突风险高。
none:容器没有网络接口,完全隔离。
用户自定义网络:可以创建更复杂的自定义网络,提供更好的容器发现和DNS解析功能。

三、VSCode Dev Container

Dev Container 的核心思想是:将你的开发环境(包括运行时、工具、依赖库、甚至编辑器配置)容器化,并放入一个 Docker 容器中运行。 而你本地的 VSCode 则作为"前端",通过该插件无缝连接到这个容器内部进行开发。简单来说,它让你在 Docker 容器里写代码,但体验和在本机一模一样。使用Dev Container需要包含两个文件:devcontainer.json和Dockerfile,通常我们设计项目结构如下:

your-project/

├── .devcontainer/

│ ├── devcontainer.json # 你提供的配置文件

│ └── Dockerfile # 容器镜像定义文件

├── src/ # 项目源代码

├── CMakeLists.txt # 项目构建文件

└── ... # 其他项目文件

需要准备的软件与插件:

  1. Visual Studio Code

  2. Docker Desktop(Windows)或 Docker Engine (Linux)

  3. VS Code扩展:Dev Containers(ms-vscode-remote.remote-containers)

3.1 核心功能与工作原理

3.1.1 一键构建开发环境

  • 你的项目根目录下包含一个配置文件(.devcontainer/devcontainer.json),里面定义了需要什么基础镜像、要安装哪些扩展、运行什么命令等。

  • 当你用 VSCode 打开这个项目时,插件会读取此配置,自动构建或启动一个 Docker 容器。

  • 你无需在本地安装 Python、Node.js、Java、数据库等任何与项目相关的运行时和工具。

3.1.2 无缝连接与集成

  • 容器启动后,VSCode 的整个核心进程(语言服务、调试器、终端等)都会运行在容器内部。

  • 你在 VSCode 里打开的终端,是容器内的终端;你运行的代码,使用的是容器内的环境;你安装的扩展,也可以指定安装在容器内部(与本地扩展隔离)。

  • 你的项目代码目录,会被"挂载"到容器内,因此文件编辑是双向同步的。

3.1.3 环境完全一致与隔离

  • 一致性:无论你是在 Windows、macOS 还是 Linux 上,只要安装了 Docker 和 VSCode,就能获得完全相同的开发环境。这对团队协作和新成员 onboarding 至关重要。

  • 隔离性:每个项目都可以有自己独立的、互不干扰的环境。项目A用 Python 3.8,项目B用 Python 3.11,完全不会冲突。

相关推荐
栈溢出了1 小时前
Redis 分片集群与哈希槽笔记
java·redis·笔记·spring
我命由我123451 小时前
复利极简理解
经验分享·笔记·学习·职场和发展·求职招聘·职场发展·学习方法
AOwhisky2 小时前
Python 学习笔记(第三期)——流程控制核心知识点自测与详解
开发语言·笔记·python·学习·云原生·运维开发·流程控制
tyqtyq222 小时前
药品说明书解读 —— AI 安全用药助手,鸿蒙原生应用深度解析
人工智能·学习·华为·生活·harmonyos
小心亦新3 小时前
STM32学习13 定时器1中断
stm32·嵌入式硬件·学习
我命由我123453 小时前
72 法则极简理解
经验分享·笔记·学习·职场和发展·求职招聘·职场发展·学习方法
qq_263_tohua4 小时前
第112期 CNN学习,不错的文章
学习
我想我不够好。4 小时前
满级的惩戒在范围
学习
LiaoWL1234 小时前
【SpringCloud合集-04】Sentinel 流量控制与熔断降级 学习笔记
学习·spring cloud·sentinel
xian_wwq5 小时前
【学习笔记】OpenAI 兼容 API 服务化:从协议到 LLM Gateway(19/35)
笔记·学习