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

Docker?exec?的實現(xiàn)原理介紹

 更新時間:2022年04月02日 09:22:29   作者:wzlinux  
這篇文章主要介紹了Docker?exec的實現(xiàn)原理,詳細解讀了docker?exec這個操作背后,Linux?Namespace更具體的工作原理,這種通過操作系統(tǒng)進程相關的知識,逐步剖析Docker容器的方法,需要的朋友可以參考一下

我使用了 docker exec 命令進入到了容器當中。在了解了Linux Namespace 的隔離機制后,你應該會很自然地想到一個問題:docker exec 是怎么做到進入容器里的呢?
實際上,Linux Namespace 創(chuàng)建的隔離空間雖然看不見摸不著,但一個進程的 Namespace 信息在宿主機上是確確實實存在的,并且是以一個文件的方式存在。

比如,通過如下指令,你可以看到當前正在運行的 Docker 容器的進程號(PID)是 25686:

$ docker inspect --format '{{ .State.Pid }}' 4ddf4638572d
25686

這時,你可以通過查看宿主機的 proc 文件,看到這個 25686 進程的所有 Namespace 對應的文件:

$ ls -l /proc/25686/ns
total 0
lrwxrwxrwx 1 root root 0 Aug 13 14:05 cgroup -> cgroup:[4026531835]
lrwxrwxrwx 1 root root 0 Aug 13 14:05 ipc -> ipc:[4026532278]
lrwxrwxrwx 1 root root 0 Aug 13 14:05 mnt -> mnt:[4026532276]
lrwxrwxrwx 1 root root 0 Aug 13 14:05 net -> net:[4026532281]
lrwxrwxrwx 1 root root 0 Aug 13 14:05 pid -> pid:[4026532279]
lrwxrwxrwx 1 root root 0 Aug 13 14:05 pid_for_children -> pid:[4026532279]
lrwxrwxrwx 1 root root 0 Aug 13 14:05 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Aug 13 14:05 uts -> uts:[4026532277]

可以看到,一個進程的每種Linux Namespace,都在它對應的 /proc/[進程號]/ns 下有一個對應的虛擬文件,并且鏈接到一個真實的 Namespace 文件上。
有了這樣一個可以“hold 住”所有 Linux Namespace 的文件,我們就可以對 Namespace 做一些很有意義事情了,比如:加入到一個已經存在的 Namespace 當中。

這也就意味著:一個進程,可以選擇加入到某個進程已有的 Namespace 當中,從而達到“進入”這個進程所在容器的目的,這正是 docker exec 的實現(xiàn)原理。

而這個操作所依賴的,乃是一個名叫 setns() 的 Linux 系統(tǒng)調用。它的調用方法,我可以用如下一段小程序為你說明:

#define _GNU_SOURCE
#include <fcntl.h>
#include <sched.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE);} while (0)

int main(int argc, char *argv[]) {
int fd;

fd = open(argv[1], O_RDONLY);
if (setns(fd, 0) == -1) {
errExit("setns");
}
execvp(argv[2], &argv[2]);
errExit("execvp");
}

這段代碼功能非常簡單:它一共接收兩個參數(shù),第一個參數(shù)是 argv[1],即當前進程要加入的 Namespace 文件的路徑,比如/proc/25686/ns/net;而第二個參數(shù),則是你要在這個 Namespace 里運行的進程,比如 /bin/bash。

這段代碼的的核心操作,則是通過 open() 系統(tǒng)調用打開了指定的 Namespace 文件,并把這個文件的描述符 fd 交給 setns() 使用。在 setns() 執(zhí)行后,當前進程就加入了這個文件對應的 Linux Namespace 當中了。

現(xiàn)在,你可以編譯執(zhí)行一下這個程序,加入到容器進程(PID=25686)的 Network Namespace 中:

$ gcc -o set_ns set_ns.c
$ ./set_ns /proc/25686/ns/net /bin/bash
$ ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:ac:11:00:02
inet addr:172.17.0.2 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:acff:fe11:2/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:12 errors:0 dropped:0 overruns:0 frame:0
TX packets:10 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:976 (976.0 B) TX bytes:796 (796.0 B)

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

正如上所示,當我們執(zhí)行 ifconfig 命令查看網絡設備時,我會發(fā)現(xiàn)能看到的網卡“變少”了:只有兩個。而我的宿主機則至少有四個網卡。這是怎么回事呢?
實際上,在 setns() 之后我看到的這兩個網卡,正是我在前面啟動的 Docker 容器里的網卡。也就是說,我新創(chuàng)建的這個 /bin/bash 進程,由于加入了該容器進程(PID=25686)的 Network Namepace,它看到的網絡設備與這個容器里是一樣的,即:/bin/bash 進程的網絡設備視圖,也被修改了。
而一旦一個進程加入到了另一個 Namespace 當中,在宿主機的 Namespace 文件上,也會有所體現(xiàn)。

在宿主機上,你可以用 ps 指令找到這個 set_ns 程序執(zhí)行的 /bin/bash 進程,其真實的 PID 是 28499:

# 在宿主機上
ps aux | grep /bin/bash
root 28499 0.0 0.0 19944 3612 pts/0 S 14:15 0:00 /bin/bash

這時,如果按照前面介紹過的方法,查看一下這個 PID=28499 的進程的 Namespace,你就會發(fā)現(xiàn)這樣一個事實:

$ ls -l /proc/28499/ns/net
lrwxrwxrwx 1 root root 0 Aug 13 14:18 /proc/28499/ns/net -> net:[4026532281]

$ ls -l /proc/25686/ns/net
lrwxrwxrwx 1 root root 0 Aug 13 14:05 /proc/25686/ns/net -> net:[4026532281]

/proc/[PID]/ns/net 目錄下,這個 PID=28499 進程,與我們前面的 Docker 容器進程(PID=25686)指向的 Network Namespace 文件完全一樣。這說明這兩個進程,共享了這個名叫net:[4026532281] 的 Network Namespace。
此外,Docker 還專門提供了一個參數(shù),可以讓你啟動一個容器并“加入”到另一個容器的 Network Namespace 里,這個參數(shù)就是 -net,比如:

$ docker run -it --net container:4ddf4638572d busybox ifconfig

這樣,我們新啟動的這個容器,就會直接加入到 ID=4ddf4638572d 的容器,也就是我們前面的創(chuàng)建的應用容器(PID=25686)的Network Namespace 中。所以,這里 ifconfig 返回的網卡信息,跟我前面那個小程序返回的結果一模一樣,你也可以嘗試一下。
而如果我指定–net=host,就意味著這個容器不會為進程啟用 Network Namespace。這就意味著,這個容器拆除了 Network Namespace 的“隔離墻”,所以,它會和宿主機上的其他普通進程一樣,直接共享宿主機的網絡棧。這就為容器直接操作和使用宿主機網絡提供了一個渠道。

到此這篇關于Docker exec 的實現(xiàn)原理介紹的文章就介紹到這了,更多相關Docker exec 的實現(xiàn)內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • docker打包 commit和Dockerfile過程

    docker打包 commit和Dockerfile過程

    這篇文章主要介紹了docker打包 commit和Dockerfile過程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • 安裝harbor作為docker鏡像倉庫的問題

    安裝harbor作為docker鏡像倉庫的問題

    這篇文章主要介紹了安裝harbor作為docker鏡像倉庫,主要包括docker和docker-compose離線部署,安裝harbor作為本地的倉庫,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • 前端項目容器化Docker打包部署方式詳解

    前端項目容器化Docker打包部署方式詳解

    這篇文章主要為大家介紹了前端項目容器化Docker打包部署方式詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-11-11
  • Docker部署Mysql集群的實現(xiàn)

    Docker部署Mysql集群的實現(xiàn)

    這篇文章主要介紹了Docker部署Mysql集群的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-09-09
  • Docker搭建Redis5.0并掛載數(shù)據(jù)

    Docker搭建Redis5.0并掛載數(shù)據(jù)

    本文主要介紹了Docker搭建Redis5.0并掛載數(shù)據(jù),文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧
    2021-07-07
  • 使用Docker快速部署ES單機方式

    使用Docker快速部署ES單機方式

    這篇文章主要介紹了使用Docker快速部署ES單機方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • 如何解決mysql配置文件錯誤導致在docker中無法啟動的問題

    如何解決mysql配置文件錯誤導致在docker中無法啟動的問題

    這篇文章主要介紹了如何解決mysql配置文件錯誤導致在docker中無法啟動的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Docker自定義鏡像上傳至阿里云的實現(xiàn)

    Docker自定義鏡像上傳至阿里云的實現(xiàn)

    本文主要介紹了Docker自定義鏡像上傳至阿里云的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2024-04-04
  • docker 容器自定義 hosts 網絡訪問操作

    docker 容器自定義 hosts 網絡訪問操作

    這篇文章主要介紹了docker 容器自定義 hosts 網絡訪問操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • Docker?安裝Tomcat、實現(xiàn)Tomcat集群的詳細過程

    Docker?安裝Tomcat、實現(xiàn)Tomcat集群的詳細過程

    這篇文章主要介紹了Docker安裝Tomcat、實現(xiàn)Tomcat集群,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-06-06

最新評論