Docker容器實戰(zhàn):容器安全的優(yōu)秀實踐
??想了解更多關(guān)于開源的內(nèi)容,請訪問:??
一. 容器配置
1、禁止使用特權(quán)容器
使用--privileged啟動容器時,會將所有內(nèi)核功能賦予容器,從而覆蓋Capability的能力限制。在這種情況下,容器可執(zhí)行主機層面能做的大部分事情,從而給系統(tǒng)帶來較大的安全隱患,所以應(yīng)該被禁止。
$ docker run -d --privileged nginx
2、限制容器的資源使用
默認(rèn)情況下,主機上的容器對于資源的訪問并沒有受到限制。此時,當(dāng)某個容器被攻擊或者程序出錯時,將可能因為過多占用資源而影響到主機和其他容器的運行。
因此,可以通過Cgroup的特性來設(shè)置容器的資源使用限制,這樣得以最大程度減少因此類問題而產(chǎn)生的影響 。
示例1:限制CPU可以使用的最大核數(shù)為1 。
$ docker run -d --cpus 1 nginx
示例2:限制容器可以使用特定的CPU,如宿主機有4個CPU,我們只允許容器使用第一個CPU,可以設(shè)置如下 :
$ docker run -d --cpuset-cpus 0 nginx
示例3:限制容器最大內(nèi)存使用量為512M。
$ docker run -d -m 512m nginx
3、 隔離容器網(wǎng)絡(luò)
Docker默認(rèn)使用bridge網(wǎng)絡(luò),該網(wǎng)絡(luò)會創(chuàng)建一個虛擬網(wǎng)橋,連接在同一個網(wǎng)橋之間的容器可以互相訪問。為了提升網(wǎng)絡(luò)安全性,建議不要依賴默認(rèn)的docker0網(wǎng)絡(luò),而是通過自定義網(wǎng)絡(luò)方式進行容器網(wǎng)絡(luò)的劃分,這樣可保證對宿主機中的容器之間做到訪問隔離。
另外,在主機層面也應(yīng)盡可能進行網(wǎng)絡(luò)劃分,不同的主機運行不同安全性要求的容器,如開發(fā)環(huán)境、測試環(huán)境和生產(chǎn)環(huán)境的宿主機應(yīng)該彼此隔離。
4、禁止掛載主機系統(tǒng)目錄
主機中與系統(tǒng)相關(guān)的目錄,包含 /boot、/dev、/etc、/proc、/sys、/usr等,應(yīng)該明令禁止被掛載到容器中。尤其是在讀寫模式下,這種情況會導(dǎo)致容器具有對主機系統(tǒng)進行修改的能力,從而給主機系統(tǒng)帶來極大的安全隱患。
遺憾的是,目前在Docker層面并沒有相關(guān)的技術(shù)方案來限制此類行為,只能通過審計等手段進行發(fā)現(xiàn)。
5、 將容器的根文件系統(tǒng)掛載為只讀
將容器的根文件系統(tǒng)掛載為只讀模式,這種模式可以避免對根文件系統(tǒng)帶來任何的修改,從而保證了容器的安全性。當(dāng)然,只讀的模式也會帶來不便 ,需要結(jié)合掛載存儲來使用,將輸出的內(nèi)容寫到持久化存儲中。
配置只讀的方式很簡單,在啟動容器時添加 --read only 選項,如下:
$ docker run -it --read-only nginx sh
# echo 'test' > /root/1.txt
sh: 2: cannot create /root/1.txt: Read-only file system
6、禁止共享主機的網(wǎng)絡(luò)棧
在啟動容器時,使用--network host 可以讓容器與主機共享網(wǎng)絡(luò)棧,此時,容器會使用主機的IP及其他的網(wǎng)絡(luò)配置,并自動將容器的端口映射到主機。
這種方法雖然帶來了一定的便利性,但也給容器帶來了風(fēng)險。在這種模式下,容器內(nèi)可對主機的網(wǎng)絡(luò)棧進行操作,所以并不建議使用。
$ docker run -d --network host nginx
二、鏡像管理
1、禁止在鏡像中存儲機密信息
容器中程序在正常運行的過程中,通常需要使用到一些機密信息,如數(shù)據(jù)庫賬號密碼、access token等。諸如此類的敏感信息,不應(yīng)被保存到鏡像中,不然會造成機密信息泄露風(fēng)險。
可以使用配置中心等方案,將這些信息移到外部進行管理。
2、選用最小化的基礎(chǔ)鏡像
在使用Dockerfile構(gòu)建應(yīng)用鏡像時,需要選擇一個鏡像來作為基礎(chǔ)鏡像。對于該鏡像的選擇,應(yīng)避免使用功能大而全的鏡像,而采用最小化滿足的模式。
這樣可以帶來兩個好處:
最大程度減少安全漏洞。
減少對于資源的占用。
3、掃描并驗證鏡像
在 2019 年時,作為安全公司的Snyk 發(fā)現(xiàn),10大最流行的 Docker 鏡像中,每個鏡像至少有 30 個安全漏洞。這足以引起我們對于鏡像安全的警覺。
通過對Docker鏡像進行漏洞掃描,可以讓開發(fā)和運維人員清楚鏡像的安全狀態(tài),并采取措施修復(fù)發(fā)現(xiàn)的問題,從而實現(xiàn)更安全的部署。
目前支持鏡像掃描的開源方案有Docker scan、Clair、Anchore等,其中Docker Scan已集成到最新的Docker版本中,可以開箱即用。
4、使用多階段構(gòu)建
在舊的版本中,構(gòu)建鏡像的操作通常在一個Dockerfile流程中完成,在這種模式下構(gòu)建的鏡像會包含很多冗余的文件,如源碼文件、下載的依賴包、打包產(chǎn)生的臨時文件等。
為了解決這個問題,Docker在17.05 版本開始支持使用多階段構(gòu)建(Multi-stage builds)。使用這種模式構(gòu)建鏡像時,我們可以第一階段完成代碼的打包等工作流程,然后在第二階段選擇合適的運行鏡像,并將上個階段生成的包拷貝到鏡像中配置運行。
多階段構(gòu)建具有速度快、鏡像體積更小、安全性更高等特點,建議采用此種方式來進行鏡像的構(gòu)建 。
示例:
#階段一:編譯打包
FROM maven:3.5.0-jdk-8-alpine AS builder
ADD ./pom.xml pom.xml
ADD ./src src/
RUN mvn clean package
# 階段二:配置運行
From openjdk:8-jre-alpine
COPY --from=builder target/my-app-1.0-SNAPSHOT.jar my-app-1.0-SNAPSHOT.jar
EXPOSE 8080
CMD ["java", "-jar", "my-app-1.0-SNAPSHOT.jar"]
三、管理規(guī)范
1、限制用戶對容器主機的訪問
運行容器的主機應(yīng)該存放在安全、可靠的環(huán)境中,如IDC機房,這可以在物理上保證機器的安全性。同時 ,做好系統(tǒng)登錄權(quán)限的管控,只允許可信任的用戶登錄訪問主機,這樣能夠減少由于人為影響而出現(xiàn)的故障。
2、定期更新Docker版本
過時的版本由于已發(fā)現(xiàn)的漏洞,容易受到安全攻擊。新版本通常會修復(fù)舊版本出現(xiàn)的Bug和程序錯誤,有利于更好地保證容器安全。作為容器的管理員,需要定期進行Docker版本的更新,并維持著較新的版本。
3、完善容器監(jiān)控
如何合理有效的利用好監(jiān)控是容器管理員的重要工作,一套完善的監(jiān)控系統(tǒng)有利于幫助我們及時發(fā)現(xiàn)容器的問題,例如資源負(fù)載高、容器退出等。
關(guān)于容器的監(jiān)控,目前比較常用的方案有cAdvisor+Prometheus+Grafana+Alertmanager組合,該方案集成監(jiān)控、展示和告警等系列功能,可以有效發(fā)現(xiàn)容器問題。