当前位置: 首页 > news >正文

docker镜像与dockerfile

一、docker镜像

1.什么是镜像

        容器解决应用开发、测试和部署的问题,而镜像解决应用部署环境问题。镜像是一个只读的容器模板, 打包了应用程序和应用程序所依赖的文件系统以及启动容器的配置文件,是启动容器的基础。镜像所打 包的文件内容就是容器的系统运行环境——rootfs(根文件系统或根目录)。容器与镜像类似对象与类的关系。

2.docker镜像原理

1. 分层: Docker镜像采用分层的方式构建,每一个镜像都由一组镜像组合而成。每一个镜像层都可 以被需要的镜像所引用,实现了镜像之间共享镜像层的效果。这样的分层设计在镜像的上传与下载 过程当中有效的减少了镜像传输的大小,在传输过程当中本地或注册中心只需要存在一份底层的基 础镜像层即可,真正被保存和下载的内容是用户构建的镜像层。而在构建过程中镜像层通常会被缓 存以缩短构建过程。

2. 写时复制:底层镜像层在多个容器间共享,每个容器启动时不需要复制一份镜像文件,而是将所有 需要的镜像层以只读的方式挂载到一个挂载点,在只读层上再覆盖一层读写层。在容器运行过程中 产生的新文件将会写入到读写层,被修改过的底层文件会被复制到读写层并且进行修改,而老文件 则被隐藏。

3. 联合挂载:docker采用联合挂载技术,在同一个挂载点同时挂载多个文件系统,从而使得容器的根 目录看上去包含了各个镜像层的所有文件。如下图:

 4. 内容寻址:根据镜像层内容计算校验和,生成一个内容哈希值,并使用该值来充当镜像层ID、索引 镜像层。内容寻址提高了镜像的安全性,在pull、push和load、save操作后检测数据的完整性。另 外基于内容哈希来索引镜像层,对于来自不同构建的镜像层,只要拥有相同的内容哈希值,就能被 不同的镜像所引用。

        docker的镜像和容器的关系不是类和对象的关系而是相同的引用,以下是详细讲解:

一、“类与对象” 类比的局限性

1. 类与对象的本质特征
  • 类(Class):是抽象模板,定义属性和方法,不占用实际资源;
  • 对象(Object):是类的实例化结果,每个对象独立拥有数据空间,修改对象不会影响类或其他对象。
  • 核心逻辑:对象是类的 “复制”,彼此隔离。
2. Docker 镜像与容器的实际机制
  • 镜像(Image):是只读的文件系统快照,由多层只读层叠加而成(基于 UnionFS);
  • 容器(Container):是镜像的运行实例,在镜像顶层添加一个可写层(container layer)。
  • 核心逻辑:容器并非镜像的 “复制”,而是共享镜像的底层只读层,仅添加独立的可写层。

二、“相同引用” 的本质:分层存储与共享机制

1. UnionFS 分层架构

Docker 使用 UnionFS(如 Overlay2)实现镜像和容器的分层存储:

 
  • 镜像层(只读):多个镜像可共享底层基础层(如ubuntu:latest的文件系统),类似 Linux 的硬链接,多个引用指向同一物理存储;
  • 容器层(可写):每个容器在镜像顶层添加一个专属的可写层,用于存储运行时修改(如写入文件、环境变量变更)。
2. “相同引用” 的具体体现
  • 底层共享:当多个容器基于同一镜像启动时,它们共享镜像的所有只读层(即底层文件系统的引用相同),而非各自复制一份镜像数据。例如:

    bash

    # 启动两个容器基于同一镜像
    docker run -d ubuntu:22.04 sleep 3600
    docker run -d ubuntu:22.04 sleep 3600
    

    这两个容器的底层文件系统(如/bin/bash/etc)实际指向同一份物理存储,仅各自的可写层独立。
  • 空间效率:这种共享机制大幅节省磁盘空间,避免镜像复制的冗余(类似 Linux 系统中多个进程共享同一可执行文件的内存映射)。
3. 与 “类与对象” 的关键差异
对比维度类与对象关系镜像与容器关系
数据隔离性对象完全独立,无共享数据容器共享镜像的只读层数据
修改影响修改对象不影响类或其他对象容器修改仅作用于自身可写层
资源占用每个对象独立占用内存多个容器共享底层镜像资源
创建逻辑对象是类的 “实例化复制”容器是镜像的 “引用 + 扩展”

 3. docker镜像关键概念

        1. registry:注册中心,用来保存docker镜像,其中包括镜像的层次结构和关于镜像的元数据。

        2. repository:仓库,即由具有某个功能的Docker镜像的所有迭代版本构成的镜像组。

        3. manifest:Docker镜像元数据文件,在pull、push、save和load中作为镜像结构和基础信息的描 述文件。在镜像被pull或者load到Docker宿主机时,manifest被转化为本地的镜像配置文件config

        4. image:镜像,用来存储一组相关的元数据信息,主要包括镜像的架构(如amd64)、镜像默认配 置信息、构建镜像的容器配置信息、包含所有镜像层的rootfs。

        5. layer:镜像层,是docker用来管理镜像的中间概念,镜像是由镜像层组成的,单个镜像层可以被 多个镜像和容器共享。

        6. dockerfile:是一个镜像制作过程的定义,文档包含了镜像制作的所有命令和完整操作流程

1. Registry(注册中心)

定义与作用

Registry 是 Docker 生态中的镜像存储服务,负责集中保存 Docker 镜像的完整数据(包括镜像层、元数据、清单等)。它是镜像的「云端仓库」,支持镜像的上传(push)、下载(pull)、删除等操作。

核心特性
  • 存储结构:以分层方式存储镜像数据,支持内容寻址(通过镜像层的哈希值索引),避免重复存储;
  • 元数据管理:保存镜像的 manifest(清单)、标签(tag)、版本信息等;
  • 多租户支持:可部署公共 Registry(如 Docker Hub)或私有 Registry(如 Harbor、AWS ECR)。
如何查看与使用?
  • 公共 Registry(Docker Hub)
    访问 hub.docker.com 可浏览官方仓库(如 nginxubuntu)和用户仓库。例如,搜索 nginx 会显示其所有标签(latestalpine 等)。

  • 私有 Registry 操作
    若部署了私有 Registry(如 Harbor),需先登录:

    docker login my-private-registry.com:5000  # 输入账号密码
    

    上传镜像到私有 Registry:

    docker tag nginx:alpine my-private-registry.com/my-team/nginx:alpine  # 重命名镜像为私有仓库路径
    docker push my-private-registry.com/my-team/nginx:alpine  # 上传
    

2. Repository(仓库)

定义与作用

Repository(仓库)是 Registry 中的镜像逻辑分组单元,由同一功能镜像的所有迭代版本(不同标签)组成。例如,nginx 仓库包含 nginx:latestnginx:alpinenginx:1.25 等不同标签的镜像。

核心特性
  • 标签(Tag):仓库中的每个镜像版本通过标签区分(如 latest 是默认标签);
  • 命名规则:仓库名通常为 [用户/组织名]/[镜像名](如 docker/library/nginx 是官方仓库,myuser/myapp 是个人仓库)。
如何查看与使用?
  • 查看仓库中的标签

    • 公共仓库:在 Docker Hub 页面直接查看标签列表(如 nginx 标签页);
    • 私有仓库:通过命令行或 Registry 管理界面(如 Harbor 的 Web 界面)查看。
  • 拉取仓库中的特定标签

    docker pull nginx:alpine  # 拉取 nginx 仓库的 alpine 标签镜像
    

3. Manifest(清单)

定义与作用

Manifest 是镜像的元数据描述文件,JSON 格式,记录镜像的核心信息,包括:

 
  • 镜像的配置文件(config)的哈希值;
  • 所有镜像层(layers)的哈希值列表(按堆叠顺序);
  • 镜像的架构(如 amd64)、操作系统(如 linux)等元数据。
核心作用
  • 镜像传输的「地图」:当执行 docker pull 或 docker push 时,首先传输 Manifest,通过其中的层哈希值确认需要下载 / 上传的层;
  • 本地镜像的「索引」:下载后,Manifest 会被转换为本地镜像的配置文件(config.json),记录镜像的运行时默认配置(如入口命令、环境变量)。
如何查看与使用?
  • 查看远程镜像的 Manifest(需镜像未开启内容信任):

    docker manifest inspect nginx:alpine
    

    输出示例(简化):

    {"schemaVersion": 2,"mediaType": "application/vnd.docker.distribution.manifest.v2+json","config": {"mediaType": "application/vnd.docker.container.image.v1+json","size": 7023,"digest": "sha256:abc123..."  # 镜像配置文件的哈希},"layers": [{"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip","size": 2815,"digest": "sha256:def456..."  # 第一层的哈希},{"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip","size": 1234,"digest": "sha256:ghi789..."  # 第二层的哈希}]
    }
    
  • 查看本地镜像的 Manifest(需通过 docker inspect 间接获取):

    docker inspect nginx:alpine | jq '.[0].RootFS'  # 查看镜像层的哈希列表
    

4. Image(镜像)

定义与作用

Image(镜像)是 Docker 容器的只读模板,由以下部分组成:

  • 配置信息config.json):包括镜像的架构、默认命令(CMD)、入口点(ENTRYPOINT)、环境变量(ENV)等;
  • 根文件系统(RootFS):由多个只读镜像层(layer)堆叠而成,定义容器的初始文件系统;
  • 元数据:如镜像创建时间、作者、标签等。
核心特性
  • 不可变性:镜像一旦构建完成,内容不可修改(修改需生成新镜像);
  • 分层结构:基于内容寻址的镜像层共享机制,节省存储(详见下文 layer 部分)。
如何查看与使用?
  • 查看本地镜像列表

    docker images  # 显示所有本地镜像(仓库名、标签、镜像 ID、大小等)
    
  • 查看镜像详细信息

    docker inspect nginx:alpine  # 输出镜像的完整配置(JSON 格式)
    

    关键字段:

    • Config:镜像的默认运行配置(如 CmdEnv);
    • RootFS.Layers:镜像层的哈希列表(与 Manifest 中的 layers 一致);
    • Created:镜像的创建时间。

5. Layer(镜像层)

定义与作用

Layer(镜像层)是镜像的最小存储单元,对应 Dockerfile 中一条指令(如 RUNCOPY)的文件系统变更。每个层是一个只读的 tar 压缩包,包含该指令对文件系统的修改(新增、删除、修改的文件 / 目录)。

核心特性
  • 内容寻址:每个层的哈希值由其内容(文件数据 + 元数据)计算生成(SHA256),相同内容的层会被不同镜像共享;
  • 堆叠顺序:层按 Dockerfile 指令顺序堆叠,上层覆盖下层的同名文件;
  • 可写层隔离:容器运行时,会在镜像层顶部添加一个可写层(container layer),所有运行时修改仅作用于该层。
如何查看与使用?
  • 查看镜像的层历史

    docker history nginx:alpine
    

    输出示例:

    IMAGE          CREATED         CREATED BY                                      SIZE      COMMENT
    sha256:abc123  2 weeks ago     /bin/sh -c #(nop)  CMD ["nginx" "-g" "daemon…   0B        
    <missing>      2 weeks ago     /bin/sh -c #(nop)  EXPOSE 80/tcp                0B        
    <missing>      2 weeks ago     /bin/sh -c apt-get update && apt-get install…   123MB     
    ...
    
     

    每行对应一个镜像层,CREATED BY 显示该层对应的 Dockerfile 指令,SIZE 是层的大小。

  • 查看层的具体内容(需借助工具):
    可通过 docker image inspect 获取层的哈希,然后到 Docker 存储目录(如 /var/lib/docker/overlay2)查看层的实际文件:

    # 获取镜像层的哈希列表
    docker inspect nginx:alpine | jq '.[0].RootFS.Layers'
    # 输出类似:["sha256:def456...", "sha256:ghi789..."]# 查看层的内容(需 root 权限)
    ls /var/lib/docker/overlay2/def456.../diff  # 该目录是层的解压内容
    

6. Dockerfile

定义与作用

Dockerfile 是镜像构建的脚本文件,包含一系列指令(如 FROMRUNCOPY),定义了镜像的构建步骤和配置。Docker 通过解析 Dockerfile 逐行执行指令,生成镜像层,最终构建出完整镜像。

核心指令与示例

常见 Dockerfile 指令:

  • FROM:指定基础镜像(如 FROM ubuntu:22.04);
  • RUN:执行命令(如 RUN apt-get update);
  • COPY:复制文件到镜像(如 COPY app/ /app/);
  • CMD:定义容器默认启动命令(如 CMD ["nginx", "-g", "daemon off;"]);
  • EXPOSE:声明容器监听的端口(如 EXPOSE 80)。
如何使用?
  • 编写 Dockerfile(示例:构建一个简单的 Nginx 镜像):

    # 基础镜像
    FROM nginx:alpine# 复制自定义配置到镜像
    COPY nginx.conf /etc/nginx/nginx.conf# 声明端口(仅文档作用)
    EXPOSE 80# 容器启动时执行的命令(继承自基础镜像的 CMD)
    
  • 构建镜像

    docker build -t my-nginx:v1 .  # -t 指定镜像标签,. 表示 Dockerfile 在当前目录
    
  • 验证构建结果

    docker images | grep my-nginx  # 查看新构建的镜像
    docker history my-nginx:v1     # 查看镜像层是否包含 COPY 指令生成的层
    

总结:概念间的协同关系

  1. 构建阶段:用户编写 Dockerfile,Docker 逐行执行指令生成 layer(镜像层),最终构建为 image(镜像);
  2. 存储阶段:镜像的 manifest(清单)描述其层结构和元数据,镜像与层被存储在 registry(注册中心)的 repository(仓库)中;
  3. 分发与运行阶段:用户通过 docker pull 从 Registry 下载镜像(基于 Manifest 拉取层),启动容器时镜像的只读层与容器的可写层合并,形成运行环境。

 4. 镜像管理命令

        Docker 镜像的全生命周期管理(构建、查看、标记、导出 / 导入、删除)依赖一系列核心命令。以下按功能分类,详细讲解每个命令的作用、常用选项、操作示例注意事项,帮助你高效管理镜像。

一、镜像构建:docker build

功能

通过解析 Dockerfile 脚本,逐层构建镜像。支持分层缓存、参数传递、资源限制等高级特性,是镜像创建的标准方式(推荐替代 docker commit)。

常用选项(标⭐为高频使用)
选项说明
-t, --tag ⭐指定镜像的标签(格式:仓库名:标签,如 myapp:v1);可多次使用设置多个标签。
-f, --file ⭐显式指定 Dockerfile 路径(默认当前目录的 Dockerfile)。
--no-cache ⭐禁用构建缓存(强制重新构建所有层,用于解决缓存导致的镜像内容不同步)。
--build-arg设置构建时变量(需在 Dockerfile 中用 ARG 声明)。
--pull构建前尝试拉取基础镜像的最新版本(避免使用本地旧版本)。
--rm构建成功后删除中间容器(默认 true,节省磁盘空间)。
--force-rm无论构建是否成功,总是删除中间容器(避免中间容器残留)。
操作示例

假设当前目录有 Dockerfile(内容如下):

# 基础镜像
FROM nginx:alpine# 复制自定义配置到镜像
COPY nginx.conf /etc/nginx/nginx.conf# 声明端口(仅文档作用)
EXPOSE 80# 容器启动命令(继承自基础镜像)

构建命令

 
# 基本构建(标签为 my-nginx:v1,使用当前目录的 Dockerfile)
docker build -t my-nginx:v1 .# 显式指定 Dockerfile 路径(假设文件在 ./docker/ 目录)
docker build -t my-nginx:v1 -f ./docker/Dockerfile .# 禁用缓存并设置构建变量(假设 Dockerfile 中有 ARG VERSION)
docker build -t my-nginx:v1 --no-cache --build-arg VERSION=1.25 .
注意事项
  • 构建上下文(PATH):命令中的 . 表示构建上下文路径,Docker 会将该路径下的所有文件打包传给 Docker 守护进程(避免在上下文中放入大文件,否则会影响构建速度)。
  • 缓存机制:默认情况下,若某层的内容未变(哈希匹配),则直接复用缓存层,加速构建。若需强制更新某层(如 RUN apt-get update),需用 --no-cache
  • 中间容器:构建过程中会生成临时容器(用于执行 RUN 指令),默认构建成功后删除(--rm=true),失败时保留(便于调试)。

二、镜像查看:docker images

功能

列出本地已下载或构建的镜像,支持过滤、格式化输出,可查看镜像的标签、大小、创建时间等信息。

常用选项(标⭐为高频使用)
选项说明
-a, --all ⭐显示所有镜像(包括中间层镜像,默认过滤中间层)。
--filter ⭐过滤镜像(如 dangling=true 查看悬空镜像,label=key=value 按标签过滤)。
--format自定义输出格式(使用 Go 模板,如 {{.Repository}}:{{.Tag}})。
-q, --quiet仅显示镜像 ID(用于脚本自动化)。
--digests显示镜像的摘要(SHA256 哈希,用于验证镜像完整性)。
操作示例
# 查看所有本地镜像(含标签、大小等)
docker images# 查看所有镜像(含中间层)
docker images -a# 过滤悬空镜像(无标签、未被引用的镜像,通常是构建失败的残留)
docker images --filter dangling=true# 仅显示镜像 ID
docker images -q# 格式化输出(显示仓库:标签 及 大小)
docker images --format "{{.Repository}}:{{.Tag}} \t {{.Size}}"
注意事项
  • 悬空镜像(Dangling Image):指无标签(<none>:<none>)且未被其他镜像引用的镜像,通常由覆盖标签(如 docker tag old-image new-tag)或构建失败导致,可通过 docker image prune 清理。
  • 中间层镜像:构建过程中生成的临时层(docker images -a 可见),默认被过滤,可通过 --no-cache 避免生成冗余中间层。

三、镜像删除:docker rmi

功能

删除本地镜像。若镜像被容器引用(即使容器已停止),需先删除容器或强制删除镜像。

常用选项
选项说明
-f, --force强制删除镜像(即使被容器引用,需先停止容器)。
--no-prune不删除该镜像的中间层(默认会删除未被其他镜像引用的中间层)。
操作示例
# 删除指定标签的镜像
docker rmi my-nginx:v1# 强制删除被容器引用的镜像(需先停止容器)
docker stop my-container  # 停止容器
docker rmi -f my-nginx:v1  # 强制删除镜像# 删除多个镜像(通过镜像 ID 或标签)
docker rmi my-nginx:v1 nginx:alpine# 删除所有无标签的悬空镜像(等价于 docker image prune)
docker rmi $(docker images -q --filter dangling=true)
注意事项
  • 依赖关系:若镜像被其他镜像引用(如作为基础镜像),需先删除依赖它的镜像,否则无法删除。
  • 容器关联:运行中的容器依赖的镜像无法删除(会报错 conflict: unable to remove repository reference),需先停止并删除容器(docker rm)。

四、镜像标记:docker tag

功能

为本地镜像添加或修改标签,方便分类管理(如标记为测试版、生产版)或推送至不同仓库(如私有 Registry)。

操作示例
# 为镜像添加新标签(原标签保留)
docker tag my-nginx:v1 my-nginx:latest  # 同时存在 my-nginx:v1 和 my-nginx:latest# 标记镜像到私有 Registry(以便推送)
docker tag my-nginx:v1 private-registry.com/my-team/my-nginx:v1# 覆盖已有标签(原标签指向的镜像变为悬空镜像)
docker tag my-nginx:v1 my-nginx:old  # 原 my-nginx:old 若存在,会变为 <none>:<none>
注意事项
  • 标签的意义:标签是镜像的「别名」,不影响镜像本身(镜像的唯一标识是 IMAGE ID)。
  • 推送准备:推送镜像到私有 Registry 前,需通过 docker tag 将镜像重命名为 私有仓库路径:标签(如 private-registry.com/user/repo:tag)。

五、镜像导出与导入:docker save / docker load

功能
  • docker save:将本地镜像打包为 tar 文件,用于离线传输或备份。
  • docker load:从 tar 文件中导入镜像到本地(恢复备份或传输后的镜像)。
操作示例
# 导出单个镜像为 tar 文件(包含镜像层和元数据)
docker save -o my-nginx.tar my-nginx:v1# 导出多个镜像(用空格分隔)
docker save -o all-images.tar my-nginx:v1 nginx:alpine# 导入 tar 文件到本地镜像库(会保留原标签)
docker load -i my-nginx.tar
注意事项
  • 文件大小tar 文件包含镜像的所有层,体积较大(与镜像大小一致)。
  • 跨平台兼容性:导出的镜像仅适用于相同架构(如 amd64)的 Docker 环境,跨架构需重新构建。

六、归档文件创建镜像:docker import

功能

从 tar 归档文件(如 docker export 导出的容器文件系统)创建镜像。与 docker save 不同,docker import 会丢失镜像的层信息,生成一个单层镜像。

操作示例
# 从容器导出文件系统(得到容器的当前文件系统快照)
docker export my-container > container.tar# 从归档文件创建镜像(无层信息,仅单层)
docker import -c "CMD [\"nginx\", \"-g\", \"daemon off;\"]" container.tar my-nginx:imported
注意事项
  • 适用场景:仅用于从容器文件系统快照恢复镜像(如迁移容器状态),不推荐替代 docker build(无法利用分层缓存)。
  • 元数据丢失:导入的镜像会丢失原镜像的构建历史(docker history 仅显示一层),且无法复用其他镜像的层。

七、容器创建镜像:docker commit

功能

从运行中的容器创建新镜像(将容器的可写层保存为镜像层)。适用于快速保存容器的临时状态,但不推荐用于正式镜像构建(无法复现构建过程)。

常用选项
选项说明
-a, --author镜像作者(如 --author "Nick <nick@example.com>")。
-m, --message提交说明(类似 Git 的 commit -m)。
-p, --pause提交时暂停容器(默认 true,避免提交过程中容器状态变化)。
操作示例
# 启动容器并修改内容(如修改 nginx 配置)
docker run -it --name my-container nginx:alpine /bin/bash
echo "server { listen 80; }" > /etc/nginx/nginx.conf  # 修改配置
exit# 从容器提交新镜像
docker commit -a "Nick" -m "Custom nginx config" my-container my-nginx:committed
注意事项
  • 不可复现性commit 生成的镜像无法通过 Dockerfile 复现,后续修改需再次 commit,难以维护。
  • 镜像体积:每次 commit 会生成新层,可能导致镜像体积膨胀(推荐用 docker build 分层构建)。

总结:命令使用场景建议

需求推荐命令原因
标准镜像构建docker build可复现、支持分层缓存、易于维护。
临时保存容器状态docker commit快速保存,但不推荐长期使用。
镜像离线传输 / 备份docker save + docker load保留镜像层信息,支持恢复原镜像。
从容器文件系统创建镜像docker import仅用于迁移容器状态,无法复用分层机制。
镜像标签管理docker tag灵活标记,便于分类和推送。
镜像删除docker rmi清理冗余镜像,注意依赖关系。

5.  镜像仓库命令

        Docker 镜像的全生命周期管理不仅包括本地构建与查看,还涉及远程仓库交互(登录、拉取、推送)、镜像分享(公共仓库 / 本地导出 / 私有仓库)等关键操作。以下结合命令详解、操作示例与最佳实践,完整梳理这一流程。

一、远程仓库认证:docker login 与 docker logout

核心作用
  • docker login:登录到 Docker 镜像仓库(如 Docker Hub 或私有 Registry),获取上传 / 下载权限;
  • docker logout:退出当前登录的仓库,避免凭证泄露。
命令格式与选项
# 登录(默认 Docker Hub)
docker login [OPTIONS] [SERVER]# 登出(默认 Docker Hub)
docker logout [OPTIONS] [SERVER]

常用选项

  • -u, --username:登录用户名;
  • -p, --password:登录密码(或 Token);
  • (注意:直接使用 -p 可能泄露密码,推荐交互式输入或使用 --password-stdin 从标准输入读取)
操作示例
# 登录 Docker Hub(交互式输入密码)
docker login
# 输入用户名后,输入密码(隐藏输入)# 非交互式登录(仅用于脚本,需谨慎保管密码)
docker login -u "myuser" -p "mypassword"# 登录私有 Registry(如 localhost:5000)
docker login http://localhost:5000 -u "testuser" -p "testpwd"# 退出 Docker Hub
docker logout# 退出私有 Registry
docker logout http://localhost:5000
注意事项
  • 登录凭证默认存储在 ~/.docker/config.json(Linux/macOS)或 %USERPROFILE%\.docker\config.json(Windows),包含仓库地址和加密后的密码;
  • 若私有 Registry 使用自签名证书,需配置 Docker 信任该证书(或通过 --insecure-registry 跳过校验,见后文私有仓库部分)。

二、镜像远程操作:docker pull 与 docker push

核心作用
  • docker pull:从远程仓库下载镜像到本地;
  • docker push:将本地镜像上传到远程仓库(需先登录)。
命令格式与选项
# 拉取镜像(默认 Docker Hub)
docker pull [OPTIONS] NAME[:TAG|@DIGEST]# 推送镜像(默认 Docker Hub)
docker push [OPTIONS] NAME[:TAG]

常用选项

 
  • -a, --all-tags:拉取仓库中所有标签的镜像(如 docker pull -a nginx 拉取 nginx:latestnginx:alpine 等);
  • --disable-content-trust:跳过镜像内容校验(默认开启,确保镜像未被篡改);
操作示例
# 拉取 Docker Hub 的 nginx:latest 镜像(默认标签为 latest)
docker pull nginx# 拉取指定标签的镜像(如 nginx:alpine)
docker pull nginx:alpine# 拉取指定摘要(Digest)的镜像(确保内容绝对一致)
docker pull nginx@sha256:abc123...  # 从 manifest 中获取摘要# 推送本地镜像到 Docker Hub(需先登录)
docker push myuser/myapp:v1# 推送镜像到私有 Registry(需先打标签为私有仓库路径)
docker tag myapp:v1 localhost:5000/myuser/myapp:v1
docker push localhost:5000/myuser/myapp:v1
注意事项
  • 拉取镜像时,若本地已有相同哈希的镜像层,会直接复用(基于内容寻址),节省下载时间;
  • 推送镜像时,仅上传本地不存在于远程仓库的镜像层(增量上传),提升效率;
  • 若镜像被标记为多个标签(如 myapp:v1 和 myapp:latest),推送时需分别推送每个标签。

三、镜像搜索:docker search

核心作用

在 Docker Hub 搜索公开镜像,支持过滤(如官方镜像、高星镜像),快速定位所需镜像。

命令格式与选项
docker search [OPTIONS] TERM

常用选项

  • --automated:仅显示自动构建的镜像(由 Dockerfile 自动构建,非手动 commit);
  • --no-trunc:显示完整的镜像描述(默认截断);
  • -f, --filter:过滤条件(如 stars=10 表示收藏数≥10);
操作示例
# 搜索名称包含 "nginx" 的镜像
docker search nginx# 搜索收藏数≥10 的 nginx 镜像
docker search -f stars=10 nginx# 仅显示自动构建的 nginx 镜像
docker search --automated nginx# 显示完整描述(不截断)
docker search --no-trunc nginx

输出示例

NAME                      DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
nginx                     Official build of Nginx.                        20000     [OK]       
bitnami/nginx             Bitnami nginx Docker Image                      1500                  [OK]
...

四、镜像分层与联合挂载实践(以 Nginx 为例)

Docker 镜像的分层机制是其轻量化的核心,通过 docker save、解压镜像包和查看 manifest,可以直观理解镜像层的结构。

操作步骤
  1. 运行 Nginx 容器

    docker run -d -p 81:80 --name mynginx1 nginx:latest
    
  2. 进入容器查看文件系统

    docker exec -it mynginx1 /bin/bash
    ls /etc/nginx  # 查看 Nginx 配置文件(来自镜像层)
    exit
    
  3. 保存镜像为 tar 归档

    docker save -o nginx.tar nginx:latest
    
  4. 解压并查看镜像层

    mkdir nginx-layers && tar -xvf nginx.tar -C nginx-layers
    

    解压后会得到多个文件:

    • manifest.json:镜像的清单文件(记录层哈希、配置文件路径);
    • config.json:镜像的配置文件(记录镜像元数据);
    • 多个 sha256-xxx.tar 文件:每个文件对应一个镜像层(压缩的文件系统变更)。
  5. 分析 manifest.json(简化示例):

    [{"Config": "config.json","RepoTags": ["nginx:latest"],"Layers": ["sha256:layer1.tar",  # 基础层(如 Alpine Linux)"sha256:layer2.tar",  # Nginx 安装层"sha256:layer3.tar"   # 其他配置层]}
    ]
    
  6. 对比 docker commit 生成的镜像

    • 运行容器并修改文件(如添加 test.txt):
      docker exec mynginx1 touch /test.txt
      
    • 提交容器为新镜像:
      docker commit -m "Add test.txt" mynginx1 mynginx:v1
      
    • 保存并解压 mynginx:v1 的镜像包,会发现 manifest.json 中新增了一个层(对应 test.txt 的变更),而底层的 Nginx 层与原镜像完全一致(哈希相同,证明层复用)。
关键结论
  • 镜像由多个只读层堆叠而成,相同内容的层会被不同镜像共享(节省存储);
  • docker commit 会生成新层(记录容器可写层的变更),但无法复现构建过程(不推荐用于生产)。

五、镜像分享的三种方式

方式 1:公共仓库(Docker Hub)分享

适用于公开分享镜像,需注册 Docker Hub 账号并创建仓库。

 

操作步骤

 
  1. 创建 Docker Hub 仓库
    登录 hub.docker.com,点击 Create Repository,输入仓库名(如 myuser/mynginx)。

  2. 本地镜像打标签

    docker tag mynginx:v1 myuser/mynginx:v1
    
  3. 推送镜像到 Docker Hub

    docker login  # 登录 Docker Hub
    docker push myuser/mynginx:v1
    
  4. 拉取验证(任意设备):

    docker pull myuser/mynginx:v1
    
方式 2:本地导出 / 导入(docker save + docker load

适用于离线传输或备份镜像(无需网络)。

 

操作步骤

 
  1. 导出镜像为 tar 文件

    docker save -o myimages.tar mynginx:v1 mysql:5.7  # 导出多个镜像
    
  2. 传输文件(通过 U 盘、局域网等)。

  3. 导入镜像到目标设备

    docker load -i myimages.tar  # 导入后镜像标签和层信息完整保留
    
方式 3:私有注册中心分享

适用于企业内部私有镜像管理,需搭建私有 Registry 并配置认证。

 

搭建步骤(以本地 Registry 为例)

 
  1. 启动 Registry 容器(无认证版本):

    docker run -d -p 5000:5000 --name registry --restart=always registry:2
    
  2. 验证 Registry 状态

    curl http://localhost:5000/v2/_catalog  # 应返回 {"repositories":[]}(空仓库)
    
  3. 配置认证(可选)
    使用 htpasswd 生成密码文件(需安装 apache2-utils):

    sudo apt install apache2-utils  # Linux
    htpasswd -Bbn testuser testpwd > /path/to/auth/htpasswd  # 生成密码文件
    
  4. 启动带认证的 Registry

    docker run -d -p 5000:5000 --name registry --restart=always \-v /path/to/data:/var/lib/registry \  # 数据卷(持久化存储)-v /path/to/auth:/auth \               # 密码文件路径-e "REGISTRY_AUTH=htpasswd" \          # 启用 htpasswd 认证-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \-e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" \registry:2
    
  5. 配置 Docker 信任私有 Registry(解决 HTTPS 校验问题):

    • 编辑 Docker 服务配置(Linux):
      sudo vim /lib/systemd/system/docker.service
      
    • 在 ExecStart 行末尾添加 --insecure-registry localhost:5000(允许不安全连接):
      ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --insecure-registry localhost:5000
      
    • 重启 Docker 服务:
      sudo systemctl daemon-reload
      sudo systemctl restart docker
      
  6. 推送与拉取镜像

    # 登录私有 Registry
    docker login http://localhost:5000 -u testuser -p testpwd# 打标签
    docker tag mynginx:v1 localhost:5000/myuser/mynginx:v1# 推送
    docker push localhost:5000/myuser/mynginx:v1# 拉取(其他设备需配置相同的 --insecure-registry)
    docker pull localhost:5000/myuser/mynginx:v1

 二、 dockerfile

1.dockerfile是什么

        Dockerfile是一个创建镜像所有命令的文本文件, 包含了一条条指令和说明, 每条指令构建一层, 通过 docker build命令,根据Dockerfile的内容构建镜像,因此每一条指令的内容, 就是描述该层如何构建.有了 Dockefile, 就可以制定自己的docker镜像规则,只需要在Dockerfile上添加或者修改指令, 就可生成 docker 镜像。

2. dockerfile解决了什么问题

        Dockerfile 包含了镜像制作的完整操作流程,其他开发者可以通过 Dockerfile 了解并复现制作过程 Dockerfile 中的每一条指令都会创建新的镜像层,这些镜像可以被 Docker Daemon 缓存。再次制作镜 像时,Docker 会尽量复用缓存的镜像层(using cache),而不是重新逐层构建,这样可以节省时间和 磁盘空间 Dockerfile 的操作流程可以通过docker image history [镜像名称]查询,方便开发者查看变更记录。

3. docker build 构建流程

一、Docker build 核心流程
第一步:准备上下文(Context)并处理文件
  1. 打包上下文文件

    • docker build 会将指定的上下文目录(context)中的文件打包,发送给 Docker 引擎(Docker daemon)。
    • 若上下文中存在 .dockerignore 文件,会按规则过滤掉不需要上传的文件(如日志、临时文件等)。
  2. 例外规则

    • 若 .dockerignore 文件中包含 .dockerignore 或 Dockerfile 本身,这两个文件不会被过滤,仍会被上传。
  3. 镜像标签验证

    • 若指定了镜像标签(-t 参数),会先验证仓库名(repository)和标签(tag)的格式是否合法。
第二步:发送构建请求至 Docker 引擎
  • 通过 HTTP 请求向 Docker server 发送构建指令,请求中包含上下文信息(打包后的文件)。
第三步:Docker 引擎执行镜像构建
  1. 解压上下文文件

    • 在临时目录中解压上下文文件,作为构建的基础环境。
  2. 解析 Dockerfile 指令

    • 读取并解析 Dockerfile 中的每条指令,按指令类型(如 RUNCOPYADD 等)分发到对应模块处理。
  3. 逐层构建镜像层

    • 对每条指令,创建临时容器并执行指令,然后将容器状态提交(commit)为一个新的镜像层。
    • 例如:RUN apt-get update 会生成一个包含更新操作的镜像层。
  4. 合并镜像层

    • 所有指令执行完毕后,合并所有镜像层,最后一次 commit 生成的镜像 ID 即为最终镜像 ID。
二、构建缓存机制(提升效率的关键)
1. 缓存默认行为
  • Docker 会自动缓存已构建的镜像层,下次构建时若发现指令未变,直接复用缓存,无需重新执行。
  • 可通过 --no-cache=true 参数禁用缓存(如 docker build --no-cache=true -t myimage .)。
2. 缓存匹配规则
  • 基础检查:遍历缓存中的镜像层,检查构建指令是否与当前指令完全一致(如 RUN 命令的参数)。
  • 特殊指令处理
    • 对于 ADDCOPY 指令,除了指令本身,还会校验文件的校验和(checksum),若文件内容不同则缓存失效。
  • 忽略容器内文件检查
    • 例如 RUN apt-get update 执行后,容器内文件更新,但缓存策略不会校验这些文件,仅依赖指令本身和文件校验和。
三、查看镜像构建历史
  • 命令:docker history <镜像ID或标签>
  • 作用:显示镜像各层的构建指令、大小、时间等信息,便于调试和优化构建流程。

4. 关键字

指令说明
FROM设置镜像使用的基础镜像
MAINTAINER设置镜像的作者
RUN编译镜像时运行的脚本
CMD设置容器的启动命令
LABEL设置镜像标签
EXPOSE设置镜像暴露的端口
ENV设置容器的环境变量
ADD编译镜像时复制上下文中的文件到镜像中
COPY编译镜像时复制上下文中的文件到镜像中
ENTRYPOINT设置容器的入口程序
VOLUME设置容器的挂载卷
USER设置运行 RUN、CMD、ENTRYPOINT 的用户名
WORKDIR设置 RUN、CMD、ENTRYPOINT、COPY、ADD 指令的工作目录
ARG设置编译镜像时加入的参数
ONBUILD设置镜像的 ONBUILD 指令
STOPSIGNAL设置容器的退出信号量

5. dockerfile 实践(go)

一、基本语法实践案例

案例目标:使用 Golang 构建一个可执行程序并打包为镜像。

1. 案例准备
# 创建项目目录
mkdir example1 && cd example1
2. Dockerfile 内容
FROM golang:1.18              # 指定基础镜像
ENV env1=env1value env2=env2value  # 设置环境变量
MAINTAINER nick                # 镜像作者
LABEL hello=1.0.0              # 镜像标签
RUN git clone https://gitee.com/nickdemo/helloworld.git  # 克隆代码
WORKDIR helloworld            # 设置工作目录
RUN go env -w GOPROXY=https://proxy.golang.com.cn,https://goproxy.cn,direct  # 配置代理
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app .  # 编译程序
EXPOSE 80                     # 暴露端口
CMD ["./app", "--param1=p1", "--param2=p2"]  # 容器启动命令
3. 构建与运行
# 构建镜像
docker build -t hello:1.0.0 -f Dockerfile .
# 运行容器
docker run -p 80:80 -d --name hello hello:1.0.0
二、Docker Build 上下文实践

案例目标:理解上下文(Context)对构建的影响。

1. 素材准备
mkdir example2 && cd example2
# 下载 Nginx 源码和应用代码
curl https://nginx.org/download/nginx-1.21.6.tar.gz > nginx-1.21.6.tar.gz
git clone https://gitee.com/nickdemo/helloworld
2. 无上下文优化的 Dockerfile(低效)
FROM golang:1.18
ENV env1=env1value env2=env2value
MAINTAINER nick
LABEL hello=1.0.0
RUN git clone https://gitee.com/nickdemo/helloworld.git  # 从网络克隆,不使用本地上下文
WORKDIR helloworld
RUN go env -w GOPROXY=https://proxy.golang.com.cn,https://goproxy.cn,direct
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app .
EXPOSE 80
CMD ["./app", "--param1=p1", "--param2=p2"]
3. 优化后的上下文 Dockerfile(高效)
FROM golang:1.18
ENV env1=env1value env2=env2value
MAINTAINER nick
LABEL hello=1.0.0
COPY ./helloworld /go/src/helloworld  # 从上下文复制本地代码
WORKDIR /go/src/helloworld
RUN go env -w GOPROXY=https://proxy.golang.com.cn,https://goproxy.cn,direct
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app .
EXPOSE 80
CMD ["./app", "--param1=p1", "--param2=p2"]
4. 实践操作
  • 忽略文件测试:在 example2 中创建 .dockerignore,添加 helloworld,观察构建时是否跳过该目录。
  • 上下文路径测试:修改 COPY 路径为上下文外的路径(如 ../other),观察构建错误。
三、多阶段构建实践

案例目标:分离编译环境与运行环境,减小镜像体积。

1. 素材准备
mkdir example3 && cd example3
curl https://nginx.org/download/nginx-1.21.6.tar.gz > nginx-1.21.6.tar.gz
git clone https://gitee.com/nickdemo/helloworld
2. 基础多阶段构建(无别名)
# 第一阶段:编译环境
FROM golang:1.18
ADD ./helloworld /go/src/helloworld/
WORKDIR /go/src/helloworld
RUN go env -w GOPROXY=https://proxy.golang.com.cn,https://goproxy.cn,direct
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app .# 第二阶段:运行环境(使用 Alpine 轻量级系统)
FROM alpine:latest
ENV env1=env1value env2=env2value
MAINTAINER nick
LABEL hello=1.0.0
WORKDIR /app/
COPY --from=0 /go/src/helloworld/app ./  # 从第一阶段复制可执行文件
EXPOSE 80
CMD ["./app", "--param1=p1", "--param2=p2"]
3. 带别名的多阶段构建(更清晰)
# 第一阶段:命名为 stage0
FROM golang:1.18 as stage0
ADD ./helloworld /go/src/helloworld/
WORKDIR /go/src/helloworld
RUN go env -w GOPROXY=https://proxy.golang.com.cn,https://goproxy.cn,direct
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app .# 第二阶段:运行环境
FROM alpine:latest
ENV env1=env1value env2=env2value
MAINTAINER nick
LABEL hello=1.0.0
WORKDIR /app/
COPY --from=stage0 /go/src/helloworld/app ./
EXPOSE 80
CMD ["./app", "--param1=p1", "--param2=p2"]
4. 构建命令
docker build -t hello:1.0.0 -f Dockerfile .
四、ADD 与 COPY 指令对比实践

案例目标:理解 ADD 与 COPY 的功能差异。

1. 基础功能对比
FROM alpine:latest
WORKDIR /soft/# COPY 仅复制文件(不支持解压/URL)
COPY nginx-1.21.6.tar.gz ./copy/        # 复制本地文件
COPY srcDir/ ./destDir/                # 复制目录内容(不含目录本身)# ADD 支持解压和 URL
ADD https://nginx.org/download/nginx-1.21.6.tar.gz ./add/  # 从 URL 下载(不解压)
ADD nginx-1.21.6.tar.gz ./add/         # 解压本地压缩包
2. 多阶段构建中的应用
# 编译阶段
FROM golang:1.18 as stage0
COPY ./helloworld /go/src/helloworld/  # 推荐用 COPY 复制本地文件
WORKDIR /go/src/helloworld
RUN go build -o app .# 运行阶段
FROM alpine:latest
WORKDIR /app/
COPY --from=stage0 /go/src/helloworld/app ./
五、CMD 与 ENTRYPOINT 指令实践

案例目标:理解容器启动命令的不同配置方式。

1. CMD 指令案例
FROM alpine:latest
WORKDIR /app
COPY app ./
EXPOSE 80
CMD ["./app", "--param1=p1", "--param2=p2"]  # 默认启动命令# 运行时覆盖 CMD:
# docker run -d hello:1.0.0 ./app --param1=1 --param2=2
2. ENTRYPOINT 指令案例
FROM alpine:latest
WORKDIR /app
COPY app ./
EXPOSE 80
ENTRYPOINT ["./app"]  # 固定入口程序
CMD ["--param1=p1", "--param2=p2"]  # 为 ENTRYPOINT 提供默认参数# 运行时追加参数:
# docker run -d hello:1.0.0 --param1=1 --param2=2
# 替换入口程序:
# docker run --entrypoint sh hello:1.0.0
六、Build Arg 实践

案例目标:动态传递构建参数。

 
FROM golang:1.18 as s0
WORKDIR /go/src/app
RUN go env -w GOPROXY=$http_proxy  # 使用预定义参数FROM alpine:latest as s1
ARG wd=./app          # 定义默认参数
ARG label=myapp       # 镜像标签参数
ARG tag=1.0.0         # 镜像版本参数
RUN echo "工作目录: $wd, 标签: $label, 版本: $tag"
WORKDIR $wd
LABEL $label=$tag# 构建命令(传递参数):
# docker build --build-arg http_proxy=https://proxy... --build-arg wd=/home/app --tag hello:1.0.0 .
七、Target 与 Cache-From 实践

案例目标:加速多阶段构建,复用缓存

FROM golang:1.18 as s0
ADD ./helloworld /go/src/helloworld/
WORKDIR /go/src/helloworld
RUN go build -o app .FROM alpine:latest as s1
WORKDIR /app
COPY --from=s0 /go/src/helloworld/app ./# 分步构建:
# 1. 构建第一阶段并保存
docker build -t prehello:1.0.0 --target s0 .
# 2. 从缓存构建第二阶段
docker build -t hello:1.0.0 --cache-from prehello:1.0.0 --target s1 .
八、ONBUILD 指令实践

案例目标:定义基础镜像的下游构建行为。

1. 定义基础镜像
FROM golang:1.18
ONBUILD ADD ./helloworld /go/src/helloworld/  # 下游构建时触发
ONBUILD WORKDIR /go/src/helloworld
ONBUILD RUN go env -w GOPROXY=https://proxy.golang.com.cn,https://goproxy.cn,direct
ONBUILD RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app .# 构建基础镜像
docker build -t mygolang:1.0.0 .
2. 使用基础镜像构建应用
FROM mygolang:1.0.0 as s0  # 自动触发 ONBUILD 指令
FROM alpine:latest as s1
WORKDIR /app
COPY --from=s0 /go/src/helloworld/app ./
EXPOSE 80
ENTRYPOINT ["./app"]# 构建应用镜像(无需重复编写编译步骤)
docker build -t hello:1.0.0 .

6. dockerfile实践(c语言)

一、项目准备

1. 目录结构

创建项目目录 c-app-docker,包含:

  • src/:存放 C 源文件
  • Dockerfile:构建镜像的核心文件
2. 编写 C 程序

在 src/ 目录下创建 main.c,实现一个简单的 HTTP 服务(使用 libmicrohttpd 库)

// src/main.c
#include <stdio.h>
#include <microhttpd.h>#define PORT 8080static int handle_request(void *cls, struct MHD_Connection *connection,const char *url, const char *method,const char *version, const char *upload_data,size_t *upload_data_size, void **con_cls) {const char *response = "Hello, Docker C App!\n";struct MHD_Response *mhd_response;int ret;mhd_response = MHD_create_response_from_buffer(strlen(response), (void *)response, MHD_RESPMEM_PERSISTENT);ret = MHD_queue_response(connection, MHD_HTTP_OK, mhd_response);MHD_destroy_response(mhd_response);return ret;
}int main() {struct MHD_Daemon *daemon;daemon = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION, PORT, NULL, NULL,&handle_request, NULL, MHD_OPTION_END);if (NULL == daemon) {fprintf(stderr, "Failed to start MHD daemon\n");return 1;}printf("Server running on port %d...\n", PORT);getchar(); // 阻塞进程,避免退出MHD_stop_daemon(daemon);return 0;
}

二、Dockerfile 编写(多阶段构建优化)

使用 多阶段构建 分离编译环境与运行环境,最终镜像仅保留运行所需的最小依赖,体积更小、更安全。

Dockerfile 内容:
# ================================================
# 阶段1:编译环境(使用 GCC 编译 C 程序)
# ================================================
FROM gcc:13 as builder# 设置工作目录
WORKDIR /app# 安装依赖库(libmicrohttpd 用于 HTTP 服务)
RUN apt-get update && \apt-get install -y libmicrohttpd-dev && \rm -rf /var/lib/apt/lists/*# 复制 C 源文件到容器
COPY src/main.c ./# 编译 C 程序(生成可执行文件 app)
RUN gcc -o app main.c -lmicrohttpd# ================================================
# 阶段2:运行环境(仅保留运行所需的最小依赖)
# ================================================
FROM alpine:3.19# 安装运行时依赖(libmicrohttpd 库)
RUN apk add --no-cache libmicrohttpd# 设置工作目录
WORKDIR /app# 从编译阶段复制可执行文件(仅保留最终程序)
COPY --from=builder /app/app ./# 暴露服务端口(与 C 程序中定义的 PORT 一致)
EXPOSE 8080# 启动命令:运行编译后的可执行文件
CMD ["./app"]

三、镜像构建与运行

1. 构建镜像

在项目根目录(c-app-docker)下执行构建命令:

docker build -t c-http-server:1.0 .

说明

  • -t c-http-server:1.0:指定镜像名称为 c-http-server,标签为 1.0
  • 多阶段构建会自动跳过中间阶段(仅保留最后一个 FROM 后的内容),最终镜像体积远小于编译环境。
2. 运行容器
docker run -p 8080:8080 --name c-server -d c-http-server:1.0

参数说明

 
  • -p 8080:8080:将容器的 8080 端口映射到宿主机的 8080 端口。
  • --name c-server:指定容器名称为 c-server
  • -d:后台运行容器。
3. 验证服务

通过浏览器或命令行访问宿主机的 8080 端口:

curl http://localhost:8080

预期输出

Hello, Docker C App!

四、关键步骤说明

1. 多阶段构建的优势
  • 体积更小:编译阶段使用 gcc:13(约 1.2GB),运行阶段使用 alpine:3.19(约 5MB),最终镜像仅包含运行所需的 libmicrohttpd 库和可执行文件(总大小约 20MB)。
  • 更安全:运行环境不包含编译器、调试工具等冗余组件,减少攻击面。
2. 依赖管理
  • 编译阶段:通过 apt-get 安装 libmicrohttpd-dev(包含头文件和编译库)。
  • 运行阶段:通过 apk add 安装 libmicrohttpd(仅运行时库,无开发文件)。
3. 缓存优化
  • COPY src/main.c ./ 放在 RUN gcc 前,避免源文件修改时重复安装依赖(Docker 按指令顺序缓存,若 COPY 后修改 main.c,仅 RUN gcc 会重新执行)。

五、扩展实践建议

1. 静态编译(可选)

若需完全独立的可执行文件(不依赖宿主机库),可在编译阶段添加 -static 参数

# 阶段1 编译命令改为:
RUN gcc -o app main.c -lmicrohttpd -static

注意libmicrohttpd 可能不支持静态编译,需根据实际库的特性调整。

2. 健康检查

在 Dockerfile 中添加健康检查,确保服务正常运行:

HEALTHCHECK --interval=5s --timeout=3s \CMD curl -f http://localhost:8080/ || exit 1
3. 环境变量配置

若需动态配置端口或参数,可使用 ENV 和 ARG 指令:

# 在阶段2添加:
ARG PORT=8080
ENV APP_PORT=$PORT
EXPOSE $APP_PORT
CMD ["./app", "--port", "$APP_PORT"]

构建时指定参数

docker build -t c-http-server:1.0 --build-arg PORT=8090 .

 0voice · GitHub 

相关文章:

  • SpringBoot + VUE3 +deepseek实现的简单的AI对话页面(无广告,不会员)
  • 用QT写一个车速表
  • 如何在 CentOS / RHEL 上修改 MySQL 默认数据目录 ?
  • 【从零开始学习QT】Qt 概述
  • mysql prepare statement
  • Flink 状态管理深度解析:类型与后端的全面探索
  • DrissionPage:重新定义Python网页自动化,让爬虫与浏览器控制合二为一
  • Spring AI Alibaba 发布企业级 MCP 分布式部署方案
  • day12 leetcode-hot100-19(矩阵2)
  • 中山大学无人机具身导航新突破!FlightGPT:迈向通用性和可解释性的无人机视觉语言导航
  • ICDMC 2025:创新媒体模式,迎接数字时代的挑战
  • SpringBoot+tabula+pdfbox解析pdf中的段落和表格数据
  • 算力卡上部署OCR文本识别服务与测试
  • 基于深度学习的工业OCR实践:仪器仪表数字识别技术详解
  • Tesseract OCR 安装与中文+英文识别实现
  • c++设计模式-单例模式
  • 【Microsoft 365可用】PPT一键取消所有超链接
  • 私有化部署DeepSeek后行业数据模型的训练步骤
  • “顶点着色器”和“片元着色器”是先处理完所有顶点再统一进入片元阶段,还是一个顶点处理完就去跑它的片元?
  • 说说线程有几种创建方式
  • 长春高端模板建站/关键词权重如何打造
  • 萍乡建站公司/市场推广方案和思路
  • wordpress 上传 重命名/寰宇seo
  • 哪家公司做网站好/苏州seo培训
  • 网站服务器诊断/关键词挖掘站长工具
  • 佛山行业网站建设/搜什么关键词比较刺激