一次dockerfile的循环依赖错误实战记录

 更新时间:2025年02月08日 08:33:10   作者:phantom_111  
Dockerfile 是一个文本文件,其内包含了一条条的指令,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建,这篇文章主要介绍了使用Docker多阶段构建时遇到的循环依赖问题及其解决方法,,需要的朋友可以参考下

1. 写在最前面

笔者在使用 dockerfile 多阶段构建的功能时,写出了一个「circular dependency detected on stage: xx」的错误。

解决方式:解耦互相依赖的构建阶段即可,构建 A <=> 构建 B 两个阶段是互相依赖的,改为构建 A => 构建 B

注:「多阶段构建」是 Docker 提供的一种功能,运行用户在一个 Dockerfile 中定义多个构建阶段,从而优化构镜像的大小和构建过程的效率。通过这种方式,开发者可以在不同的阶段使用不同的基础镜像和工具,最终只将所需要的文件和依赖项复制到最终的镜像中。

但是,作为一个有求知精神的软件开发工程师,笔者去翻看了一下源码的位置。(ps: 其实就是自己感兴趣 BuildKit 的源码想要学习一下,而带着问题学习的速度更快)

1.1 具体循环依赖的例子

FROM busybox AS stage0
COPY --from=stage0 f1 /sub/ 
  • FROM busybox AS stage0: 这行代码定义了一个名为 stage0 的构建阶段,并使用 busybox 作为基础镜像。

  • COPY --from=stage0 f1 /sub/: 这行代码尝试从名为 stage0 的构建阶段复制文件 f1 到 /sub/ 目录。

在这个情况下,在同一个构建阶段中同时定义了一个新的阶段并尝试从该阶段复制文件。这会导致 Docker 无法解析这个依赖关系,因为 stage0 还没有完成构建就被引用了。

2. 报错的位置

源码仓库:GitHub - moby/buildkit: concurrent, cache-efficient, and Dockerfile-agnostic builder toolkit

具体位置:buildkit/frontend/dockerfile/dockerfile2llb/convert.go at master · moby/buildkit · GitHub

2.1 代码快速分析

得益于 Github 支持了 Codespaces 让笔者可以无需代码下载到本地,可以直接基于 Codespaces 对 「convert_test.go」的具体 case 直接做在线 debug ,逐行分析。

注:GitHub Codespaces 是一个基于云的开发环境,允许开发者在浏览器中创建和使用完整的开发环境。它旨在简化开发流程,特别是对于团队协作和快速启动项目。以下是 GitHub Codespaces 的一些关键特性和功能:

代码 debug 效果:

注:感慨一下 Codespaces 真的香!

2.2 代码总结

核心的循环依赖检测逻辑代码如下:

func validateCircularDependency(states []*dispatchState) error {
	var visit func(*dispatchState, []instructions.Command) []instructions.Command
	if states == nil {
		return nil
	}
	visited := make(map[*dispatchState]struct{})
	path := make(map[*dispatchState]struct{})

	visit = func(state *dispatchState, current []instructions.Command) []instructions.Command {
		_, ok := visited[state]
		if ok {
			return nil
		}
		visited[state] = struct{}{}
		path[state] = struct{}{}
		for dep, c := range state.deps {
			next := append(current, c)
			if _, ok := path[dep]; ok {
				return next
			}
			if c := visit(dep, next); c != nil {
				return c
			}
		}
		delete(path, state)
		return nil
	}
	for _, state := range states {
		if cmds := visit(state, nil); cmds != nil {
			err := errors.Errorf("circular dependency detected on stage: %s", state.stageName)
			for _, c := range cmds {
				err = parser.WithLocation(err, c.Location())
			}
			return err
		}
	}
	return nil
}

核心分析:它使用深度优先搜索(DFS)的方式来检测循环依赖,并在发现循环时返回一个错误。

注:看来不是算法没有用,是业务逻辑的代码中使用 DFS 这种算法的场景比较少,还是得多看源码

2.3 关于 parser 的记录

对于 dockerfile 的 parser 也有点兴趣,后面要继续抽个时间深入分析一下。笔者当前负责的模块重构成一个通用的 parser 的话,代码的复用率会更高一点。希望后面有时间可以优化改进一波

总结

到此这篇关于一次dockerfile的循环依赖错误的文章就介绍到这了,更多相关dockerfile循环依赖错误内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Docker无法登录与推送问题解决的详细教程

    Docker无法登录与推送问题解决的详细教程

    这篇文章主要介绍了如何使用阿里云容器镜像服务来解决国内访问Docker Hub速度慢的问题,并详细描述了如何设置阿里云镜像服务、配置Docker、操作镜像(包括pull和push)以及测试拉取镜像的过程,需要的朋友可以参考下
    2025-02-02
  • 给docker配置指定ip的超详细图解

    给docker配置指定ip的超详细图解

    这篇文章主要给大家介绍了关于给docker配置指定ip的超详细图解教程,Docker容器的IP地址由Docker守护进程动态分配,默认情况下,它使用的是宿主机的IP地址,但是在某些情况下,您可能需要为Docker容器指定静态IP地址,需要的朋友可以参考下
    2023-09-09
  • Prometheus 整合 AlertManager的教程详解

    Prometheus 整合 AlertManager的教程详解

    Alertmanager 主要用于接收 Prometheus 发送的告警信息,它很容易做到告警信息的去重,降噪,分组,策略路由,是一款前卫的告警通知系统。这篇文章主要介绍了Prometheus 整合 AlertManager的教程 ,需要的朋友可以参考下
    2019-07-07
  • docker实现mysql主从复制的示例代码

    docker实现mysql主从复制的示例代码

    Docker它不香吗?即省去了安装Mysql所需要的步骤,有多个容器之间相互资源独立,IP互不冲突,具有一定的参考价值,感兴趣的可以了解一下
    2021-08-08
  • 国内服务器配置Docker国内源(极限加速)

    国内服务器配置Docker国内源(极限加速)

    本文主要介绍了国内服务器配置Docker国内源,用户可以在CentOS服务器上成功安装并使用国内镜像加速器来提升Docker的使用,感兴趣的可以了解一下
    2025-02-02
  • 在Docker容器中不需要运行sshd的原因浅析

    在Docker容器中不需要运行sshd的原因浅析

    在一个容器中运行SSH服务器,这真的是一个错误(大写字母W)吗?老实说,没那么严重。当你不去访问Docker主机的时候,这样做甚至是极其方便的,但是这仍然需要在容器中取得一个shell
    2016-11-11
  • 将spring boot应用打入docker中运行的实现方法

    将spring boot应用打入docker中运行的实现方法

    这篇文章主要介绍了将spring boot应用打入docker中运行的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-07-07
  • docker start启动容器后仍然exit状态的解决

    docker start启动容器后仍然exit状态的解决

    这篇文章主要介绍了docker start启动容器后仍然exit状态的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • Docker 容器文件系统详细介绍(图文)

    Docker 容器文件系统详细介绍(图文)

    这篇文章主要介绍了Docker 容器文件系统详细介绍(图文)的相关资料,这里对Docker 容器文件系统进行了具体的分析详解,需要的朋友可以参考下
    2016-12-12
  • Docker Compose从安装到使用详细过程

    Docker Compose从安装到使用详细过程

    Docker Compose是Docker官方提供的一个工具,用于定义和运行多容器 Docker应用程序,本文给大家介绍Docker Compose从安装到使用详细过程,感兴趣的朋友跟随小编一起看看吧
    2025-09-09

最新评论