Docker中使用gosu的方法詳解
Docker中使用gosu
為什么要用 gosu?
在 Docker 鏡像中啟動(dòng)服務(wù)時(shí),我們通常不希望以 root 身份運(yùn)行主進(jìn)程。
問(wèn)題:
- 構(gòu)建鏡像時(shí)通常需要 root 權(quán)限;
- 啟動(dòng)時(shí)希望進(jìn)程使用普通用戶(hù)運(yùn)行;
- 容器中使用
sudo會(huì)產(chǎn)生額外的中間進(jìn)程,導(dǎo)致信號(hào)轉(zhuǎn)發(fā)不正常; - 最終可能出現(xiàn)僵尸進(jìn)程、容器無(wú)法優(yōu)雅退出等問(wèn)題。
gosu 是一個(gè)非常輕量的工具,功能類(lèi)似 sudo,但不會(huì)產(chǎn)生額外進(jìn)程,非常適合在 Docker 容器中用來(lái)切換用戶(hù)。
注意事項(xiàng)
- 創(chuàng)建專(zhuān)用普通用戶(hù),不要直接使用 root。
- 在 entrypoint 中使用 gosu 切換用戶(hù),不要用 sudo。
- 使用 exec 啟動(dòng)主進(jìn)程,保證 PID=1 是應(yīng)用本身。
- 正確接收 SIGTERM 信號(hào),避免僵尸進(jìn)程。
- 不要在 Docker 中濫用 sudo。
sudo vs gosu:真實(shí)對(duì)比
使用 gosu
docker run --rm gosu/alpine gosu root ps aux
輸出:
PID USER TIME COMMAND
1 root 0:00 ps aux
ps命令的 PID 是 1,容器內(nèi)只有一個(gè)進(jìn)程。- 這樣當(dāng)宿主機(jī)發(fā)送
SIGTERM信號(hào)時(shí),應(yīng)用能直接接收到。
使用 sudo
docker run --rm ubuntu:trusty sudo ps aux
輸出:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 46012 1772 ? Rs 12:05 0:00 sudo ps aux
root 6 0.0 0.0 15568 1140 ? R 12:05 0:00 ps aux
- 容器內(nèi)出現(xiàn)兩個(gè)進(jìn)程,PID=1 被
sudo占用。 - 應(yīng)用進(jìn)程的 PID 不為 1,無(wú)法直接接收信號(hào)。
- 當(dāng)執(zhí)行
docker stop時(shí),信號(hào)發(fā)送給的是sudo,而不是應(yīng)用進(jìn)程,可能導(dǎo)致應(yīng)用殘留為僵尸進(jìn)程。
對(duì)比:
| 項(xiàng)目 | gosu | sudo |
|---|---|---|
| 進(jìn)程數(shù) | 1 | 2 |
| PID=1 | 應(yīng)用進(jìn)程 | sudo |
| 信號(hào)轉(zhuǎn)發(fā) | 正常 | 不正常 |
| 僵尸進(jìn)程風(fēng)險(xiǎn) | 低 | 高 |
| 適合容器使用 | 是 | 否 |
Dockerfile 安裝 gosu
在 Dockerfile 中添加如下步驟即可:
FROM ubuntu:22.04 # 安裝 gosu RUN apt-get update && apt-get install -y gosu curl ca-certificates && rm -rf /var/lib/apt/lists/* # 創(chuàng)建普通用戶(hù) RUN groupadd -r tempuser && useradd -r -g tempuser tempuser # 拷貝入口腳本 COPY entrypoint.sh /usr/local/bin/entrypoint.sh RUN chmod +x /usr/local/bin/entrypoint.sh # 驗(yàn)證 gosu 是否工作 RUN gosu nobody true ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
entrypoint.sh 的寫(xiě)法
entrypoint.sh 是容器啟動(dòng)腳本。
#!/usr/bin/env bash
set -e
# 使用 gosu 切換用戶(hù)身份
if [ "$1" = "start-app" ]; then
echo "Running application as tempuser..."
exec gosu tempuser /app/my_server
fi
# 如果有其他命令,直接執(zhí)行
exec "$@"注意:exec 會(huì)讓當(dāng)前 shell 被新進(jìn)程取代,保證應(yīng)用進(jìn)程的 PID=1。
構(gòu)建 & 運(yùn)行容器
docker build -t myapp . docker run --rm -p 8080:8080 myapp start-app
容器內(nèi):
/app/my_server的 PID = 1- 收到
docker stop的信號(hào)時(shí),能正確退出 - 不會(huì)殘留
sudo或 shell 僵尸進(jìn)程
信號(hào)量與僵尸進(jìn)程問(wèn)題
容器啟動(dòng)時(shí) PID=1 的進(jìn)程非常特殊,它負(fù)責(zé)接收來(lái)自宿主機(jī)的信號(hào)(例如 SIGTERM、SIGINT)。
- 如果 PID=1 是
sudo,信號(hào)不會(huì)傳給應(yīng)用; - 如果 PID=1 是應(yīng)用進(jìn)程本身,就能優(yōu)雅退出;
- 使用
exec+gosu可以保證 PID=1 是你的應(yīng)用; - 避免使用 shell 包一層后
&運(yùn)行后臺(tái)進(jìn)程的錯(cuò)誤做法。
常見(jiàn)問(wèn)題
| 問(wèn)題 | 原因 | 解決方法 |
|---|---|---|
| 容器退出時(shí)殘留僵尸進(jìn)程 | PID=1 不是應(yīng)用進(jìn)程 | 使用 exec + gosu |
| docker stop 不生效 | 信號(hào)被 sudo 攔截 | 不使用 sudo,PID=1 改為應(yīng)用 |
| gosu 報(bào)權(quán)限錯(cuò)誤 | 二進(jìn)制無(wú)執(zhí)行權(quán)限 | chmod +x /usr/local/bin/gosu |
| 切換用戶(hù)失敗 | 用戶(hù)不存在 | 使用 useradd 創(chuàng)建對(duì)應(yīng)用戶(hù) |
參考資料
- gosu 官方 GitHub
- Docker 官方最佳實(shí)踐
- Docker 官方最佳實(shí)踐中文
- Why use exec in entrypoint?(Stack Overflow)
- CSDN docker與gosu
到此這篇關(guān)于Docker中使用gosu的文章就介紹到這了,更多相關(guān)docker使用gosu內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Docker容器實(shí)戰(zhàn)之鏡像倉(cāng)庫(kù)
這篇文章主要介紹了Docker容器實(shí)戰(zhàn)之鏡像倉(cāng)庫(kù),文章通過(guò)Docker?Hub為例,講解關(guān)于鏡像倉(cāng)庫(kù)的使用,需要的小伙伴可以參考一下2022-05-05
docker?掛載MySQL實(shí)現(xiàn)數(shù)據(jù)持久化的實(shí)現(xiàn)
本文主要介紹了docker?掛載MySQL實(shí)現(xiàn)數(shù)據(jù)持久化的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01
Docker安裝阿里云服務(wù)器和在虛擬機(jī)安裝遇到的坑(問(wèn)題小結(jié))
這篇文章主要介紹了Docker安裝阿里云服務(wù)器和在虛擬機(jī)安裝遇到的坑,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03
備份Docker容器中的PostgreSQL數(shù)據(jù)的圖文實(shí)操教程
現(xiàn)在docker容器很方便,可以一鍵部署項(xiàng)目,但是方便部署的同時(shí),也給運(yùn)維帶來(lái)了麻煩,docker中的pgsql數(shù)據(jù),如何進(jìn)行備份呢,本文小編給大家就介紹了備份Docker容器中的PostgreSQL數(shù)據(jù)的圖文實(shí)操教程,需要的朋友可以參考下2024-09-09
解決'nacos默認(rèn)secret.key配置不當(dāng)權(quán)限繞過(guò)漏洞'的問(wèn)題
這篇文章主要介紹了解決“nacos默認(rèn)secret.key配置不當(dāng)權(quán)限繞過(guò)漏洞“的問(wèn)題,解決這個(gè)問(wèn)題需要對(duì)這個(gè)key的默認(rèn)值進(jìn)行修改,建議不要使用明文,可以用base64,key的長(zhǎng)度要32位以上,下面介紹一下在兩種環(huán)境下的修改方法,感興趣的朋友一起看看吧2024-01-01
用Docker swarm快速部署Nebula Graph集群的教程
這篇文章主要介紹了用Docker swarm快速部署Nebula Graph集群的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09
Docker搭建Elasticsearch集群和Kibana全過(guò)程
這篇文章主要介紹了Docker搭建Elasticsearch集群和Kibana全過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-05-05

