云原生学习笔记(五) 构建 Docker 镜像与运行容器

第八篇:构建 Docker 镜像的艺术:从 Dockerfile 到多阶段构建

参考文档:


一、镜像是由哪些"层"组成的?

Docker 镜像并非单一文件,而是由多层(Layer)组成的只读文件系统叠加而成。

🧱 每一层来源:

  • 镜像层 = Dockerfile 中每条指令(如 RUN, COPY, ADD)创建一层
  • 底层基础镜像层 + 应用构建层 + 配置层

🔁 层的优点:

  • 缓存重用:只变更发生的层重新构建,提高构建速度
  • 共享优化:多个镜像可共享相同层,节省空间
  • 版本控制友好:变更可追踪与回滚

二、编写 Dockerfile 的最佳实践

Dockerfile 是构建镜像的"配方脚本",描述从哪开始、执行什么命令、如何构建运行环境。

🛠 Dockerfile 基本结构:

dockerfile 复制代码
# 指定基础镜像
FROM python:3.12-slim

# 设置工作目录
WORKDIR /app

# 拷贝文件
COPY requirements.txt .

# 安装依赖
RUN pip install -r requirements.txt

# 拷贝源代码
COPY . .

# 定义容器启动命令
CMD ["python", "app.py"]

✅ 常用指令说明:

指令 作用
FROM 基础镜像
RUN 执行命令并创建新镜像层
COPY 拷贝本地文件至镜像内
WORKDIR 设置默认工作目录
CMD 默认启动命令
ENV 设置环境变量
EXPOSE 声明开放的端口(文档提示)

🧼 编写建议:

  • 合并多个 RUN 命令为一条,减少层数
  • 明确 .dockerignore 文件排除无关文件(如 .git/, node_modules/

三、构建、标记和推送镜像的流程

🔧 构建镜像:

bash 复制代码
docker build -t myapp:1.0 .
  • -t:指定镜像名称和标签(tag)
  • .:当前目录为构建上下文

🏷 为镜像打标签:

bash 复制代码
docker tag myapp:1.0 myregistry.example.com/myapp:1.0

☁️ 推送到远程仓库:

bash 复制代码
docker push myregistry.example.com/myapp:1.0

确保已使用 docker login 登录仓库。


四、构建缓存机制的使用

构建缓存能大幅提升镜像构建效率,但也需注意顺序与变更影响。

🚀 缓存命中规则:

  • Docker 会按顺序逐条执行指令
  • 当前指令和其上下文(依赖的文件)没有变化时,则命中缓存

🔥 示例:

dockerfile 复制代码
COPY requirements.txt .
RUN pip install -r requirements.txt  # ✅ 如果 requirements 没变则可用缓存
COPY . .                             # ❌ 若这里提前 COPY,会导致前面的 RUN 缓存失效

✅ 优化建议:

  • 把稳定的文件(如依赖)提到前面
  • 利用 --target 分阶段构建调试
  • 修改频繁的代码层尽量靠后

五、多阶段构建:减小镜像体积的利器

"构建时用大镜像,运行时只带最小必需组件"

🎯 使用场景:

  • 项目依赖大量构建工具(如 Java, Go, C++ 项目)
  • 最终镜像希望精简(无 Node、无 Maven)

🏗 示例:Go 应用的多阶段构建

dockerfile 复制代码
# 第一阶段:构建阶段
FROM golang:1.22 as builder
WORKDIR /app
COPY . .
RUN go build -o myapp

# 第二阶段:运行阶段
FROM alpine:latest
COPY --from=builder /app/myapp /myapp
ENTRYPOINT ["/myapp"]

🎉 优点:

  • 最终镜像干净、体积小
  • 减少安全风险面(无编译器、构建工具残留)
  • 更适合生产环境部署

六、总结与建议

概念/操作 说明
镜像层 多层组成,支持缓存与共享
Dockerfile 镜像构建蓝图,合理组织命令可加速构建
镜像标签 有助于版本管理与部署识别
构建缓存 避免重复构建,提高构建效率
多阶段构建 精简镜像,提升安全性与部署效率

第九篇:运行容器的实战技巧:网络、数据卷与多容器协作

参考文档:


一、容器端口映射:让服务暴露给外部访问

容器内部的服务默认无法被主机直接访问,需通过 端口映射 将其公开。

🔌 示例:

bash 复制代码
docker run -d -p 8080:80 nginx
  • -p <宿主端口>:<容器端口>
  • 访问 http://localhost:8080 即可访问容器内 nginx 的 80 端口

🌐 支持多端口、多容器绑定:

bash 复制代码
docker run -p 5000:5000 myapp
docker run -p 3306:3306 mysql

二、自定义容器默认启动命令

镜像中通常会设置默认启动命令(CMD),但可在运行时覆盖。

🛠 使用命令行覆盖:

bash 复制代码
docker run ubuntu echo "Hello from container"

即使镜像默认执行 bash,此处也会覆盖为 echo

🧩 ENTRYPOINT 与 CMD 区别:

指令类型 特点
CMD 可被 docker run 参数覆盖
ENTRYPOINT 固定命令,后接参数不影响本体

三、数据持久化:容器生命周期外保存数据

容器删除时,其内部数据也会丢失。为实现持久化,可使用:

✅ Docker 卷(Volume):

bash 复制代码
docker volume create mydata
docker run -v mydata:/data myapp
  • 卷位于 Docker 管理目录下,不随容器删除
  • 支持多个容器共享

🗂 绑定主机目录:

bash 复制代码
docker run -v /host/path:/container/path myapp
  • 直接映射宿主机文件夹
  • 可用于调试、本地开发

四、共享本地文件与挂载策略

将本地代码、配置等文件共享给容器使用,适用于开发测试场景。

📁 示例:

bash 复制代码
docker run -v $(pwd):/usr/src/app myapp
  • 主机当前目录(代码)映射到容器工作目录
  • 每次本地代码修改容器可实时读取

📎 挂载模式说明:

模式 说明
读写(默认) -v src:dest
只读 -v src:dest:ro
SELinux 支持 :z:Z 标志

五、多容器应用:使用 Docker Compose 编排服务

大型应用常由多个服务组成,如:

  • Web 应用(Node.js / Flask)
  • 数据库(MySQL / PostgreSQL)
  • 缓存(Redis)
  • 消息队列(RabbitMQ)

使用 Docker Compose 编排管理多个容器。

🧾 示例 docker-compose.yml

yaml 复制代码
version: "3"
services:
  web:
    image: myapp
    ports:
      - "8080:80"
  db:
    image: postgres
    volumes:
      - pgdata:/var/lib/postgresql/data
volumes:
  pgdata:

🚀 启动应用:

bash 复制代码
docker compose up -d
  • 自动创建网络、卷
  • 服务间自动 DNS 发现(web 可通过 db 名称访问 PostgreSQL)

六、实践总结

操作点 命令或说明
映射端口 -p 宿主端口:容器端口
覆盖默认启动命令 docker run 镜像 <新命令>
数据卷持久化 -v 卷名:/路径-v 宿主路径:/路径
文件共享与挂载 本地映射容器目录(开发中常用)
多容器应用编排 使用 docker-compose.yml 配置

相关推荐
西京刀客39 分钟前
k8s热更新-subPath 不支持热更新
云原生·容器·kubernetes·configmap·subpath
大咖分享课5 小时前
云原生监控体系建设:Prometheus+Grafana的企业级实践
云原生·grafana·prometheus
藥瓿亭5 小时前
K8S认证|CKS题库+答案| 7. Dockerfile 检测
运维·ubuntu·docker·云原生·容器·kubernetes·cks
容器魔方6 小时前
KubeCon 抢鲜 | Kmesh与你共创高性能流量治理更优方案
云原生·容器·云计算
Gold Steps.7 小时前
Docker容器部署elasticsearch8.*与Kibana8.*版本使用filebeat采集日志
运维·docker·云原生·es
上海运维Q先生8 小时前
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement
云原生·k8s·cilium
AWS官方合作商9 小时前
Amazon RDS on AWS Outposts:解锁本地化云数据库的混合云新体验
云原生·云计算·aws
AWS官方合作商16 小时前
在CSDN发布AWS Proton解决方案:实现云原生应用的标准化部署
java·云原生·aws
藥瓿亭1 天前
K8S认证|CKS题库+答案| 6. 创建 Secret
运维·ubuntu·docker·云原生·容器·kubernetes·cks