欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入理解docker容器中的uid和gid

 更新時(shí)間:2018年09月12日 14:33:41   作者:sparkdev  
這篇文章主要介紹了深入理解docker容器中的uid和gid,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧

默認(rèn)情況下,容器中的進(jìn)程以 root 用戶權(quán)限運(yùn)行,并且這個(gè) root 用戶和宿主機(jī)中的 root 是同一個(gè)用戶。聽起來(lái)是不是很可怕,因?yàn)檫@就意味著一旦容器中的進(jìn)程有了適當(dāng)?shù)臋C(jī)會(huì),它就可以控制宿主機(jī)上的一切!本文我們將嘗試了解用戶名、組名、用戶 id(uid)和組 id(gid)如何在容器內(nèi)的進(jìn)程和主機(jī)系統(tǒng)之間映射,這對(duì)于系統(tǒng)的安全來(lái)說是非常重要的。說明:本文的演示環(huán)境為 ubuntu 16.04(下圖來(lái)自互聯(lián)網(wǎng))。

先來(lái)了解下 uid 和 gid

uid 和 gid 由 Linux 內(nèi)核負(fù)責(zé)管理,并通過內(nèi)核級(jí)別的系統(tǒng)調(diào)用來(lái)決定是否應(yīng)該為某個(gè)請(qǐng)求授予特權(quán)。比如當(dāng)進(jìn)程試圖寫入文件時(shí),內(nèi)核會(huì)檢查創(chuàng)建進(jìn)程的 uid 和 gid,以確定它是否有足夠的權(quán)限修改文件。注意,內(nèi)核使用的是 uid 和 gid,而不是用戶名和組名。

簡(jiǎn)單起見,本文中剩下的部分只拿 uid 進(jìn)行舉例,系統(tǒng)對(duì)待 gid 的方式和 uid 基本相同。

很多同學(xué)簡(jiǎn)單地把 docker 容器理解為輕量的虛擬機(jī),雖然這簡(jiǎn)化了理解容器技術(shù)的難度但是也容易帶來(lái)很多的誤解。事實(shí)上,與虛擬機(jī)技術(shù)不同:同一主機(jī)上運(yùn)行的所有容器共享同一個(gè)內(nèi)核(主機(jī)的內(nèi)核)。容器化帶來(lái)的巨大價(jià)值在于所有這些獨(dú)立的容器(其實(shí)是進(jìn)程)可以共享一個(gè)內(nèi)核。這意味著即使由成百上千的容器運(yùn)行在 docker 宿主機(jī)上,但內(nèi)核控制的 uid 和 gid 則仍然只有一套。所以同一個(gè) uid 在宿主機(jī)和容器中代表的是同一個(gè)用戶(即便在不同的地方顯示了不同的用戶名)。

注意,由于普通的用來(lái)顯示用戶名的 Linux 工具并不屬于內(nèi)核(比如 id 等命令),所以我們可能會(huì)看到同一個(gè) uid 在不同的容器中顯示為不同的用戶名。但是對(duì)于相同的 uid 不能有不同的特權(quán),即使在不同的容器中也是如此。

如果你已經(jīng)了解了 Linux 的 user namespace 技術(shù),參考《Linux Namespace : User》,你需要注意的是到目前為止,docker 默認(rèn)并沒有啟用 user namesapce,這也是本文討論的情況。筆者會(huì)在接下來(lái)的文章中介紹如何配置 docker 啟用 user namespace。

容器中默認(rèn)使用 root 用戶

如果不做相關(guān)的設(shè)置,容器中的進(jìn)程默認(rèn)以 root 用戶權(quán)限啟動(dòng),下面的 demo 使用 ubuntu 鏡像運(yùn)行 sleep 程序:

$ docker run -d --name sleepme ubuntu sleep infinity

注意上面的命令中并沒有使用 sudo。筆者在宿主機(jī)中的登錄用戶是 nick,uid 為 1000:

在宿主機(jī)中查看 sleep 進(jìn)程的信息:

$ ps aux | grep sleep

sleep 進(jìn)程的有效用戶名稱是 root,也就是說 sleep 進(jìn)程具有 root 權(quán)限。

然后進(jìn)入容器內(nèi)部看看,看到的情況和剛才一樣,sleep 進(jìn)程也具有 root 權(quán)限:

那么,容器內(nèi)的 root 用戶和宿主機(jī)上的 root 用戶是同一個(gè)嗎?

答案是:是的,它們對(duì)應(yīng)的是同一個(gè) uid。原因我們?cè)谇懊嬉呀?jīng)解釋過了:整個(gè)系統(tǒng)共享同一個(gè)內(nèi)核,而內(nèi)核只管理一套 uid 和 gid。

其實(shí)我們可以通過數(shù)據(jù)卷來(lái)簡(jiǎn)單的驗(yàn)證上面的結(jié)論。在宿主機(jī)上創(chuàng)建一個(gè)只有 root 用戶可以讀寫的文件:

然后掛載到容器中:

$ docker run --rm -it -w=/testv -v $(pwd)/testv:/testv ubuntu

在容器中可以讀寫該文件:

我們可以通過 Dockerfile 中的 USER 命令或者是 docker run 命令的 --user 參數(shù)指定容器中進(jìn)程的用戶身份。下面我們分別來(lái)探究這兩種情況。

在 Dockerfile 中指定用戶身份

我們可以在 Dockerfile 中添加一個(gè)用戶 appuser,并使用 USER 命令指定以該用戶的身份運(yùn)行程序,Dockerfile 的內(nèi)容如下:

FROM ubuntu
RUN useradd -r -u 1000 -g appuser
USER appuser
ENTRYPOINT ["sleep", "infinity"]

編譯成名稱為 test 的鏡像:

$ docker build -t test .

用 test 鏡像啟動(dòng)一個(gè)容器:

$ docker run -d --name sleepme test

在宿主機(jī)中查看 sleep 進(jìn)程的信息:

這次顯示的有效用戶是 nick,這是因?yàn)樵谒拗鳈C(jī)中,uid 為 1000 的用戶的名稱為 nick。再進(jìn)入到容器中看看:

$ docker exec -it sleepme bash

容器中的當(dāng)前用戶就是我們?cè)O(shè)置的 appuser,如果查看容器中的 /etc/passwd 文件,你會(huì)發(fā)現(xiàn) appuser 的 uid 就是 1000,這和宿主機(jī)中用戶 nick 的 uid 是一樣的。

讓我們?cè)賱?chuàng)建一個(gè)只有用戶 nick 可以讀寫的文件:

同樣以數(shù)據(jù)卷的方式把它掛載到容器中:

$ docker run -d --name sleepme -w=/testv -v $(pwd)/testv:/testv test

在容器中 testfile 的所有者居然變成了 appuser,當(dāng)然 appuser 也就有權(quán)限讀寫該文件。

這里到底發(fā)生了什么?而這些又這說明了什么?

首先,宿主機(jī)系統(tǒng)中存在一個(gè) uid 為 1000 的用戶 nick。其次容器中的程序是以 appuser 的身份運(yùn)行的,這是由我們通過 USER appuser 命令在 Dockerfile 程序中指定的。

事實(shí)上,系統(tǒng)內(nèi)核管理的 uid 1000 只有一個(gè),在宿主機(jī)中它被認(rèn)為是用戶 nick,而在容器中,它則被認(rèn)為是用戶 appuser。
所以有一點(diǎn)我們需要清楚:在容器內(nèi)部,用戶 appuser 能夠獲取容器外部用戶 nick 的權(quán)利和特權(quán)。在宿主機(jī)上授予用戶 nick 或 uid 1000 的特權(quán)也將授予容器內(nèi)的 appuser。

從命令行參數(shù)中自定用戶身份

我們還可以通過 docker run 命令的 --user 參數(shù)指定容器中進(jìn)程的用戶身份。比如執(zhí)行下面的命令:

$ docker run -d --user 1000 --name sleepme ubuntu sleep infinity

因?yàn)槲覀冊(cè)诿钚猩现噶盍藚?shù) --user 1000,所以這里 sleep 進(jìn)程的有效用戶顯示為 nick。進(jìn)入到容器內(nèi)部看一下:

$ docker exec -it sleepme bash

這是個(gè)什么情況?用戶名稱居然顯示為 "I have no name!"!去查看 /etc/passwd 文件,里面果然沒有 uid 為 1000 的用戶。即便沒有用戶名稱,也絲毫不影響該用戶身份的權(quán)限,它依然可以讀寫只有 nick 用戶才能讀寫的文件,并且用戶信息也由 uid 代替了用戶名:

需要注意的是,在創(chuàng)建容器時(shí)通過 docker run --user 指定的用戶身份會(huì)覆蓋掉 Dockerfile 中指定的值。
我們重新通過 test 鏡像來(lái)運(yùn)行兩個(gè)容器:

$ docker run -d test

查看 sleep 進(jìn)程信息:

$ docker run --user 0 -d test

再次查看 sleep 進(jìn)程信息:

指定了 --urser 0 參數(shù)的進(jìn)程顯示有效用戶為 root,說明命令行參數(shù) --user 0 覆蓋掉了 Dockerfile 中 USER 命令的設(shè)置。

總結(jié)

從本文中的示例我們可以了解到,容器中運(yùn)行的進(jìn)程同樣具有訪問主機(jī)資源的權(quán)限(docker 默認(rèn)并沒有對(duì)用戶進(jìn)行隔離),當(dāng)然一般情況下容器技術(shù)會(huì)把容器中進(jìn)程的可見資源封鎖在容器中。但是通過我們演示的對(duì)數(shù)據(jù)卷中文件的操作可以看出,一旦容器中的進(jìn)程有機(jī)會(huì)訪問到宿主機(jī)的資源,它的權(quán)限和宿主機(jī)上用戶的權(quán)限是一樣的。所以比較安全的做法是為容器中的進(jìn)程指定一個(gè)具有合適權(quán)限的用戶,而不要使用默認(rèn)的 root 用戶。當(dāng)然還有更好的方案,就是應(yīng)用 Linux 的 user namespace 技術(shù)隔離用戶,筆者會(huì)在接下來(lái)的文章中介紹如何配置 docker 開啟 user namespace 的支持。

參考:

Understanding how uid and gid work in Docker containers
Introduction to User Namespaces in Docker Engine
Isolate containers with a user namespace

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • docker?gitea?drone實(shí)現(xiàn)超輕量級(jí)CI?CD實(shí)戰(zhàn)詳解

    docker?gitea?drone實(shí)現(xiàn)超輕量級(jí)CI?CD實(shí)戰(zhàn)詳解

    這篇文章主要為大家介紹了docker?gitea?drone實(shí)現(xiàn)超輕量級(jí)CI?CD實(shí)戰(zhàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • Docker運(yùn)行hello-world鏡像失敗或超時(shí)的問題

    Docker運(yùn)行hello-world鏡像失敗或超時(shí)的問題

    在安裝Docker并嘗試運(yùn)行hello-world時(shí),可能會(huì)遇到超時(shí)問題,這通常是由于默認(rèn)的鏡像源訪問速度慢造成的,解決這個(gè)問題的辦法是更換鏡像源,雖然許多人推薦使用阿里云的鏡像源,對(duì)Docker hello-world超時(shí)問題感興趣的朋友一起看看吧
    2024-09-09
  • Docker 修改docker存儲(chǔ)位置 修改容器鏡像大小限制操作

    Docker 修改docker存儲(chǔ)位置 修改容器鏡像大小限制操作

    這篇文章主要介紹了Docker 修改docker存儲(chǔ)位置 修改容器鏡像大小限制操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧
    2020-11-11
  • Docker容器部署前端Vue服務(wù)(小白教程)

    Docker容器部署前端Vue服務(wù)(小白教程)

    本文主要介紹了Docker容器部署前端Vue服務(wù),文中根據(jù)實(shí)例編碼詳細(xì)介紹的十分詳盡,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • Docker創(chuàng)建鏡像、怎么修改、上傳鏡像等詳細(xì)介紹

    Docker創(chuàng)建鏡像、怎么修改、上傳鏡像等詳細(xì)介紹

    這篇文章主要介紹了Docker創(chuàng)建鏡像、怎么修改、上傳鏡像等詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下
    2016-12-12
  • docker打包前端項(xiàng)目的實(shí)現(xiàn)示例

    docker打包前端項(xiàng)目的實(shí)現(xiàn)示例

    本文介紹了如何將前端項(xiàng)目打包到Docker容器中,包括編寫Dockerfile文件、創(chuàng)建鏡像和容器以及解決部署過程中遇到的問題,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-09-09
  • linux 詳解useradd 命令基本用法

    linux 詳解useradd 命令基本用法

    這篇文章主要介紹了linux 詳解useradd 命令基本用法的相關(guān)資料,需要的朋友可以參考下
    2017-01-01
  • 關(guān)于docker部署fastapi項(xiàng)目以及日志掛載方式

    關(guān)于docker部署fastapi項(xiàng)目以及日志掛載方式

    這篇文章主要介紹了關(guān)于docker部署fastapi項(xiàng)目以及日志掛載方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • docker-compose搭建prometheus+grafana+釘釘告警

    docker-compose搭建prometheus+grafana+釘釘告警

    本文主要介紹了docker-compose搭建prometheus+grafana+釘釘告警,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • Docker制作Python運(yùn)行環(huán)境基礎(chǔ)鏡像的方法步驟

    Docker制作Python運(yùn)行環(huán)境基礎(chǔ)鏡像的方法步驟

    這篇文章主要介紹了Docker制作Python運(yùn)行環(huán)境基礎(chǔ)鏡像的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12

最新評(píng)論