当前位置:首页 > 技术 > 正文内容

Docker 镜像与容器的核心机制及实践

访客 技术 2026年7月11日 3

镜像:分层文件系统与可复用模板

Docker 镜像是容器运行的基础,其本质结合了"模板"和"纳戒"的特性。作为模板,镜像可以被快速复制、分发;而作为"纳戒",它依赖于 Union File System(联合文件系统) 实现多层目录的叠加挂载。每一层称为一个 layer,代表一次构建操作的增量变更。

在 Union FS 中,各层支持只读(readonly)、读写(readwrite)和写出(whiteout-able)权限,但 Docker 镜像的所有 layer 均为只读。当构建新镜像时,从基础操作系统开始逐层叠加修改,上层内容会覆盖下层同名文件,最终对外呈现为一个统一的完整文件系统视图。

镜像的优势与局限

  • 优势:
    • 环境一致性:屏蔽不同主机间的差异,实现"一次构建,处处运行"。
    • 分层存储:多个镜像可共享相同底层 layer,显著节省磁盘空间。
    • 高效传输:拉取镜像时仅下载缺失层级,提升部署速度。
  • 劣势:
    • 空间占用:每层依赖均需存储,累积增加磁盘消耗。
    • 性能损耗:访问文件需逐层查找,存在 I/O 开销。

常用镜像管理命令

# 删除指定镜像(若被容器使用则失败)
docker rmi nginx:latest

# 强制删除正在使用的镜像
docker rmi -f nginx:latest

# 将镜像导出为 tar 包(保留所有 layer)
docker save -o nginx_backup.tar nginx:1.25.0

# 从 tar 包加载镜像
docker load -i nginx_backup.tar

# 安静模式加载(不显示进度)
docker load -q -i nginx_backup.tar

# 查看镜像构建历史(每层指令)
docker history nginx:1.25.0 --no-trunc

# 清理无用的悬空镜像
docker image prune

# 删除所有未被容器引用的镜像
docker image prune -a

实战:镜像操作与离线迁移

# 搜索并拉取轻量级镜像
docker search busybox
docker pull busybox:1.36

# 给本地镜像添加标签并推送至仓库
docker tag busybox:1.36 myrepo/mybox:v1
docker push myrepo/mybox:v1

# 登录后查看凭证信息
cat ~/.docker/config.json

# 在无网络环境迁移镜像
# 主机A:导出镜像包
docker save -o app_image.tar myapp:latest

# 主机B:导入并运行
docker load -i app_image.tar
docker run -it myapp:latest sh

容器:镜像的可执行实例

容器是镜像的运行时实体,本质上是一个受隔离限制的进程。与静态的镜像不同,容器包含一个额外的可写层,用于保存运行期间的数据变更。尽管容器拥有独立的文件系统、网络和进程空间,但它仍运行在宿主机内核之上,不具备真正的硬件虚拟化能力。

容器生命周期状态

容器的状态流转包括:创建(created)→ 运行(running)→ 暂停(paused)→ 停止(stopped)→ 删除(deleted)。用户可通过命令控制其启停、重启或强制终止。

核心容器操作命令

# 创建但不启动容器
docker create --name web_srv -p 8080:80 nginx:1.25

# 启动已创建的容器
docker start web_srv

# 停止运行中的容器(发送 SIGTERM,超时后 SIGKILL)
docker stop web_srv

# 强制立即终止容器
docker kill web_srv

# 查看容器详细信息(含配置、挂载点等)
docker inspect web_srv

# 查看容器资源使用情况(CPU、内存、IO)
docker stats web_srv

# 实时跟踪日志输出
docker logs -f web_srv

# 查看最近 10 条日志
docker logs --tail 10 web_srv

容器交互方式

有两种主要方式进入容器内部进行调试:

  • docker attach:连接到正在运行的容器主进程。
    docker attach web_srv --sig-proxy=false
    使用 --sig-proxy=false 可避免 Ctrl+C 导致容器退出。
  • docker exec:在运行中容器内启动新进程(推荐用于调试)。
    docker exec -it web_srv bash
    docker exec -u www-data -w /var/www html cat index.html

容器与宿主机的数据交换

# 复制文件到容器
docker cp ./local_file.txt container_name:/tmp/

# 从容器复制文件到本地
docker cp container_name:/etc/hosts ./

# 导出容器文件系统为 tar 包(丢失元数据)
docker export -o container_fs.tar container_name

# 将 tar 包导入为新镜像(相比 save 更轻量但信息不全)
docker import container_fs.tar imported_img:v1

基于容器创建新镜像

通过 docker commit 可将运行中容器的改动固化为新的镜像 layer。

# 启动容器并修改内容
docker run -d --name modifiable_nginx nginx:1.25
docker exec modifiable_nginx sh -c "echo 'Custom Page' > /usr/share/nginx/html/index.html"

# 提交变更生成新镜像
docker commit \
  -a "Author <author@example.com>" \
  -m "Updated homepage" \
  -c 'CMD ["nginx", "-g", "daemon off;"]' \
  modifiable_nginx custom_nginx:v2

# 验证新镜像功能
docker run -d --name test_v2 -p 8090:80 custom_nginx:v2
curl http://localhost:8090

资源限制与动态调整

可通过以下命令对运行中容器施加资源约束:

# 查看当前资源占用
docker stats modifiable_nginx

# 动态设置内存上限(物理 + swap)
docker update --memory 300m --memory-swap 300m modifiable_nginx

# 限制 CPU 使用配额(如:每 100ms 最多使用 50ms)
docker update --cpu-period 100000 --cpu-quota 50000 modifiable_nginx

典型应用场景示例

1. 部署 MySQL 服务

docker run -d \
  --name mysql_db \
  -e MYSQL_ROOT_PASSWORD=secure_password \
  -p 3306:3306 \
  mysql:5.7

# 进入容器执行 SQL
docker exec -it mysql_db mysql -uroot -p

2. 运行 Redis 缓存

docker run -d \
  --name redis_cache \
  -p 6379:6379 \
  redis:7

# 测试数据读写
docker exec -it redis_cache redis-cli
> SET counter 100
> GET counter

3. 托管 Java 应用

# 准备 jar 包
mkdir -p /opt/app && cp app.jar /opt/app/

# 启动基础容器
docker run -it --name java_app -p 8080:8080 ubuntu:22.04 bash

# 容器内安装 JDK 并运行应用
apt update && apt install openjdk-8-jdk -y
java -jar /app.jar

4. 自动重启策略

# 设置容器异常退出后自动重启
docker run -d \
  --name resilient_app \
  --restart unless-stopped \
  nginx:1.25

支持策略:no(默认)、on-failure[:max-retries]alwaysunless-stopped

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。