彻底解决docker build时安装软件失败问题

本文介绍了在构建Dockerfile时遇到的软件安装失败问题,特别是使用Alpine镜像时。通过分析日志,发现网络请求可能通过Google DNS解析,导致构建失败。为了解决这个问题,提出了两种方案:一是修改宿主机文件,二是调整Docker守护进程配置,例如使用dnspod DNS。文中提供了具体的操作步骤和参考资料。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近遇到一个问题,构建Dockerfile镜像时,如果安装软件,有一定概率失败(2%-10%)。以alpine为例

失败日志如下

Step 4/6 : RUN echo -e "https://mirrors.ustc.edu.cn/alpine/latest-stable/main\nhttps://mirrors.ustc.edu.cn/alpine/latest-stable/community" > /etc/apk/repositories &&     apk update &&     apk add tzdata &&     cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime &&     echo "Asia/Shanghai" >  /etc/timezone &&     rm -rf /var/cache/apk/*
 ---> Running in bd5d1dfd3ff4
fetch https://mirrors.ustc.edu.cn/alpine/latest-stable/main/x86_64/APKINDEX.tar.gz
fetch https://mirrors.ustc.edu.cn/alpine/latest-stable/community/x86_64/APKINDEX.tar.gz
v3.6.2-83-g1079181bed [https://mirrors.ustc.edu.cn/alpine/latest-stable/main]
v3.6.2-84-g6ee501e465 [https://mirrors.ustc.edu.cn/alpine/latest-stable/community]
OK: 8440 distinct packages available
(1/1) Installing tzdata (2017a-r0)
ERROR: tzdata-2017a-r0: temporary error (try again later)复制代码

为了重现该问题,简单的构建一个Docker 镜像,基于alpine,安装tzdata,并设置北京时区

为了加速构建,替换为中科大的镜像地址

Dockerfile

FROM alpine
RUN echo -e "https://mirrors.ustc.edu.cn/alpine/latest-stable/main\nhttps://mirrors.ustc.edu.cn/alpine/latest-stable/community" > /etc/apk/repositories && \
    apk update &&\
    apk --no-cache add tzdata && \
    cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
    echo "Asia/Shanghai" >  /etc/timezone复制代码

其实一开始没有用国内源,用的官方,但是经常失败,以为是墙的问题,辗转换过阿里云镜像,清华镜像,中科大镜像,甚至后来自建镜像 github repo anjia0532/alpine-package-mirror , 三种方法解决docker构建失败(alpine),但是都是时好时坏,严重影响效率。

后来在观察nginx访问日志的时候,报错的时候nginx没有产生访问日志,遂怀疑是构建镜像时没有发出网络请求,祭出神器 tcpdump 进行进一步排查

note

为了减少干扰,实验机器中,没有其他docker服务在跑(否则tcp请求太多)

sudo tcpdump -i docker0

....

10:47:43.038404 IP6 :: > ff02::16: HBH ICMP6, multicast listener report v2, 1 group record(s), length 28
10:47:43.114734 ARP, Request who-has 172.17.0.1 tell 172.17.0.2, length 28
10:47:43.114746 ARP, Reply 172.17.0.1 is-at 02:42:30:19:53:45 (oui Unknown), length 28
10:47:43.114750 IP 172.17.0.2.48223 > google-public-dns-a.google.com.domain: 18503+ A? alpine.xxx.com. (39)
10:47:43.114775 IP 172.17.0.2.48223 > google-public-dns-b.google.com.domain: 18503+ A? alpine.xxx.com. (39)
10:47:43.114827 IP 172.17.0.2.48223 > google-public-dns-a.google.com.domain: 18687+ AAAA? alpine.xxx.com. (39)
10:47:43.114833 IP 172.17.0.2.48223 > google-public-dns-b.google.com.domain: 18687+ AAAA? alpine.xxx.com. (39)
10:47:43.209679 IP google-public-dns-a.google.com.domain > 172.17.0.2.48223: 18503 1/0/0 A 172.60.20.6 (55)
10:47:43.229261 IP google-public-dns-a.google.com.domain > 172.17.0.2.48223: 18687 0/1/0 (106)

....复制代码

发现在构建的时候,是走的google的dns进行解析的,因为众多不可描述的问题,google在国内基本是瘫痪状态(google翻译例外)

Filtering is necessary because all localhost addresses on the host are unreachable from the container’s network. After this filtering, if there are no more nameserver entries left in the container’s /etc/resolv.conf file, the daemon adds public Google DNS nameservers (8.8.8.8 and 8.8.4.4) to the container’s DNS configuration. If IPv6 is enabled on the daemon, the public IPv6 Google DNS nameservers will also be added (2001:4860:4860::8888 and 2001:4860:4860::8844).

原文见官方文档 Embedded DNS server in user-defined networks

两种方案,

  1. 修改宿主机的hosts文件,写死ip
  2. 修改Docker的daemon.json文件

推荐用第二种,参考一下官方文档 DAEMON CONFIGURATION FILE#On Linux

更合理的方案是修改docker的daemon.json sudo vi /etc/docker/daemon.json

比如改成dnspod dns

增加 "dns": ["119.29.29.29"]

然后sudo systemctl daemon-reload

11:14:17.586559 ARP, Request who-has 172.17.0.1 tell 172.17.0.2, length 28
11:14:17.586577 ARP, Reply 172.17.0.1 is-at 02:42:30:19:53:45 (oui Unknown), length 28
11:14:17.586581 IP 172.17.0.2.43273 > pdns.dnspod.cn.domain: 53616+ A? alpine.xxx.com. (39)
11:14:17.586604 IP 172.17.0.2.43273 > pdns.dnspod.cn.domain: 53868+ AAAA? alpine.xxx.com. (39)
11:14:17.777921 IP pdns.dnspod.cn.domain > 172.17.0.2.43273: 53868 0/1/0 (106)
11:14:17.843875 IP pdns.dnspod.cn.domain > 172.17.0.2.43273: 53616 1/0/0 A 172.60.20.6 (55)
11:14:17.844028 IP 172.17.0.2.36810 > 172.60.20.6.http: Flags [S], seq 4032628285, win 42340, options [mss 1460,sackOK,TS val 1959807306 ecr 0,nop,wscale 11], length 0复制代码

整个过程可参见我在中科大 github的issues alpine 镜像频繁异常

博客 anjia.ml/2017/09/01/…
掘金 juejin.im/post/59a8f9…
简书 www.jianshu.com/p/1f4e62dff…

### 解决 Windows 下 Docker 安装过程中常见错误 #### WSL2 错误处理 当在 Windows 上安装 Docker Desktop 并启用 WSL2 后端,可能会遇到各种配置和兼容性问题。如果收到有关 WSL2 的错误提示,建议先确认已正确安装并启用了适用于 Linux 的 Windows 子系统 (WSL)[^1]。 对于具体的 WSL2 错误消息,通常可以通过以下方式排查: - 执行 `wsl --list --verbose` 查看当前安装的所有发行版及其状态。 - 使用命令 `wsl --set-default-version 2` 将默认版本设置为 WSL2。 - 更新到最新版本的 WSL 和内核组件,可通过 PowerShell 命令 `wsl --update` 实现。 这些操作有助于确保 WSL2 处于最佳工作状态,从而减少因环境不匹配而导致的安装失败情况。 #### 验证 Docker 卸载是否彻底完成 有旧版本残留文件可能干扰新版本的正常安装。为了防止这种情况发生,在重新安装之前应完全清除之前的 Docker 数据目录。这一步骤涉及删除位于 `/var/lib/docker/` 路径下的所有数据,具体做法如下所示[^2]: ```bash cd /var/lib/docker/ rm -rf * ``` 之后再次尝试执行 `docker -v` 来验证 Docker 是否已被成功移除;若显示未找到该指令,则说明卸载干净,可继续进行全新安装流程。 #### GitLab 权限错误解决方案 针对某些特定应用如 GitLab 可能会碰到容器内部权限不足的情况。此除了调整宿主机上的共享卷挂载选项外,还可以考虑通过重建官方提供的 GitLab CE 社区版镜像来规避潜在的风险因素[^3]: ```bash docker build -t gitlab/gitlab-ce . ``` 此命令将会依据项目根目录里的 Dockerfile 文件定义重制一个新的 GitLab 映像实例,进而绕过原有映像中存在的任何权限设定缺陷。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值