基本信息
# 鏡像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需要的路徑~