不要以root用戶啟動docker進程
默認docker是沒有開啟user namespace的(開啟需要修改docker配置文件),也就是說默認容器和宿主機用的是同一個user namespace,linux內核只認uid和gid,容器root(uid=0)用戶和宿主機root(uid=0)是同一個,并沒有隔離
- 如果不是必須以root用戶運行,就不要以root用戶運行。
- 如果root用戶逃逸容器,很危險。我們很容易地錯誤地假設容器是“完全”隔離的,在一個容器中做的事情,不會影響到其他容器,也不會影響到宿主機。就像我們在云供應商上租用一個虛擬機(ECS)不會擔心會被其他人的虛擬機影響到。但是相比虛擬機的隔離,容器的隔離是比較弱的。這就意味著,在一個容器內做的危險操作,可能會影響到其他容器,甚至影響到宿主機。這種突破容器的隔離性的行為也叫容器逃逸(container escape)。如果容器內以root用戶運行,就會使得惡意攻擊變得更加容易。
分析宿主機UID和容器UID關系
執行docker的用戶,和真正運行起來的docker用戶不一樣
宿主機marc用戶執行docker run命令啟動docker進程,不指定-u指定用戶,默認會用容器里的用戶,通常是root命令啟動docker進程
marc@server:~$ docker run -d ubuntu:latest sleep infinity
92c57a8a4eda60678f049b906f99053cbe3bf68a7261f118e411dee173484d10
marc@server:~$ ps aux | grep sleep
root 15638 0.1 0.0 4380 808 ? Ss 19:49 0:00 sleep infinity
- 在宿主機上查看docker進程
- 所屬用戶是root(uid=0)。。。這個權限變大了,所以容器里執行命令不建議用root,他的uid會映射到宿主機的root uid
- 在容器內登錄用戶,指定id顯示當前用戶是root
- 默認是root(uid=0)
指定docker進程用戶,再分析用戶uid關系
宿主機用uid=1001(宿主機上用戶名是marc)啟動docker進程,在宿主機查看docker進程,是marc用戶
FROM ubuntu:latest
RUN useradd -r -u 1001 -g appuser appuser
USER appuser
ENTRYPOINT [“sleep”, “infinity”]
marc@server:~$ docker run -d test
8ad0cd43592e6c4314775392fb3149015adc25deb22e5e5ea07203ff53038073
marc@server:~$ ps aux | grep sleep
marc 16507 0.3 0.0 4380 668 ? Ss 20:02 0:00 sleep infinity
容器里面查看當前登錄容器的用戶,uid=1001(容器內用戶名是appuser)
marc@server:~$ docker exec -it 8ad0 /bin/bash
appuser@8ad0cd43592e:/$ ps aux | grep sleep
appuser 1 0.0 0.0 4380 668 ? Ss 20:02 0:00 sleep infinity
- 總結:
- 默認docker是沒有開啟user namespace的(開啟需要修改docker配置文件)
- 在沒開啟user namespace情況下,默認容器和宿主機用的是同一個user namespace,uid都是共享的,只是uid在不同的操作系統(容器操作系統rootfs和宿主機操作系統)對應的username不一樣
- uid=1001(容器內用戶名是appuser)
- uid=1001(宿主機上用戶名是marc)
- 為什么可以這樣?
- 因為username不是Linux kernel的一部分,只是屬于外部工具,在rootfs上面
- That’s because the username (and group names) that show up in common linux tools aren’t part of the kernel, but are managed by external tools (/etc/passwd, LDAP, Kerberos, etc). So, you might see different usernames, but you can’t have different privileges for the same uid/gid, even inside different containers
指定docker啟動用戶的兩種方式:
方式一:在dockerfile上指定
在Dockerfile中創建用戶和用戶組,并指定以該用戶和用戶組運行。
指定容器USER為appuser
FROM ubuntu:latest
RUN useradd -r -u 1001 -g appuser appuser
USER appuser
ENTRYPOINT [“sleep”, “infinity”]
宿主機啟動docker進程,docker進程用戶1001(marc)
marc@server:~$ docker run -d test
8ad0cd43592e6c4314775392fb3149015adc25deb22e5e5ea07203ff53038073
marc@server:~$ ps aux | grep sleep
marc 16507 0.3 0.0 4380 668 ? Ss 20:02 0:00 sleep infinity
查看容器內登錄用戶:uid=1001(appuser)
marc@server:~$ docker exec -it 8ad0 /bin/bash
appuser@8ad0cd43592e:/$ ps aux | grep sleep
appuser 1 0.0 0.0 4380 668 ? Ss 20:02 0:00 sleep infinity
方式二:在docker run -u上指定
$ docker run --user www-data busybox id
uid=33(www-data) gid=33(www-data)
docker run -u(--user)[user:group] 或 --group-add 參數方式
-u表示,創建容器時,創建對應用戶和用戶組,也可以指定uid.(如果用戶已存在則不創建)