dockerfile 中的 RUN 命令产生的结果与在容器内手动运行相同命令的结果不同

2024-02-02

我正在创建一个包含 gcc 4.8.5 的 Ubuntu 12.04 docker 映像。我正在获取 gcc 4.8.5 源代码并自己构建它。该容器将在 Ubuntu 18.04 主机上运行。

引用底部的代码,如果我不将其放入 dockerfile 并在启动容器后运行相同的命令,则构建工作正常,但是如果我在 dockerfile 中使用 RUN 代替,则会收到以下构建错误

In file included from /usr/include/stdio.h:28:0,
             from ../../../gcc-4.8.5/libgcc/../gcc/tsystem.h:87,
             from ../../../gcc-4.8.5/libgcc/libgcc2.c:27:
/usr/include/features.h:324:26: fatal error: bits/predefs.h: No such 
file or directory
#include <bits/predefs.h>
                      ^

该问题似乎源于 ./gcc-4.8.5/configure 调用。 当在容器内运行时我得到:

checking build system type... i686-pc-linux-gnu

当放入 dockerfile 时我得到:

checking build system type... x86_64-unknown-linux-gnu

有人可以填写我对 dockerfiles 中 RUN 的理解吗,因为我觉得我缺少一些关于它如何工作的信息。我的印象是这些命令会在上一层运行?但看起来它们正在我的主机上运行。

## Get gcc 4.8.5 and build it
RUN wget ftp://gcc.gnu.org/pub/gcc/releases/gcc-4.8.5/gcc-4.8.5.tar.gz \
&& tar xzf gcc-4.8.5.tar.gz && \
cd gcc-4.8.5 && \
./contrib/download_prerequisites && \
cd .. && mkdir gccbuild && cd gccbuild && \
../gcc-4.8.5/configure \
--prefix="/opt/gcc" \
--enable-shared --with-system-zlib --enable-threads=posix \
--enable-__cxa_atexit --enable-checking --enable-gnu-indirect-function \
--enable-languages="c,c++" --disable-bootstrap \
&& make all && make install 

EDIT:

docker build -t 12.04_builder - < dockerfile
docker run -i -t 12.04_builder

完整的dockerfile:

FROM jnickborys/i386-ubuntu:12.04

RUN apt-get update && \ 
    apt-get install -y \ 
      wget \
      build-essential \
      libssl-dev \
      git \
      asciidoc \
      libpulse-dev \
      libasound2-dev \
      libpcsclite-dev 

## Get latest cmake that has a 32-bit version
RUN wget https://github.com/Kitware/CMake/releases/download/v3.6.3/cmake-3.6.3-Linux-i386.sh && \ 
    chmod +x cmake-3.6.3-Linux-i386.sh && \ 
    ./cmake-3.6.3-Linux-i386.sh --skip-license --prefix=/usr

## Get gcc 4.8.5 and build it
RUN wget ftp://gcc.gnu.org/pub/gcc/releases/gcc-4.8.5/gcc-4.8.5.tar.gz \
    && tar xzf gcc-4.8.5.tar.gz && \
    cd gcc-4.8.5 && \
    ./contrib/download_prerequisites && \
    cd .. && mkdir gccbuild && cd gccbuild && \
    ../gcc-4.8.5/configure \
    --prefix="/opt/gcc" \
    --enable-shared --with-system-zlib --enable-threads=posix \
    --enable-__cxa_atexit --enable-checking --enable-gnu-indirect-function \
    --enable-languages="c,c++" --disable-bootstrap 
    && make all && make install

首先,有一点背景知识:构建期间运行的平台检测脚本使用uname(1)效用(因此uname(2)系统调用)来识别它运行的硬件:

root@6e4b69adfd4c:/gcc-4.8.5# grep 'uname -m' config.guess 
UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown

在您的 64 位机器上uname -m回报x86_64。但是,有一个系统调用可以覆盖此结果:personality(2)。当进程调用personality(2),它及其后续的分叉(子级)在调用时开始看到假结果uname(2)。因此,有可能要求内核提供虚假的硬件信息uname(2).

您使用的基础镜像(jnickborys/i386-ubuntu:12.04) 包含 32 位二进制文​​件并定义入口点/usr/bin/linux32,这称为personality(PER_LINUX32)要求内核假装它在 32 位硬件上运行并返回i686 in uname(2)(这可以使用检查docker inspect and strace分别)。这使得可以假装容器化进程在 32 位环境中运行。

执行构建有什么区别RUN在容器中指令并手动?

当您执行构建时RUN,Docker 不使用入口点来运行命令。它使用中指定的内容SHELL相反(默认是/bin/sh -c)。这意味着运行构建的 shell 的特性不会改变,并且它(和子进程)可以看到真实的硬件信息 -x86_64,因此,你得到x86_64-unknown-linux-gnu在 32 位环境中构建系统类型并且构建失败。

当您在容器中手动运行构建时(例如,在使用docker run -it jnickborys/i386-ubuntu:12.04然后执行与 Dockerfile 中相同的步骤),调用入口点,因此,个性被改变,并且内核开始报告它在 32 位硬件上运行(i686),所以你得到i686-pc-linux-gnu构建系统类型,并且构建正确运行。

如何解决这个问题?取决于你想要什么。如果您的目标是为 64 位环境构建 gcc,则只需使用 64 位基础映像即可。如果您想构建 32 位环境,您的选择之一是更改SHELL被用于RUN在这些之前RUNs:

SHELL ["/usr/bin/linux32", "/bin/sh", "-c"]

这将使 Docker 执行RUNs 具有改变的个性,因此,构建系统类型将被正确检测(i686-pc-linux-gnu)并且构建将会成功。如果需要,您可以更改SHELL回到/bin/sh -c构建后。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

dockerfile 中的 RUN 命令产生的结果与在容器内手动运行相同命令的结果不同 的相关文章

  • 在主目录中安装库

    在 Linux Ubuntu 中 我尝试运行一个工具 但它显示错误 库丢失 我无权在系统中安装任何内容 或者根本无法从我的用户帐户执行 sudo 是否可以在我的主目录 没有 sudo 中安装缺少的库 在我的例子中为 libstdc so 6
  • 并行运行 make 时出错

    考虑以下制作 all a b a echo a exit 1 b echo b start sleep 1 echo b end 当运行它时make j2我收到以下输出 echo a echo b start a exit 1 b star
  • 如何模拟ARM处理器运行环境并加载Linux内核模块?

    我尝试加载我的vmlinux into gdb并使用 ARM 内核模拟器 但我不明白为什么我会得到Undefined target command sim 这是外壳输出 arm eabi gdb vmlinux GNU gdb GDB 7
  • Godaddy 托管上的 CakePHP 控制台

    我一直在努力让我的 CakePHP 网站在 Godaddy 网格托管 帐户上运行 我的蛋糕应用程序设置是从帐户的子目录托管的 并且可以通过子域访问 我必须调整我的 htaccess 文件才能使其正常工作 现在我需要让 CakePHP 控制台
  • ansible 重新启动 2.1.1.0 失败

    我一直在尝试创建一个非常简单的 Ansible 剧本 它将重新启动服务器并等待它回来 我过去在 Ansible 1 9 上有一个可以运行的 但我最近升级到 2 1 1 0 并且失败了 我正在重新启动的主机名为 idm IP 为 192 16
  • 在 docker 中将 pgadmin 连接到 postgres

    我有一个docker compose与服务文件python nginx postgres and pgadmin services postgres image postgres 9 6 env file env volumes postg
  • Locale.getDefault() 始终返回 en

    unix 机器上的服务器始终使用 en 作为默认区域设置 以下是区域设置输出 LANG en US LC CTYPE C LC NUMERIC C LC TIME C LC COLLATE C LC MONETARY C LC MESSAG
  • 在 Mac OS X 上从 boot2docker 迁移到 Vagrant+NFS 的最快方法是什么?

    我有一个从官方 mysql 构建的数据库容器docker pull mysql 我有一个前端应用程序app用蛋糕建造 我有一个后端应用程序cms使用 Symfony 构建 我为两者都设置了容器链接app and cms自动启动并连接到db
  • Unix 命令列出包含字符串但*不*包含另一个字符串的文件

    如何递归查看包含一个字符串且不包含另一个字符串的文件列表 另外 我的意思是评估文件的文本 而不是文件名 结论 根据评论 我最终使用了 find name html exec grep lR base maps xargs grep L ba
  • 使用 find - 删除除任何一个之外的所有文件/目录(在 Linux 中)

    如果我们想删除我们使用的所有文件和目录 rm rf 但是 如果我希望一次性删除除一个特定文件之外的所有文件和目录怎么办 有什么命令可以做到这一点吗 rm rf 可以轻松地一次性删除 甚至可以删除我最喜欢的文件 目录 提前致谢 find ht
  • 如何从 AWS SAM 本地 docker 实例连接到主机 MySQL?

    我正在尝试使用调用我的 Lambda 函数sam local invoke但发现无法连接到我的主机MySQL 我尝试添加 docker network host但也无法连接 Traceback most recent call last F
  • Elasticsearch 无法写入日志文件

    我想激活 elasticsearch 的日志 当我运行 elasticsearch 二进制文件时 我意识到我在日志记录方面遇到问题 无法加载配置 这是输出 sudo usr share elasticsearch bin elasticse
  • 如何从连接到外部网络的另一个组合访问容器?

    这是带有容器配置的撰写文件 我希望从外部容器连接到该容器 在另一个撰写文件中定义 version 3 5 services service to connect to build networks my external network n
  • awk 子串单个字符

    这是columns txt aaa bbb 3 ccc ddd 2 eee fff 1 3 3 g 3 hhh i jjj 3 kkk ll 3 mm nn oo 3 我可以找到第二列以 b 开头的行 awk if substr 2 1 1
  • 强制卸载 NFS 安装目录 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 Locked 这个问题及其答案是locked help locked posts因为这个问题是题外话 但却具有历史意义 目前不接受新的答案
  • 如何在 Linux 中编写文本模式 GUI? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 当我编写脚本 程序时 我经常想弹出一个简单的文本 gui 来提示输入 我该怎么做 例如 来自 Shel
  • Linux TUN/TAP:无法从 TAP 设备读回数据

    问题是关于如何正确配置想要使用 Tun Tap 模块的 Linux 主机 My Goal 利用现有的路由软件 以下为APP1和APP2 但拦截并修改其发送和接收的所有消息 由Mediator完成 我的场景 Ubuntu 10 04 Mach
  • Docker - SequelizeConnectionRefusedError:连接 ECONNREFUSED 127.0.0.1:3306

    我正在尝试使用 Docker 容器启动并运行我的 Nodejs 应用程序 我不知道可能出了什么问题 当我使用控制台调试凭据时 凭据似乎已正确传递 另外启动sequel pro并使用相同的用户名和密码直接连接似乎也可行 当节点在容器中启动时
  • 如何在bash中使用jq从变量中包含的json中提取值

    我正在编写一个 bash 脚本 其中存储了一个 json 值 现在我想使用 Jq 提取该 json 中的值 使用的代码是 json val code lyz1To6ZTWClDHSiaeXyxg redirect to http examp
  • 无法访问本地 Docker 容器上的 Asp.Net Core

    我在 asp net core 中创建了一个应用程序 并创建了一个 dockerfile 来生成本地映像并运行它 FROM microsoft dotnet latest COPY app WORKDIR app RUN dotnet re

随机推荐

  • 如何从 C# 应用程序调用带有 void 指针的 C++ 函数?

    我有一个动态库 dll 用 C 编写 导出我想在 C 应用程序中使用的函数 int SendText void pControl char sText 鉴于它需要一个指向 void 的指针 我该怎么办 for void 你可以使用IntPt
  • 如何添加在 OSX 上按预期工作的菜单项分隔符?

    On Windows平台 与VCL 当我们想要添加一个分隔器在菜单中 我们添加一个TMenuItem with a Caption With 火猴 我们添加一个TMenuItem with a Text 它在 Windows 平台上按预期工
  • QtCreator Build 不会更新设计表单中的 UI 更改

    我的 Qt 项目使用影子构建 当我更改 MainWindow 表单 ui 文件 时 我构建了项目 但我的程序没有更新 GUI 如果我重建所有 GUI 将被更新 但重建速度非常非常慢 我尝试创建一个新项目 带有一些标签的空 QMainWind
  • MKMapView:获取注释图钉上的点击事件

    我正在使用一个MKMapView包含几个MKAnnotation pins 在地图上方我显示了UITableView的详细信息MKAnnotation pins 我的问题 当我选择一个引脚时 我想选择相应的表格单元格 为此 如果选择了引脚
  • show() 接受 1 个位置参数,但给出了 2 个

    我对我一直在处理的代码得到了一些很好的反馈 并且我已经得到了在 google collab 上运行的所有内容 但是当我在 Visual studio 上运行完全相同的代码时 我得到的错误是这样的 发生异常 类型错误 show 接受 1 个位
  • 一个好的 Java 排序列表

    我正在寻找一个好的java排序列表 谷歌搜索给了我一些关于使用 TreeSet TreeMap 的提示 但这些组件缺少一件事 随机访问集合中的元素 例如 我想访问排序集中的第 n 个元素 但对于 TreeSet 我必须迭代其他 n 1 个元
  • tkinter 小部件 ipad(x/y) 的工作方式与 pad(x,y) 不同

    我可以自定义外部填充所有四个侧面tkinter 小部件的使用 widget grid 0 0 padx left pad right pad pady top pad bottom pad 但是 当我更换padx and pady with
  • 对所有数组元素进行类型检查

    是否有任何简单的方法可以检查数组的所有元素是否都是特定类型的实例 而无需循环所有元素 或者至少有一种从数组中获取 X 类型的所有元素的简单方法 s array abd 10 10 1 s array map gettype s t arra
  • 函数的右值引用和返回值

    我是 c 11 的新手 在阅读时有以下问题C 11 常见问题解答 http www stroustrup com C 11FAQ html rval 假设我们有一个函数f 返回类型的值X 那么我们有以下几种方式来存储它的返回值 X a f
  • 无法更改 Google Cardboard 相机的 FOV

    我正在使用 Google Card Board Unity SDK 开发 Android 狙击手游戏 现在需要调整相机的 FOV 这导致我与 CardBoard cs 中名为 mockFieldOfView 的变量进行交互 在 Unity
  • Vue-cli 3:“命令失败:npm install --loglevel 错误”

    每次我尝试创建一个新项目 vue create my project 我收到此错误 错误 命令失败 npm install loglevel 错误 我使用的是 PC Windows 10 Vue cli 3 2 1 Node 8 11 3
  • 如何将 ReadonlyArray 转换为 any[]?

    一些本机角度函数返回 ReadonlyArray 一些本机角度回调传递 ReadonlyArrays 由于我的打字稿代码可能以多种方式调用 因此我不想要求传递给我的函数的所有数组都是 ReadonlyArrays 因此我需要将 Readon
  • 在 Android 中使用新 Material Design 主题的颜色

    我正在设计 Android 应用程序 并决定尝试新的 Material 主题 我在网上找到了新主题的所有可用配色方案 但无法找到包含调色板中所有颜色的相应 xml 文件 有谁知道我在哪里可以找到这个 以便我可以在我的风格中使用这些颜色 这是
  • 无法将脚本名称识别为 cmdlet、函数等;在简单的脚本中也找不到位置参数

    我正在尝试做我的第一个剧本 要简单地让 PowerShell 提取在记事本中输入的脚本并保存为标题为 test 的 ps1 文件 也尝试过脚本 但知道名称与它无关 Write Host Hello World 在 PowerShell 中我
  • ImageView和设置位置

    我有 imageView 活动 我如何在我的活动中设置此 imageView 的位置 我知道如何在 xml 文件中执行此操作 但我想在活动中执行此操作 因为我有 onTouch 方法 可以在其中获取单击的坐标 并且我想在此坐标中绘制此图像
  • 编辑链接列表中的节点

    我正在创建一个学生列表 链接列表 可以添加 查看和编辑学生信息 我有两个字段 即学生姓名和学生成绩 我在列表中添加新学生 其方式是根据学生的成绩降序排列 我已经完成了添加和查看部分 问题出在编辑部分 因为我需要编辑信息 然后我需要再次对其进
  • 将数据表放入shinyjs模式中

    我将 Shiny 与 Shiny Semantic 库一起使用 以使应用程序看起来不错 使用 showModal modalDialog 的标准 Shiny 弹出消息不适用于 Semantic UI 因此我求助于shinyjs 来使用一些
  • 使用 Javascript 更改 CSS 值

    使用 javascript 设置内联 CSS 值很容易 如果我想改变宽度并且我有这样的html div style width 10px div 我需要做的就是 document getElementById id style width
  • 单选按钮组 XAML

    我在 XAML 中有六个单选按钮 我想创建两个组 WPF 似乎没有单选按钮组元素 那么我该怎么做呢 您必须为元素指定一个 GroupName
  • dockerfile 中的 RUN 命令产生的结果与在容器内手动运行相同命令的结果不同

    我正在创建一个包含 gcc 4 8 5 的 Ubuntu 12 04 docker 映像 我正在获取 gcc 4 8 5 源代码并自己构建它 该容器将在 Ubuntu 18 04 主机上运行 引用底部的代码 如果我不将其放入 dockerf