为何Docker构建不具备跨平台性?同一Dockerfile在Ubuntu与macOS表现不同
问题:同一Dockerfile在Linux构建正常,macOS构建失败的原因
我编写了如下Dockerfile:
FROM python:3.8-slim-buster # Set environment variables ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONUNBUFFERED 1 ARG WORK_DIR=my-app # Create a new directory to keep the project files RUN mkdir $WORK_DIR # Copy local contents into container COPY ./ $WORK_DIR # Setting newly created directory as PWD WORKDIR $WORK_DIR # Installing system dependencies RUN apt-get update && apt-get install --no-install-recommends -y \ # Packages for building python build-essential \ # git CLI git # Installing pip packages RUN pip install pip -U && pip install psycopg2-binary==2.8.5
该Dockerfile在Ubuntu机器上构建镜像无任何问题,但在macOS机器上构建时出现错误,错误日志如下:
$ docker build -f Dockerfile . -t test-img [+] Building 16.3s (10/10) FINISHED docker:desktop-linux => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 654B 0.0s => [internal] load metadata for docker.io/library/python:3.8-slim-buster 2.5s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [1/6] FROM docker.io/library/python:3.8-slim-buster@sha256:8799b0564103a9f36cfb8a8e1c562e11a9a6f2e3bb214e2adc23982b36a04511 0.0s => [internal] load build context 0.0s => => transferring context: 5.16kB 0.0s => CACHED [2/6] RUN mkdir my-app 0.0s => [3/6] COPY ./ my-app 0.0s => [4/6] WORKDIR my-app 0.0s => [5/6] RUN apt-get update && apt-get install --no-install-recommends -y build-essential git 10.2s => ERROR [6/6] RUN pip install pip -U && pip install psycopg2-binary==2.8.5 3.5s ------ > [6/6] RUN pip install pip -U && pip install psycopg2-binary==2.8.5: 0.811 Requirement already satisfied: pip in /usr/local/lib/python3.8/site-packages (23.0.1) 0.932 Collecting pip 1.184 Downloading pip-24.0-py3-none-any.whl (2.1 MB) 1.496 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.1/2.1 MB 6.9 MB/s eta 0:00:00 1.536 Installing collected packages: pip 1.536 Attempting uninstall: pip 1.536 Found existing installation: pip 23.0.1 1.583 Uninstalling pip-23.0.1: 1.621 Successfully uninstalled pip-23.0.1 2.090 Successfully installed pip-24.0 2.090 WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv 2.719 Collecting psycopg2-binary==2.8.5 2.882 Downloading psycopg2-binary-2.8.5.tar.gz (381 kB) 3.055 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 381.7/381.7 kB 2.2 MB/s eta 0:00:00 3.106 Preparing metadata (setup.py): started 3.395 Preparing metadata (setup.py): finished with status 'error' 3.398 error: subprocess-exited-with-error 3.398 3.398 × python setup.py egg_info did not run successfully. 3.398 │ exit code: 1 3.398 ╰─> [23 lines of output] 3.398 running egg_info 3.398 creating /tmp/pip-pip-egg-info-7ualc3qt/psycopg2_binary.egg-info 3.398 writing /tmp/pip-pip-egg-info-7ualc3qt/psycopg2_binary.egg-info/PKG-INFO 3.398 writing dependency_links to /tmp/pip-pip-egg-info-7ualc3qt/psycopg2_binary.egg-info/dependency_links.txt 3.398 writing top-level names to /tmp/pip-pip-egg-info-7ualc3qt/psycopg2_binary.egg-info/top_level.txt 3.398 writing manifest file '/tmp/pip-pip-egg-info-7ualc3qt/psycopg2_binary.egg-info/SOURCES.txt' 3.398 3.398 Error: pg_config executable not found. 3.398 3.398 pg_config is required to build psycopg2 from source. Please add the directory 3.398 containing pg_config to the $PATH or specify the full executable path with the 3.398 option: 3.398 3.398 python setup.py build_ext --pg-config /path/to/pg_config build ... 3.398 3.398 or with the pg_config option in 'setup.cfg'. 3.398 3.398 If you prefer to avoid building psycopg2 from source, please install the PyPI 3.398 'psycopg2-binary' package instead. 3.398 3.398 For further information please check the 'doc/src/install.rst' file (also at 3.398 <https://www.psycopg.org/docs/install.html>). 3.398 3.398 [end of output] 3.398 3.398 note: This error originates from a subprocess, and is likely not a problem with pip. 3.399 error: metadata-generation-failed 3.399 3.399 × Encountered error while generating package metadata. 3.399 ╰─> See above for output. 3.399 3.399 note: This is an issue with the package mentioned above, not pip. 3.399 hint: See above for details. ------ Dockerfile:26 -------------------- 24 | 25 | # Installing pip packages 26 | >>> RUN pip install pip -U && pip install psycopg2-binary==2.8.5 -------------------- ERROR: failed to solve: process "/bin/sh -c pip install pip -U && pip install psycopg2-binary==2.8.5" did not complete successfully: exit code: 1
核心疑问:为何同一Dockerfile在Linux上可正常构建,在macOS上却失败?明明Docker构建应该不依赖主机系统,却出现了这种差异。
解答
这不是Docker构建依赖主机系统的问题,而是CPU架构差异导致的psycopg2-binary包安装行为不同:
架构差异背景
你的Ubuntu机器是x86_64架构,macOS机器大概率是Apple Silicon(arm64)架构。Docker在Apple Silicon上默认会构建arm64架构的镜像,而psycopg2-binary 2.8.5这个旧版本没有提供arm64预编译的轮子(wheel)包。具体原因
在x86_64的Ubuntu上构建时,pip会直接下载对应架构的预编译wheel包,不需要从源码编译,因此不需要pg_config工具;而在arm64的macOS上构建时,因为没有匹配的预编译wheel,pip会尝试从源码编译psycopg2-binary,而编译必须依赖pg_config(来自libpq-dev包),你的Dockerfile里没安装这个依赖,所以触发报错。解决方案
两种方式可选:- 修改Dockerfile,补充编译依赖
在安装系统依赖的步骤中加入libpq-dev,确保源码编译时能获取到pg_config:# Installing system dependencies RUN apt-get update && apt-get install --no-install-recommends -y \ # Packages for building python build-essential \ # git CLI git \ # Dependency for psycopg2 compilation libpq-dev - 指定构建x86_64架构镜像
在macOS上执行构建命令时指定平台,让pip下载x86_64的预编译wheel,避免源码编译:
这种方式依赖QEMU模拟x86_64环境,性能不如原生arm64镜像。docker build --platform linux/amd64 -f Dockerfile . -t test-img
- 修改Dockerfile,补充编译依赖
内容的提问来源于stack exchange,提问作者JPG
相关产品推荐
相关产品推荐

