Docker|--镜像中既有gcc和.NET运行时, 但是容器启动的时候报错 exec: "dotnet": executable file not found in $PATH: unknown.
基本信息
# 镜像gcc_for_net7_image是如何产生的, 分为3步
1.基于gcc的镜像运行起来的一个包含了gcc环境的容器,
2.在这个容器里安装了.NET7运行时,
3.再将这个包含了gcc环境和.NET7的容器打包为一个镜像"gcc_for_net7_image"
总之, 这个镜像"gcc_for_net7_image"既包含了gcc开发环境, 也包含了.NET7开发环境
# 基于这个基础镜像"gcc_for_net7_image", 想生成一个api应用程序的镜像, 但是运行此api应用程序的容器时候, 报错...
# 多说一句, 为什么我要搞这个一个镜像, 既包含gcc开发环境, 又包含.NET开发环境
我的api应用程序是基于.NET写的, 但是我的这个api程序, 又要调用c++的一些东西,特别是涉及一些画图之类的, 所以, 最终搞了这么一个镜像~~~
报错信息
docker: Error response from daemon: failed to create shim: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "dotnet": executable file not found in $PATH: unknown.
原因查找
# 启动容器
docker run -id --name gcc_for_net7_container gcc_for_net7_image
# 使用"/bin/bash"进入容器, 发现执行gcc或者dotnet, 命令都有可以的~
docker exec -it gcc_for_net7_container /bin/bash
# 使用"/bin/sh"进入容器会发现执行gcc不报错,但是执行dotnet报错!
docker exec -it gcc_for_net7_container /bin/sh
# gcc
gcc: fatal error: no input files
compilation terminated.
# dotnet
/bin/sh: 4: dotnet: not found
通过这个容器, 会发现,
使用"/bin/bash"的情况下, gcc和dotnet命令都可以执行,
但是使用"/bin/sh"的情况下, gcc可以执行, 但是dotnet命令没有~
所以我就想着改一下,Dockerfile中的内容~
# 进一步发现, 只有"/bin/bash"下可以执行dotnet, 如果在启动docker容器的时候, 使用交互方式方式"-t", 直接使用"dotnet"也报错!
$ docker run -id --name gcc_for_net7_container gcc_for_net7_image:v1
1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1
$ docker exec -it gcc_for_net7_container dotnet
OCI runtime exec failed: exec failed: container_linux.go:380:
starting container process caused: exec: "dotnet": executable file not found in $PATH: unknown
初步确定原因如下 :
- 当使用bash进入容器的时候, 环境变量PATH的路径会增加dotnet需要的路径
$HOME/dotnet
- 当使用sh进入容器的时候, 环境变量PATH的路径中没有dotnet需要的路径
- 直接交互,
docker run -it gcc_for_net7_container dotnet
这样操作, PATH路径更是没有配置dotnet需要的路径~
总之, 想办法把PATH路径配置好~
解决方案( docker run的时候增加-e配置 )
# docker容器启动的时候增加参数 -e PATH="$PATH:$HOME/dotnet"
$ docker run -id --name gcc_for_net7_container -e PATH="$PATH:$HOME/dotnet" gcc_for_net7_image:v1
# 验证是否可行( 可以看到,交互方式进入容器是可以直接发现dotnet命令的! )
$ docker exec -it gcc_for_net7_container dotnet
Usage: dotnet [options]
Usage: dotnet [path-to-application]
Options:
-h|--help Display help.
--info Display .NET information.
--list-sdks Display the installed SDKs.
--list-runtimes Display the installed runtimes.
path-to-application:
The path to an application .dll file to execute.
关于启动镜像介绍
# 1. 镜像gcc_for_net7_image中既有gcc开发环境, 又有.NET7运行时
# 2. 这个镜像是基于一个"既有gcc开发环境, 又有.NET7运行时"的容器生成的, 并且该容器已经配置好了dotnet的PATH路径
# 2.1. dotnet的PATH路径配置方法是 : #
# 2.1.1. 修改PATH变量 "vim /etc/profile", 在PATH赋值的地方增加上":/root/dotnet"
# 2.1.1. 在容器实例"/root/.bashrc"配置文件末尾添加(首先vim /root/.bashrc)"source /etc/profile",保存退出即可, 这样能够实现重启后自动刷新配置文件.
反思,,,
还是对进入容器"docker exec"的不同方式, 区别理解不深,
"bash" / "sh" / "dotnet" ...都会发生什么?
# 问了下chatGPT, 发现问题所在( 如果chatGPT没有骗我的话 ~ )
# 问 :
Linux容器的"/root/.bashrc"是何时触发的?
# 答 :
在Linux容器中,/root/.bashrc 文件通常在每次以交互方式启动新的bash shell时触发。
这个文件包含了在每次打开新的bash shell时要执行的命令和设置。
具体来说,当以下情况之一发生时,/root/.bashrc 文件将被触发:
1. 登录交互式Shell: 当你登录到系统时,或者通过SSH等方式远程登录到容器,
并且使用bash shell时,/root/.bashrc 将被执行。
2. 新的终端会话: 每次你启动一个新的终端会话(比如打开一个新的终端窗口或标签页),
并且该终端使用bash shell时,/root/.bashrc 也会被执行。
3. 执行bash命令: 当你在已有的bash shell中执行 bash 命令来启动一个新的bash子shell时,/root/.bashrc 也会被执行。
这个文件通常用于设置用户的个性化环境变量、别名、函数以及其他一些个性化的配置。
最终明白了, 由于我的PATH是配置在了/etc/profile中,
我的{sourcee /etc/profile}又是在"/root/.bashrc"中配置的,
所以就导致了, 我只有在bash命令的时候{docker exec -it gcc_for_net7_container /bin/bash}才会配置了PATH路径,才有dotnet命令,
反之, 我使用sh{docker exec -it gcc_for_net7_container /bin/sh}和{docker exec -it gcc_for_net7_container dotnet}的时候,
根本不会去触发"/root/.bashrc", 也就不会执行{sourcee /etc/profile}, 所以PATH没有增加dotnet需要的路径~