摘要:發現問題之后,相應的解決方法也很簡單把當前目錄的擁有者賦值給,再啟動容器就一切正常了。這時我們已經可以知道容器的本地數據卷中文件目錄的權限是和宿主機上一致的,只是在容器和宿主機中可能映射為不同的用戶組名稱。
Volume數據卷是Docker的一個重要概念。數據卷是可供一個或多個容器使用的特殊目錄,可以為容器應用存儲提供有價值的特性:
持久化數據與容器的生命周期解耦:在容器刪除之后數據卷中的內容可以保持。Docker 1.9之后引進的named volume(命名文件卷)可以更加方便地管理數據卷的生命周期;數據卷可以被獨立地創建和刪除。 數據卷可以用于實現容器之間的數據共享 可以支持不同類型的數據存儲實現
Docker缺省提供了對宿主機本地文件卷的支持,可以將宿主機的目錄掛載到容器之中。由于沒有容器分層文件系統帶來的性能損失,本地文件卷非常適合一些需要高性能數據訪問的場景,比如MySQL的數據庫文件的存儲。同時Docker支持通過volume plugin實現不同類型的數據卷,可以更加靈活解決不同應用負載的存儲需求。比如在阿里云容器服務中可以為容器提供基于云盤的塊存儲、基于OSSFS和NAS/NFS的共享文件存儲。
然而Docker數據卷的權限管理經常是非常令人困惑的。本文將結合實例給大家介紹Docker數據卷權限管理中的常見問題和解決方法。
從Jenkins掛載本地數據卷錯誤談起
最近的一個同事在利用容器運行Jenkins時遇到一個問題,其復現步驟如下:
注:如果是Windows/Mac需要登錄到Boot2docker虛擬機之上,而Linux無需如此。
注:如果是Windows/Mac需要登錄到Boot2docker虛擬機之上,而Linux無需如此。
docker-machine ssh default
啟動Jenkins官方鏡像,并檢查日志
docker run -d -p 8080:8080 -p 50000:50000 --name jenkins jenkins docker logs jenkins
我們可以發現"jenkins"容器日志顯示結果一切正常
然而為了持久化Jenkins配置數據,當我們把宿主機當前目錄下的data文件夾掛載到容器中的目錄"/var/jenkins_home"的時候,問題出現了:
docker rm -f jenkins
docker run -d -p 8080:8080 -p 50000:50000 -v $(pwd)/data:/var/jenkins_home --name jenkins jenkins
docker logs jenkins
錯誤日志如下
touch: cannot touch ‘/var/jenkins_home/copy_reference_file.log’: Permission denied
Can not write to /var/jenkins_home/copy_reference_file.log. Wrong volume permissions?
這是神馬情況?
我們檢查一下之前啟動方式的"/var/jenkins_home"目錄權限,查看Jenkins容器的當前用戶: 當前用戶是"jenkins"而且"/var/jenkins_home"目錄是屬于jenkins用戶擁有的
docker@default:~$ docker run -ti --rm --entrypoint="/bin/bash" jenkins -c "whoami && id" jenkins uid=1000(jenkins) gid=1000(jenkins) groups=1000(jenkins) docker@default:~$ docker run -ti --rm --entrypoint="/bin/bash" jenkins -c "ls -la /var/jenkins_home" total 20 drwxr-xr-x 2 jenkins jenkins 4096 Jun 5 08:39 . drwxr-xr-x 28 root root 4096 May 24 16:43 .. -rw-r--r-- 1 jenkins jenkins 220 Nov 12 2014 .bash_logout -rw-r--r-- 1 jenkins jenkins 3515 Nov 12 2014 .bashrc -rw-r--r-- 1 jenkins jenkins 675 Nov 12 2014 .profile
而當映射本地數據卷時,/var/jenkins_home目錄的擁有者變成了root用戶
docker run -ti --rm -v $(pwd)/data:/var/jenkins_home --entrypoint="/bin/bash" jenkins -c "ls -la /var/jenkins_home" total 4 drwxr-sr-x 2 root staff 40 Jun 5 08:32 . drwxr-xr-x 28 root root 4096 May 24 16:43 ..
這就解釋了為什么當"jenkins"用戶的進程訪問"/var/jenkins_home"目錄時,會出現 Permission denied 的問題
我們再檢查一下宿主機上的數據卷目錄,當前路徑下"data"目錄的擁有者是"root",這是因為這個目錄是Docker進程缺省創建出來的。
docker@default:~$ ls -la data total 0 drwxr-sr-x 2 root staff 40 Jun 5 08:32 ./ drwxr-sr-x 5 docker staff 160 Jun 5 08:32 ../
發現問題之后,相應的解決方法也很簡單:把當前目錄的擁有者賦值給uid 1000,再啟動"jenkins"容器就一切正常了。
sudo chown -R 1000 data docker start jenkins
這時利用瀏覽器訪問 "http://192.168.99.100:8080/" 就可以看到Jenkins的Web界面了。注:如無法訪問,可能需要通過docker-machine ip命令獲得當前Docker宿主機的IP地址。
當我們再進入容器內部查看"/var/jenkins_home"目錄的權限,其擁有者已經變成 "jenkins"
docker@default:~$ docker exec jenkins ls -la /var/jenkins_home total 24 drwxr-sr-x 11 jenkins staff 340 Jun 5 09:00 . drwxr-xr-x 28 root root 4096 May 24 16:43 .. drwxr-sr-x 3 jenkins staff 60 Jun 5 08:59 .java -rw-r--r-- 1 jenkins staff 289 Jun 5 08:59 copy_reference_file.log ...
而有趣的是在宿主機上我們看到的 "data"目錄的擁有者是"docker",這是因為"docker"用戶在"boot2docker"宿主機上的uid也是"1000"。
docker@default:~$ ls -la data total 20 drwxr-sr-x 2 docker staff 40 Jun 5 11:55 ./ drwxr-sr-x 6 docker staff 180 Jun 5 11:55 ../ ...
這時我們已經可以知道:容器的本地數據卷中文件/目錄的權限是和宿主機上一致的,只是uid/gid在Docker容器和宿主機中可能映射為不同的用戶/組名稱。
在上文,我們使用了一個常見的技巧,即在宿主機上執行chown命令時采用了uid而不是具體的用戶名,這樣就可以保證設置正確的擁有者。
問題雖然解決了,但思考并沒有結束。因為當使用本地數據卷時,Jenkins容器會依賴宿主機目錄權限的正確性,這會給自動化部署帶來額外的工作。有沒有方法讓Jenkins容器為數據卷自動地設置正確的權限呢?這個問題對很多以non-root方式運行的應用也都有借鑒意義。
為non-root應用正確地掛載本地數據卷
我們可以從萬能的stackoverflow.com找到很多相關的討論,其中一個非常有借鑒意義問答如下
http://stackoverflow.com/ques...
其中的基本思路有兩個:
一個是利用Data Container的方法在容器間共享數據卷。這樣就規避了解決宿主機上數據卷的權限問題。由于在1.9版本之后,Docker提供了named volume來取代純數據容器,我們還需要真正地解決這個問題。
另外一個思路就是讓容器中以root用戶啟動,在容器啟動腳本中利用"chown"命令來修正數據卷文件權限,之后切換到non-root用戶來執行程序
我們來參照第二個思路來解決這個問題
下面是一個基于Jenkins鏡像的Dockerfile:它會切換到"root"用戶并在鏡像中添加"gosu"命令,和新的入口點"/entrypoint.sh"
FROM jenkins:latest USER root RUN GOSU_SHA=5ec5d23079e94aea5f7ed92ee8a1a34bbf64c2d4053dadf383992908a2f9dc8a && curl -sSL -o /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.9/gosu-$(dpkg --print-architecture)" && chmod +x /usr/local/bin/gosu && echo "$GOSU_SHA /usr/local/bin/gosu" | sha256sum -c - COPY entrypoint.sh /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"]
注釋:gosu 是經常出現在官方Docker鏡像中的一個小工具。它是"su"和"sudo"命令的輕量級替代品,并解決了它們在tty和信號傳遞中的一些問題。
新入口點的"entrypoint.sh"的內容如下:它會為"JENKINS_HOME"目錄設置"jenkins"的擁有權限,并且再利用"gosu"命令切換到"jenkins"用戶來執行"jenkins"應用。
#! /bin/bash set -e chown -R 1000 "$JENKINS_HOME" exec gosu jenkins /bin/tini -- /usr/local/bin/jenkins.sh
您可以直接從 https://github.com/denverdino... 獲得相關代碼,并構建自己的Jenkins鏡像。執行命令如下:
git clone https://github.com/AliyunContainerService/docker-jenkins cd docker-jenkins/jenkins docker build -t denverdino/jenkins .
然后基于新鏡像啟動Jenkins容器
docker rm -f jenkins docker run -d -p 8080:8080 -p 50000:50000 -v $(pwd)/data:/var/jenkins_home --name jenkins denverdino/jenkins
總結
本文介紹了Docker數據卷的基本概念。針對non-root進程訪問本地數據卷出現的權限問題,我們給出了一個解決方案。我們計劃在未來為大家繼續總結在Docker數據卷上遇到的一些其他問題,
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/26743.html
摘要:正式上線已經大約兩年,基本已經成熟,為宜信大數據創新中心各個團隊提供了統一的測試和生產環境,簡化了服務的部署與上線流程,也降低了運維人員對系統管理的復雜度。地址白皮書原文發布于高可用架構作者宜信大數據創新中心團隊王超一 一、基于Docker的PaaS平臺LAIN 在金融的場景下,LAIN 是為解放各個團隊和業務線的生產力而設計的一個云平臺。LAIN 正式上線已經大約兩年,基本已經成熟,...
摘要:前言容器技術中最核心的一個技術點是分層存儲。當容器運行在進程隔離模式下時,在容器內使用進程相關賬號進行操作。掛載好并指定盤符后就可以在在容器內開始使用掛載的存儲卷了。 前言 容器技術中最核心的一個技術點是分層存儲。在Linux下相關文件默認被存放在/var/lib/docker下,而在Windows 10下安裝Docker for Windows 后默認的存儲文件被放在 C:Progr...
閱讀 2020·2019-08-30 15:52
閱讀 2975·2019-08-29 16:09
閱讀 1323·2019-08-28 18:30
閱讀 2452·2019-08-26 12:24
閱讀 1089·2019-08-26 12:12
閱讀 2272·2019-08-26 10:45
閱讀 565·2019-08-23 17:52
閱讀 809·2019-08-23 16:03