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

初步確定原因如下 :

  1. 當使用bash進入容器的時候, 環境變量PATH的路徑會增加dotnet需要的路徑$HOME/dotnet
  2. 當使用sh進入容器的時候, 環境變量PATH的路徑中沒有dotnet需要的路徑
  3. 直接交互, 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需要的路徑~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章