深入解析Docker:核心架构与最佳实践
文章目录
- 前言
- 一、Docker 解决了什么问题?
- 二、Docker 底层核心架构
- 2.1 Docker 引擎的分层架构
- 2.2 镜像的奥秘:联合文件系统(UnionFS)
- 2.3 容器隔离的核心技术
- 2.3.1 命名空间
- 2.3.2 控制组(Cgroups)
- 2.3.3 内核能力(Capabilities)
- 2.4 Docker 网络模型
- 三、Docker 使用指南
- 3.1 安装与配置
- 3.2 Dockerfile 最佳实践
- 3.3 容器数据管理
- 3.4 容器网络高级配置
- 四、Docker 的演进与未来趋势
- 总结
前言
Docker 的诞生彻底改变了软件开发和部署的方式,其核心思想是“一次构建,随处运行”。它不仅解决了环境不一致的难题,还通过轻量级的容器化技术提升了资源利用率和运维效率。本文将深入剖析 Docker 的底层架构、核心原理、使用场景,并结合实际案例给出最佳实践。
一、Docker 解决了什么问题?
1. 环境不一致:开发、测试、生产环境的“水土不服”。
在传统软件开发中,开发人员在本地编写代码,测试人员在测试环境验证,最终部署到生产环境。然而,这三个环境的差异(如操作系统版本、依赖库、配置文件等)常常导致一个致命问题:“代码在我机器上能跑,为什么上线就崩溃?”
举一个场景例子,开发者在本地使用 Ubuntu 20.04 和 Python 3.8,但生产环境是 CentOS 7 和 Python 3.6。当代码依赖 Python 3.8 的特性时,生产环境运行直接报错。而Docker通过 镜像 将应用及其依赖(代码、运行时、系统工具、配置文件)打包成一个标准化单元。镜像可以在任何安装了 Docker 的环境中运行,彻底消除环境差异。
2. 资源浪费:虚拟机的“笨重”与容器的“轻便”
在 Docker 之前,虚拟机(VM)是隔离环境的主流技术。但虚拟机需要模拟完整的硬件和操作系统,导致严重的资源浪费:
虚拟机的问题:
- 每个 VM 需安装完整的操作系统(如 10GB 的 Ubuntu),占用大量磁盘和内存。
- 启动时间长达几分钟,无法快速扩展。
- 同一物理机上运行多个 VM 时,资源利用率低。
针对这些问题,Docker做的改进包括容器共享宿主机的操作系统内核,无需重复加载内核和系统库,并且容器本质是进程,启动时间仅需毫秒级,资源占用极低。
3. 依赖冲突:多个应用“打架”的难题
在一台服务器上部署多个应用时,不同应用可能依赖同一软件的不同版本(如 Python 2.7 和 Python 3.0),导致 依赖冲突。传统解决方案是为每个应用分配独立虚拟机,但这进一步加剧资源浪费。Docker 的隔离机制是通过命名空间和隔离组来完成的。
命名空间:
每个容器拥有独立的进程树、网络接口、文件系统挂载点。
容器内的进程无法看到其他容器或宿主机的进程。
控制组:
限制容器使用的 CPU、内存、磁盘 IO,避免单个容器耗尽资源。
4. 部署效率:从“手动运维”到“一键发布”
传统部署流程需要手动安装依赖、配置环境、调试兼容性,耗时且容易出错。Docker 通过镜像仓库或者声明式部署(通过 docker-compose.yml 或 Kubernetes 配置文件定义服务依赖、网络、存储,实现一键部署。)的方式实现自动化部署。
在微服务场景下通常使用Docker 结合编排工具可实现快速部署与弹性伸缩。
二、Docker 底层核心架构
2.1 Docker 引擎的分层架构
Docker 引擎是一个复杂的系统,通过 职责分离 和 标准化接口 实现了高扩展性和稳定性:
- Docker Client:用户通过 CLI 或 API 与 Docker Daemon 交互。
- Docker Daemon:核心后台进程,接收并处理请求(如构建镜像、启动容器)。
- containerd:专注于容器生命周期管理(创建、启动、停止、删除),向上提供 gRPC 接口。
- runc:符合 OCI(开放容器倡议)标准的轻量级容器运行时,直接调用 Linux 内核功能。
组件间通信协议
Docker Client ↔ Daemon:HTTP REST API(默认通过 UNIX socket)。
Daemon ↔ containerd:gRPC 协议(高性能二进制通信)。
containerd ↔ runc:JSON 配置文件 + 命令行调用。
docker info # 显示 Docker 系统信息
ctr containers ls # containerd 命令行工具
runc list # 列出所有通过 runc 运行的容器
2.2 镜像的奥秘:联合文件系统(UnionFS)
联合文件系统(UnionFS)是 Docker 镜像和容器的核心存储技术,它通过创新的分层和堆叠机制,实现了镜像的轻量化、高效存储和快速启动。
核心概念: 联合文件系统是一种将多个目录(称为"层")透明叠加为单一视图的文件系统。而我们的Docker 镜像就是由多个只读层(Layer) 叠加组成,每个层对应文件系统的部分内容(如基础系统、依赖库、应用代码)。
当容器启动时,在镜像层顶部添加 可读写层(Upperdir),形成用户视图的完整文件系统。
关键特性:
- 写时复制:修改文件时复制到可写层,原始层保持不变。
- 分层存储:只读层(镜像) + 可写层(容器)组合成最终文件系统。
Merged(用户视图)
├── Upperdir(容器可读写层)
└── Lowerdir(镜像只读层) ├── Layer N(应用层) ├── ... └── Base Layer(基础镜像,如 Ubuntu)
读写操作规则:
读操作:
优先从 Upperdir 查找文件,若未找到则逐层向下搜索 Lowerdir,无额外开销。
写操作:
写时复制:若修改 Lowerdir 中的文件,会先将文件复制到 Upperdir 再进行修改,原始镜像层保持不变,首次修改有复制延迟。
新增文件:直接写入 Upperdir,性能很快。
删除文件:在 Upperdir 中标记文件为删除以隐藏 Lowerdir 中的原始文件。
写时复制(CoW)示例:
场景:容器修改 /etc/hosts(原属镜像层)
步骤:
- 从镜像层复制 hosts 文件到 UpperDir
- 在 UpperDir 中修改文件
- MergedDir 视图显示修改后的文件
总结: UnionFS 的设计思想
不可变基础设施:镜像层只读保证一致性
空间效率:共享相同基础层节省存储
快速部署:基于已有层快速启动容器
安全隔离:容器修改不影响镜像和其他容器
2.3 容器隔离的核心技术
Docker 容器的隔离能力主要依赖 Linux 内核的三大核心技术:命名空间、控制组和 内核能力,配合安全模块实现完整的运行时隔离。
2.3.1 命名空间
命名空间是 Linux 内核提供的资源隔离机制,为容器创建独立的系统视图,实现以下 7 种关键隔离:
命名空间类型 | 隔离内容 | Docker 应用场景 | 操作示例 |
---|---|---|---|
PID | 进程 ID 空间 | 容器内只能看到自己的进程 | docker exec 进入容器后 ps aux 仅显示容器内进程 |
Network | 网络设备、IP、端口、路由表 | 每个容器拥有独立 IP 和端口 | docker run --net=bridge 创建独立网络栈 |
Mount | 文件系统挂载点 | 容器无法访问宿主机的挂载目录 | docker run -v /data 仅挂载指定目录 |
UTS | 主机名和域名 | 容器可自定义主机名 | docker run --hostname=mycontainer |
IPC | 进程间通信(消息队列等) | 阻止容器间通过共享内存通信 | 默认启用,无需额外配置 |
User | 用户和用户组 ID 映射 | 容器内 root 不等于宿主机 root | docker run --user=1000 指定非特权用户 |
Cgroup | 控制组视图(Linux 4.6+) | 限制容器资源使用 | 与 Cgroups 协同工作 |
实现原理: 通过 clone() 系统调用创建新命名空间:
// 创建新进程并同时赋予多个命名空间
clone(child_func, stack, CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWNET, arg);
验证命令:
# 查看容器的命名空间信息
docker inspect --format '{{.State.Pid}}' <container_id> # 获取容器主进程PID
ls -l /proc/<PID>/ns # 查看该进程所属的所有命名空间
2.3.2 控制组(Cgroups)
Cgroups 是 Linux 内核的资源配额机制,用于限制、统计和隔离进程组的资源使用。
核心子系统:
子系统 | 功能 | Docker 参数示例 |
---|---|---|
cpu | 分配 CPU 时间片 | –cpus=1.5 |
cpuacct | 统计 CPU 使用情况 | 自动启用 |
memory | 限制内存和 Swap 使用 | –memory=500m --memory-swap=1g |
blkio | 限制块设备 I/O 带宽 | –device-read-bps=/dev/sda:1mb |
devices | 控制设备访问权限 | –device=/dev/sda:/dev/sda:rw |
freezer | 暂停/恢复容器进程 | docker pause 底层实现 |
Docker 资源限制示例:
# 启动一个受限容器
docker run -it \--cpus=2 \ # 最多使用 2 核 CPU--memory=1g \ # 内存限制 1GB--blkio-weight=500 \ # 磁盘 IO 相对权重--device-write-iops=/dev/nvme0n1:1000 \ # 限制写入 IOPSalpine
Cgroups 文件系统操作:
# 手动查看容器的 Cgroups 配置
cat /sys/fs/cgroup/memory/docker/<container_id>/memory.limit_in_bytes
2.3.3 内核能力(Capabilities)
Linux 内核能力(Capabilities)是一种细粒度的权限控制机制,将传统 root 用户的超级权限拆分为多个独立权限单元,以提升容器安全性,Linux 的 POSIX 能力模型将 root 权限细分为 40+ 种独立能力,Docker 默认仅保留必要权限。
Docker 能力管理实践:
查看容器默认能力:
# 启动容器并查看进程能力
docker run -it --rm alpine sh -c 'apk add libcap && capsh --print'
输出(默认保留约 14 项能力):
Current: = cap_chown,cap_dac_override,...+ep
自定义能力配置
# 运行容器时调整能力
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE nginx # 只保留绑定低端口权限# 完全禁用特权模式(避免容器获得宿主机 root 权限)
docker run --privileged=false ...
关键能力配置:
CAP_NET_ADMIN:网络配置(如修改路由),默认移除
CAP_SYS_MODULE:加载内核模块,默认移除
CAP_SYS_ADMIN:广泛系统管理权限,默认部分限制(如挂载文件系统)
CAP_DAC_OVERRIDE:绕过文件权限检查,默认移除
2.4 Docker 网络模型
默认网络模式:
bridge:容器通过虚拟网桥(docker0)连接,分配私有 IP。
host:容器直接使用宿主机网络栈,性能高但牺牲隔离性。
none:无网络连接,适用于特殊场景。
自定义:
# 创建自定义网络
docker network create --driver=bridge --subnet=172.18.0.0/16 mynet# 运行容器并加入网络
docker run --net=mynet --ip=172.18.0.2 nginx
三、Docker 使用指南
3.1 安装与配置
Linux安装:
sudo apt-get update
sudo apt-get install docker.io
sudo systemctl enable --now docker
配置镜像加速:
受国内网络政策影响,Docker 官方镜像源(hub.docker.com)及部分国内镜像站访问受限,以下为综合实践方案(修改 /etc/docker/daemon.json):
{ "registry-mirrors": [ "https://docker.m.daocloud.io", "https://docker-0.unseo.tech", "https://docker.1ms.run", "https://docker.hlmirror.com" ]
}
然后执行命令:
systemctl daemon-reload
systemctl restart docker
当然还有第三方镜像加速方案,比如阿里云、天翼云等,这里不赘述了。
3.2 Dockerfile 最佳实践
Dockerfile 是一个纯文本文件,包含一系列用于自动化构建 Docker 镜像的指令。它本质上是镜像的“源代码”,通过逐行解释指令来定义镜像的组成和行为。
减少镜像层数:
# 反例:产生多个临时层
RUN apt-get update
RUN apt-get install -y curl
RUN rm -rf /var/lib/apt/lists/*# 正例:单层完成所有操作
RUN apt-get update && \apt-get install -y curl && \rm -rf /var/lib/apt/lists/*
使用多阶段构建:
# 阶段1:构建环境
FROM golang:1.19 AS builder
WORKDIR /app
COPY . .
RUN go build -o app .# 阶段2:运行环境
FROM alpine:3.16
COPY --from=builder /app/app /usr/local/bin/
CMD ["app"]
安全加固:
FROM alpine
RUN adduser -D appuser && \chown -R appuser /app
USER appuser # 禁止以 root 运行
利用构建缓存:
- 将高频变动的指令(如 COPY)放在文件尾部
- 固定版本号避免缓存失效:FROM ubuntu:22.04 而非 FROM ubuntu:latest
完整示例(构建 Python 应用镜像):
# 使用官方轻量级基础镜像
FROM python:3.9-slim# 设置元数据
LABEL maintainer="dev@example.com"# 安装系统依赖
RUN apt-get update && \apt-get install -y --no-install-recommends gcc && \rm -rf /var/lib/apt/lists/*# 配置工作目录
WORKDIR /app
COPY requirements.txt .# 安装Python依赖
RUN pip install --no-cache-dir -r requirements.txt# 复制应用代码
COPY . .# 声明环境变量
ENV FLASK_APP=app.py
ENV FLASK_ENV=production# 暴露端口
EXPOSE 5000# 健康检查
HEALTHCHECK --interval=30s --timeout=3s \CMD curl -f http://localhost:5000/health || exit 1# 启动命令
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "app:app"]
3.3 容器数据管理
Volume(数据卷):持久化存储,绕过容器层直接读写宿主机目录。
# 创建数据卷
docker volume create mysql_data# 挂载数据卷
docker run -v mysql_data:/var/lib/mysql mysql
Bind Mount:直接挂载宿主机目录到容器。
docker run -v /host/path:/container/path nginx
3.4 容器网络高级配置
跨容器通信:
# 创建网络
docker network create app_network# 启动服务并加入网络
docker run -d --net=app_network --name=redis redis
docker run -d --net=app_network --name=app myapp
暴露端口:
docker run -p 8080:80 nginx # 宿主机 8080 → 容器 80
四、Docker 的演进与未来趋势
Kubernetes 整合: 大多数的企业采用 Docker 与 Kubernetes 协同方案,实现容器调度、自愈与弹性伸缩的自动化。
容器原生云平台发展: 云服务商(如阿里云、腾讯云)推出集成 Docker 的容器原生服务,实现一键式容器集群管理与多云互联)。
Serverless 集成: Docker 容器作为函数计算(如 AWS Lambda)的底层运行时,支撑事件驱动型架构的快速扩展。
总结
Docker 不仅是一项技术,更是一种开发范式的革新。通过深入理解其底层原理(如 Namespaces、Cgroups、UnionFS),结合最佳实践(镜像优化、安全加固),开发者可以构建高效、稳定、安全的容器化应用。随着云原生技术的演进,Docker 将继续在微服务、Serverless 等领域发挥关键作用。
相关文章:

深入解析Docker:核心架构与最佳实践
文章目录 前言一、Docker 解决了什么问题?二、Docker 底层核心架构2.1 Docker 引擎的分层架构2.2 镜像的奥秘:联合文件系统(UnionFS)2.3 容器隔离的核心技术2.3.1 命名空间2.3.2 控制组(Cgroups)2.3.3 内核…...
HVV面试题汇总合集
应急响应的命令 Linux ps -aux 查看进程 netstat -antlp 查看端口 top查看 cpu使用情况 Windows tasklist 查看进程 netstat -an 查看端口struts2原理特征 原理: 045:默认的content-type解析器会把用户传来的数据直接当成代码执行,造成rce 特征:ognl表达式&…...
什么是深度神经网络
深度神经网络(DNN)详细介绍 1. 定义与核心原理 深度神经网络(Deep Neural Network, DNN)是一种具有多个隐藏层的人工神经网络模型,其核心在于通过层次化的非线性变换逐步提取输入数据的高层次抽象特征。与浅层神经网络相比,DNN的隐藏层数量通常超过三层,例如VGGNet、R…...
Node.js 24.0 正式发布:性能跃升与开发体验全面升级
Node.js v24.0.0 震撼发布!V8 13.6、npm 11、权限模型稳定化等重磅更新 2025年5月6日 —— Node.js 社区迎来重大里程碑!Node.js v24.0.0 正式发布,带来一系列激动人心的新特性、性能优化和 API 改进。本次更新涵盖 V8 JavaScript 引擎升级至…...
Linux/AndroidOS中进程间的通信线程间的同步 - 信号量
1 概述 本文将介绍 POSIX 信号量,它允许进程和线程同步对共享资源的访问。有两种类型的 POSIX 信号量: 命名信号量:这种信号量拥有一个名字。通过使用相同的名字调用 sem_open(),不相关的进程能够访问同一个信号量。未命名信号量…...
Python Cookbook-7.10 在 MySQL 数据库中储存 BLOB
任务 想把一个二进制的大对象(BLOB)存入MySQL数据库 解决方案 MySQLdb 模块并不支持完整的占位符,不过可以使用模块的escape_string 函数来解决: import MySQLdb,cPickle #连接到数据库,用你的本机来测试数据库,并获得游标 connection = MySQLdb.connect(db = "tes…...

Edge浏览器PDF字体显示错误
Edge浏览器PDF字体显示错误 软件版本信息 Edge Version: 136.0.3240.50 Word Version: Microsoft Office 专业增强版2021问题描述 在Word中使用多级列表自动编号, 并使用Word软件自带的导出为PDF文件功能, 在Word中显示正常的数字, 在Edge中查看PDF将会出现渲染错误的现象,…...
计算机网络与多线程同步机制详解
一、IP地址与子网划分 在互联网世界中,IP地址就像是每个设备的"门牌号",它使得数据包能够准确送达目的地。IP地址的划分与管理就像城市的规划,通过合理的子网划分,能够高效地管理网络资源。 子网掩码的工作原理 子网…...

Python训练营打卡——DAY22(2025.5.11)
复习日 学习参考如何使用kaggle平台,写下使用注意点,并对下述比赛提交代码 泰坦尼克号——来自灾难的机器学习 数据来源: kaggle泰坦里克号人员生还预测 挑战 泰坦尼克号沉没是历史上最臭名昭著的海难之一。 1912年4月15日,在被普…...

实战项目4(05)
目录 任务场景一 【sw1配置】 任务场景二 【sw1配置】 【sw2配置】 任务场景一 按照下图完成网络拓扑搭建和配置 任务要求: 1、在交换机SW1的E0/0/1端口进行设置,实现允许最多两个电脑可以正常进行通信。 2、在交换机SW1的E0/0/2端口进行设置&…...
快速上手Pytorch Lighting框架 | 深度学习入门
快速上手Pytorch Lighting框架 | 深度学习入门 前言参考官方文档 介绍快速上手基本流程常用接口LightningModule\_\_init\_\_ & setup()\*\_step()configure_callbacks()configure_optimizers()load_from_checkpoint Trainer常用参数 可选接口LoggersTensorBoard Logger Ca…...

C++学习之STL学习
在经过前面的简单的C入门语法的学习后,我们开始接触C最重要的组成部分之一:STL 目录 STL的介绍 什么是STL STL的历史 UTF-8编码原理(了解) UTF-8编码原理 核心编码规则 规则解析 编码步骤示例 1. 确定码点范围 2. 转换为…...

3. 仓颉 CEF 库封装
文章目录 1. capi 使用说明2. Cangjie CEF2. 1实现目标 3. 实现示例 1. capi 使用说明 根据上一节 https://blog.csdn.net/qq_51355375/article/details/147880718?spm1011.2415.3001.5331 所述, cefcapi 是libcef 共享库导出一个 C API, 而以源代码形式分发的 li…...

LabVIEW多通道并行数据存储系统
在工业自动化监测、航空航天测试、生物医学信号采集等领域,常常需要对多个传感器通道的数据进行同步采集,并根据后续分析需求以不同采样率保存特定通道组合。传统单线程数据存储方案难以满足实时性和资源利用效率的要求,因此设计一个高效的多…...

谷歌在即将举行的I/O大会之前,意外泄露了其全新设计语言“Material 3 Expressive”的细节
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...

十三、基于大模型的在线搜索平台——整合function calling流程
基于大模型的在线搜索平台——整合function calling流程 一、function calling调用总结 上篇文章已经实现了信息抓取能力,并封装成了函数。现在最后一步将能力转换为大模型可以调用的能力,实现搜索功能就可以了。这篇主要实现大模型的function calling能…...

力扣70题解
记录 2025.5.8 题目: 思路: 1.初始化:p 和 q 初始化为 0,表示到达第 0 级和第 1 级前的方法数。r 初始化为 1,表示到达第 1 级台阶有 1 种方法。 2.循环迭代:从第 1 级到第 n 级台阶进行迭代: p 更新为前…...

电商双11美妆数据分析
1、初步了解 2.2 缺失值处理 通过上面观察数据发现sale_count,comment_count 存在缺失值,先观察存在缺失值的行的基本情况 2.3 数据挖掘寻找新的特征 给出各个关键词的分类类别 由title新生成两列类别 对是否是男性专用进行分析并新增一列 对每个产品总销量新增销售额这一列...
Python爬虫实战:研究nodejs aes加密
1. 引言 1.1 研究背景与意义 在当今数字化时代,Web 数据的价值日益凸显。通过爬虫技术获取公开数据并进行分析,能够为企业决策、学术研究等提供有力支持。然而,为了保护数据安全和隐私,许多网站采用了加密技术对数据进行保护,其中 AES 加密是一种常见且安全的加密算法。…...

24、TypeScript:预言家之书——React 19 类型系统
一、预言家的本质 "TypeScript是魔法世界的预言家之书,用静态类型编织代码的命运轨迹!" 霍格沃茨符文研究院的巫师挥动魔杖,类型注解与泛型的星轨在空中交织成防护矩阵。 ——基于《国际魔法联合会》第12号类型协议,Ty…...

第8章-1 查询性能优化-优化数据访问
上一篇:《第7章-3 维护索引和表》 在前面的章节中,我们介绍了如何设计最优的库表结构、如何建立最好的索引,这些对于提高性能来说是必不可少的。但这些还不够——还需要合理地设计查询。如果查询写得很糟糕,即使库表结构再合理、索…...

PCL点云按指定方向进行聚类(指定类的宽度)
需指定方向和类的宽度。测试代码如下: #include <iostream> #include <fstream> #include <vector> #include <string> #include <pcl/point_types.h> #include <pcl/point_cloud.h> #include <pcl/visualization/pcl_visu…...
复现nn-Unet模型 实验报告
目的是将 nn-Unet 模型应用到切割脑出血CT图像上 论文学习步骤为 1.学习Unet,Unet等模型作为复现nn-Unet模型的基础。 2.学习nn-Unet原论文,掌握nn-Unet的结构。 3.学习将nn-Unet模型应用到切割脑出血CT医学图像的相关论文。 这周学习了Unet&#x…...

C#对SQLServer增删改查
1.创建数据库 2.SqlServerHelper using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Data; using System.Linq; using System.Text; using System.Threading.Tasks;namespace WindowsFormsApp1 {internal class SqlServerHelper{//…...

模拟太阳系(C#编写的maui跨平台项目源码)
源码下载地址:https://download.csdn.net/download/wgxds/90789056 本资源为用C#编写的maui跨平台项目源码,使用Visual Studio 2022开发环境,基于.net8.0框架,生成的程序为“模拟太阳系运行”。经测试,生成的程序可运行…...

蓝桥杯14届 数三角
问题描述 小明在二维坐标系中放置了 n 个点,他想在其中选出一个包含三个点的子集,这三个点能组成三角形。然而这样的方案太多了,他决定只选择那些可以组成等腰三角形的方案。请帮他计算出一共有多少种选法可以组成等腰三角形? 输…...
redis sentinel和redis cluster的主从切换选举过程
引言 redis sentinel和redis cluster的主从切换选举过程不同,本文将从选举机制、核心差异对比两者的不同。 一、Redis Sentinel的选举机制 监控与故障判定 Sentinel集群通过心跳检测(每秒一次PING)监控主节点状态: 主观下线&…...
C++自学笔记 makefile
本博客参考南科大于仕琪教授的讲解视频和这位同学的学习笔记: 参考博客 感谢两位的分享。 makefile 的作用 用于组织大型项目的编译,是一个一键编译项目的脚本文件。 本博客通过四个版本的makefile逐步说明makefile的使用 使用说明 四个演示文件 …...
前端密码加密:保护用户数据的第一道防线
引言 在当今互联网时代,用户数据安全至关重要,而密码作为用户身份验证的核心凭证,其安全性更是重中之重。传统的前端开发中,密码常常以明文形式传输到服务器,这带来了严重的安全隐患。本文将深入探讨前端密码加密的必…...

HTML12:文本框和单选框
表单元素格式 属性说明type指定元素的类型。text、password、 checkbox、 radio、submit、reset、file、hidden、image 和button,默认为textname指定表单元素的名称value元素的初始值。type为radio时必须指定一个值size指定表单元素的初始宽度。当type为text 或pas…...