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,完全不会冲突。

相关推荐
可可苏饼干39 分钟前
MySQL 索引
运维·数据库·学习·mysql
盐焗西兰花41 分钟前
鸿蒙学习实战之路 - 轮播图组件实现
学习·华为·harmonyos
Lovely Ruby42 分钟前
前端er Go-Frame 的学习笔记:实现 to-do 功能(一)
前端·学习·golang
crary,记忆1 小时前
Angular.json中的commonChunk 的作用
前端·javascript·学习·angular.js
洛可可白1 小时前
Ubuntu 上安装 Docker
linux·ubuntu·docker
试着1 小时前
【投资学习】腾讯
人工智能·学习·业界资讯
摇滚侠1 小时前
零基础小白自学 Git_Github 教程,Git 命令行操作3,笔记20
笔记·git·github
墨小羽ovo1 小时前
EtherCAT入门之旅(学习笔记)
笔记·stm32·学习·ethercat协议
车载测试工程师1 小时前
CAPL学习-ETH功能函数-方法类1
网络协议·学习·以太网·capl·canoe