K8S执行MAC打出的本地镜像错误:exec /usr/local/bin/uvicorn: exec format error

容器里要执行的 /usr/local/bin/uvicorn 这个文件,当前系统根本没法按可执行程序格式运行。

也就是启动命令到了 uvicorn 这里,二进制格式或解释方式不对,所以报:

exec /usr/local/bin/uvicorn: exec format error

通常不是 FastAPI 代码本身的问题,而是镜像架构、基础镜像、启动脚本、换行符、shebang、构建方式这几类问题。

最常见原因

1)镜像架构不匹配

这是最常见的。

比如:

• 你在 Mac M 系列(arm64) 上构建了镜像

• 然后把镜像放到 x86_64 的 Linux/K8s 节点 上运行

或者反过来。

这样镜像里的可执行文件、Python、依赖脚本架构不匹配,就会报:

bash 复制代码
exec format error

典型场景

你本地是:

• MacBook M1 / M2 / M3 / M4:arm64

而服务器/K8s 节点通常是:

• 阿里云、腾讯云、普通 Intel/AMD 服务器:amd64

如果你直接:

bash 复制代码
docker build -t xxx .

在 Mac 上构建,再推到仓库,K8s 在 amd64 节点拉下来运行,就很容易出这个错误。

2)ENTRYPOINT / CMD 指向了错误格式的文件

例如 Dockerfile 里写了:

bash 复制代码
CMD ["/usr/local/bin/uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

但 /usr/local/bin/uvicorn 实际上:

• 不是正常可执行文件

• shebang 有问题

• 被损坏

• 是给别的架构安装出来的文件

也会报这个错。

3)脚本文件是 Windows 换行符 CRLF

如果你的启动脚本类似:

bash 复制代码
start.sh
entrypoint.sh

在 Windows 编辑过,变成了 CRLF,Linux 容器里执行时也可能报:

bash 复制代码
exec format error

尤其是 Dockerfile 中:

bash 复制代码
ENTRYPOINT ["/app/entrypoint.sh"]

这种特别常见。

4)基础镜像或依赖安装异常

例如你把某个二进制文件复制进去了,但它不是当前系统架构的版本。

比如:

• 从别的镜像里 COPY 了错误架构的 Python/uvicorn

• 手动装了不匹配平台的可执行文件

先判断是哪一种

你可以按这个顺序排查。

一、先看 K8s 节点架构

在节点上执行:

bash 复制代码
uname -m

常见结果:

• x86_64 = amd64

• aarch64 = arm64

再看镜像是按什么架构构建的。

二、看本地构建机器架构

本地如果是 Mac:

bash 复制代码
uname -m
复制代码
•	arm64 说明你是苹果芯片

如果你在这个机器上直接 docker build,默认很可能构出来的是 linux/arm64 镜像。

三、检查镜像架构

本地执行:

bash 复制代码
docker image inspect 你的镜像名 --format '{{.Architecture}}/{{.Os}}'

比如会看到:

bash 复制代码
arm64/linux

如果你的 K8s 节点是 x86_64,那就对不上了。

也可以看远端镜像支持的平台:

bash 复制代码
docker manifest inspect 你的镜像:tag

看里面是否包含:

• linux/amd64

• linux/arm64

四、进入镜像里检查 uvicorn

先本地起一个 shell:

bash 复制代码
docker run --rm -it --entrypoint /bin/sh 你的镜像

然后执行:

bash 复制代码
which uvicorn
ls -l /usr/local/bin/uvicorn
head -n 1 /usr/local/bin/uvicorn
file /usr/local/bin/uvicorn

你重点看:

情况 A:如果 uvicorn 是脚本

可能看到第一行类似:

bash 复制代码
#!/usr/local/bin/python

这说明它是 Python 脚本入口。

那就继续检查:

bash 复制代码
file /usr/local/bin/python
python --version

如果 python 本身架构不对,也会导致这个错。

情况 B:如果 file /usr/local/bin/uvicorn 显示异常

比如不是脚本、不是当前平台支持的 ELF 文件,那就说明镜像内容有问题。

五、如果你用了 entrypoint.sh,检查换行符

如果 Dockerfile 里类似:

bash 复制代码
COPY entrypoint.sh /app/entrypoint.sh
RUN chmod +x /app/entrypoint.sh
ENTRYPOINT ["/app/entrypoint.sh"]

进入容器检查:

bash 复制代码
cat -A /app/entrypoint.sh

如果每行末尾有 ^M,说明是 Windows 换行符 CRLF。

修复方式:

bash 复制代码
sed -i 's/\r$//' /app/entrypoint.sh

或者在本地先转成 LF。

最常见的真实根因:Mac 构建 ARM 镜像,K8s 跑 AMD 节点

你这个场景非常像这个。

尤其你前面一直在 Mac 上开发、再部署到 Linux/K8s,这种概率非常高。

解决办法

方案 1:构建指定 amd64 镜像

如果你的 K8s 节点是普通云服务器,基本都用这个:

bash 复制代码
docker buildx build --platform linux/amd64 -t 你的镜像:tag . --push

如果只是本地测试:

bash 复制代码
docker buildx build --platform linux/amd64 -t 你的镜像:tag --load .

然后再部署到 K8s。

方案 2:构建多架构镜像

这样 amd64 和 arm64 都能跑:

bash 复制代码
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t 你的镜像:tag \
  --push .

这样 K8s 节点会自动拉适合自己架构的版本。

方案 3:Dockerfile 里直接用 python -m uvicorn

有时候可以规避 uvicorn 启动脚本本身的问题。

把:

bash 复制代码
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

改成:

bash 复制代码
CMD ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

这样更稳一些。

方案 4:如果是启动脚本问题,修正 shebang 和换行符

例如:

bash 复制代码
#!/bin/sh

或者:

bash 复制代码
#!/usr/bin/env sh

并确保是 LF 换行,不是 CRLF。

Dockerfile 可加:

bash 复制代码
RUN sed -i 's/\r$//' /app/entrypoint.sh && chmod +x /app/entrypoint.sh

推荐你检查的 Dockerfile 写法

一个比较稳的 FastAPI Dockerfile 例子:

bash 复制代码
FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 8000

CMD ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

如果你项目入口不是 main:app,改成实际的,比如:

bash 复制代码
CMD ["python", "-m", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

在 K8s 中为什么会暴露出来

因为 K8s 本质上只是帮你运行镜像。

如果镜像本身有问题,比如:

• 架构错了

• ENTRYPOINT 文件坏了

• 启动脚本格式不对

那么到了 Pod 启动时就会直接失败,日志里就出现这个错。

你现在最应该做的 3 步

第 1 步:确认节点架构

bash 复制代码
kubectl get nodes -o wide

登录节点后:

bash 复制代码
uname -m

第 2 步:确认镜像架构

bash 复制代码
docker image inspect 你的镜像 --format '{{.Architecture}}/{{.Os}}'

或者看远端 manifest:

bash 复制代码
docker manifest inspect 你的镜像:t

ag

第 3 步:重新构建 amd64 镜像

如果节点是 x86_64,就直接重新构建:

bash 复制代码
docker buildx build --platform linux/amd64 -t 你的镜像:tag --push .

然后更新 K8s deployment:

bash 复制代码
kubectl rollout restart deployment 你的deployment名

一句话判断

如果你是 在 Mac M 系列上构建镜像,再部署到普通 Linux K8s 服务器,那这个错误 大概率就是镜像架构不匹配。

把你的 Dockerfile 和 Deployment YAML 发我,我可以直接帮你定位到底是:

• 镜像架构问题

• uvicorn 启动命令问题

• entrypoint 脚本换行符问题

• 还是镜像基础层有问题。

相关推荐
4t4run3 小时前
3、k8s安装
云原生·容器·kubernetes
未佩妥剑,已入江湖4 小时前
docker Windows下安装
运维·windows·docker·容器
小路恢弘7 小时前
xcode替换LLVM插件
ide·macos·xcode
love530love7 小时前
Duix-Avatar 去 Docker Desktop 本地化完整复盘
人工智能·pytorch·windows·python·docker·容器·数字人
文静小土豆7 小时前
深入理解 Kubernetes Pause 容器:Pod 的核心基石
kubernetes
janthinasnail7 小时前
升级docker-buildx
docker·容器
ChengQianO8 小时前
从 0 开始:Mac 下 UTM 虚拟机安装 ROS Noetic(Ubuntu 20.04)
linux·ubuntu·macos
KubeSphere 云原生8 小时前
云原生周刊:Kubernetes 1.36 要来了
云原生·容器·kubernetes
奥格列的魔法拖鞋~8 小时前
Docker安装OpenClaw并接入飞书
docker·容器·飞书·openclaw