news 2026/7/29 20:55:03

Docker 镜像与容器核心概念详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Docker 镜像与容器核心概念详解

1. Docker 镜像是什么?

Docker 镜像是一个轻量级、可执行的独立软件包,包含运行某个软件所需的所有内容:代码、运行时环境、系统工具、系统库和设置。镜像采用分层存储结构,每一层都是只读的,这种设计带来了两大核心优势:

  • 节约存储空间:多个镜像可以共享相同的基础层,避免重复存储。
  • 高效分发与构建:镜像层可以被缓存和复用,加速构建和拉取过程。

简单来说,镜像 = 应用程序代码 + 微型操作系统环境 + 配置,是一个静态的、分层的文件系统快照。

2. Dockerfile 指令详解

2.1 COPY 与 ADD 的区别

COPY:主要用于将宿主机(构建上下文)的文件或目录复制到镜像中。

COPY app.py /app/

ADD:除了具备 COPY 的功能外,还额外支持:

  • 自动解压 tar、gzip、bzip2、xz 等压缩包
  • 支持从 URL 下载文件(但不推荐,因为无法保证下载文件的完整性)
ADD app.tar.gz /app/ # 会自动解压到 /app/ 目录

最佳实践:除非需要解压功能,否则优先使用 COPY,因为它更透明、更可预测。

2.2 VOLUME 指令

VOLUME 指令在镜像中声明一个挂载点,用于持久化数据和共享数据:

VOLUME /var/lib/mysql

当容器启动时:

  • Docker 会自动创建一个匿名卷(随机名称)挂载到容器的 /var/lib/mysql 目录
  • 即使容器被删除,卷中的数据仍然保留
  • 也可以通过docker run -v指定具名卷或宿主机目录覆盖此声明

2.3 CMD 与 ENTRYPOINT 的区别

ENTRYPOINT:定义容器启动时必须执行的核心命令,通常是一个脚本或可执行文件。

CMD:定义容器启动时的默认参数。如果启动容器时指定了其他命令,CMD 中的内容会被覆盖。

组合使用示例

ENTRYPOINT ["/docker-entrypoint.sh"] CMD ["nginx", "-g", "daemon off;"]

等价于容器启动时执行:

/docker-entrypoint.sh nginx -g "daemon off;"

关键点

  • CMD 中的参数会作为位置变量传递给 ENTRYPOINT 对应的脚本
  • daemon off强制 Nginx 以前台进程模式运行(容器中运行的程序必须前台运行)
  • 容器生命周期 = 容器中运行的主进程生命周期

2.4 Shell 调试模式

在 Dockerfile 或启动脚本中常用的 Shell 选项:

set -eux # -e (errexit):上条命令执行失败时立即退出脚本 # -u (nounset):引用未定义变量时报错退出 # -x (xtrace):打开调试模式,显示执行的每一条命令 set +x # 关闭调试模式

3. 如何制作更小的镜像?

镜像大小直接影响构建速度、存储成本和网络传输效率。优化策略:

  1. 减少镜像层数:每个 RUN、COPY、ADD、WORKDIR、ENV 等指令都会创建新层
    • 合并多个 RUN 命令:RUN apt-get update && apt-get install -y package && rm -rf /var/lib/apt/lists/*
    • 减少不必要的文件复制
  2. 使用最小的基础镜像
    • Alpine Linux:仅 5MB 左右
    • Distroless:只包含应用程序及其运行时依赖,没有 Shell 和包管理器
    • Scratch:空镜像,适合静态编译的程序
  3. 合理使用多阶段构建:在构建阶段安装编译工具,最终镜像只包含运行所需文件
  4. 使用 .dockerignore 文件:排除不必要的构建上下文文件
  5. 数据与镜像分离:使用卷(Volume)挂载配置文件、日志、数据库文件等可变数据

4. 实战案例:Python Flask 微服务镜像制作

4.1 项目结构

/myapp/python2/ ├── app.py # Flask 应用程序 ├── requirements.txt # Python 依赖 └── Dockerfile # 镜像构建文件

4.2 核心应用程序 (app.py)

from flask import Flask from redis import Redis, RedisError import os import socket 连接 Redis redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2) app = Flask(name) @app.route("/") def hello(): try: visits = redis.incr("counter") except RedisError: visits = "<i>cannot connect to Redis, counter disabled</i>" html = "&lt;h3&gt;Hello {name}!&lt;/h3&gt;" \ "&lt;b&gt;Hostname:&lt;/b&gt; {hostname}&lt;br/&gt;" \ "&lt;b&gt;Visits:&lt;/b&gt; {visits}" return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits) if name == "main": app.run(host='0.0.0.0', port=80)

4.3 依赖文件 (requirements.txt)

flask redis

4.4 Dockerfile 配置

# 使用 Python 2.7 精简版作为基础镜像 FROM python:2.7-slim 设置工作目录 WORKDIR /app 复制当前目录所有文件到容器的 /app 目录 ADD . /app 安装 Python 依赖(使用国内镜像加速) RUN pip install --trusted-host https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt 暴露端口 EXPOSE 80 设置环境变量 ENV NAME World ENV AUTHOR cali 容器启动命令 CMD ["python", "app.py"]

4.5 构建与运行

# 构建镜像 docker build -t sweb:1.0 . 查看镜像 docker images 运行容器(映射宿主机 8050 端口到容器 80 端口) docker run -d --name sweb-1 -p 8050:80 sweb:1.0 查看运行状态 docker ps 访问应用 浏览器打开:http://宿主机IP:8050

4.6 网络配置与容器互联

微服务架构中,多个容器需要通信:

# 创建自定义网络(指定子网和网关) docker network create --driver bridge \ --subnet 172.20.0.0/16 \ --gateway 172.20.0.1 \ my-custom-network 启动容器并指定固定 IP docker run -d --name nginx-fixed-ip -p 8051:80 --network my-custom-network --ip 172.20.0.10 nginx 启动 Redis 容器(供 Flask 应用连接) docker run -d --name redis --network my-custom-network redis:alpine 修改 app.py 中的 Redis 连接主机名为 "redis"(容器名)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/29 20:54:59

AWS云技术基础:从基础设施到高可用Web应用实战

1. 从“云”到“AWS”&#xff1a;为什么我们需要重新理解基础设施如果你和我一样&#xff0c;是从传统的IDC机房、物理服务器时代一路走过来的&#xff0c;那么第一次接触“AWS”或者“云计算”这个概念时&#xff0c;内心多少会有些复杂。一方面&#xff0c;它听起来像是能解…

作者头像 李华
网站建设 2026/7/29 20:49:35

如何高效使用LinkSwift脚本工具:3个提升网盘下载效率的实用技巧

如何高效使用LinkSwift脚本工具&#xff1a;3个提升网盘下载效率的实用技巧 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 &#xff0c;支持 百度网盘 / 阿里云盘 / 中国移动云…

作者头像 李华
网站建设 2026/7/29 20:47:21

致焦虑的程序员:AI 不会让你失业,但“写 CRUD”会

AI 继续发展&#xff0c;会导致程序员大规模失业吗&#xff1f;&#x1f914; 最近不管是刷技术社区还是朋友圈&#xff0c;总能看到 “AI 要取代程序员” 的焦虑帖。作为写了十几年 Java、从 SSH 时代用到现在 AI 辅助编码的老开发&#xff0c;我先给个干脆的结论&#xff1a…

作者头像 李华
网站建设 2026/7/29 20:47:06

单片机毕业设计-基于单片机的自动手动双模式护眼台灯开发 基于光敏采集的 10 档可调智能台灯系统设计(011901)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/7/29 20:46:03

Android16 rk3576修改系统自适应亮度曲线

RK平台默认的自适应亮度有时候很难满足个人的项目需求,这里记录一下自己修改系统自适应亮度逻辑的过程。 1.修改驱动: 在kernel-6.1\drivers\input\sensors\lsensor\sdf_dals_z1p.c里面: /** drivers/input/sensors/lsensor/ls_sdf_dals_z1p.c** Copyright (C) Rockchip E…

作者头像 李华