2014-06-19 290 views
68

yesterday's news of Shocker之後,Docker容器中的應用程序似乎不應該作爲root運行。我試圖更新我的Dockerfile以創建應用程序用戶,但是更改應用程序文件的權限(仍然是root用戶)似乎無法正常工作。我猜這是因爲一些LXC權限沒有被授予root用戶?在Docker中以非root用戶身份運行應用程序

這裏是我的Dockerfile:

# Node.js app Docker file 

FROM dockerfile/nodejs 
MAINTAINER Thom Nichols "[email protected]" 

RUN useradd -ms /bin/bash node 

ADD . /data 
# This next line doesn't seem to have any effect: 
RUN chown -R node /data 

ENV HOME /home/node 
USER node 

RUN cd /data && npm install 

EXPOSE 8888 

WORKDIR /data 

CMD ["npm", "start"] 

很簡單,但是當我ls -l一切仍屬於root:

[ [email protected]:/data {docker-nonroot-user} ]$ ls -l /data 
total 64K 
-rw-r--r-- 1 root root 383 Jun 18 20:32 Dockerfile 
-rw-r--r-- 1 root root 862 Jun 18 16:23 Gruntfile.js 
-rw-r--r-- 1 root root 1.2K Jun 18 15:48 README.md 
drwxr-xr-x 4 root root 4.0K May 30 14:24 assets/ 
-rw-r--r-- 1 root root 416 Jun 3 14:22 bower.json 
-rw-r--r-- 1 root root 930 May 30 01:50 config.js 
drwxr-xr-x 4 root root 4.0K Jun 18 16:08 lib/ 
drwxr-xr-x 42 root root 4.0K Jun 18 16:04 node_modules/ 
-rw-r--r-- 1 root root 2.0K Jun 18 16:04 package.json 
-rw-r--r-- 1 root root 118 May 30 18:35 server.js 
drwxr-xr-x 3 root root 4.0K May 30 02:17 static/ 
drwxr-xr-x 3 root root 4.0K Jun 18 20:13 test/ 
drwxr-xr-x 3 root root 4.0K Jun 3 17:38 views/ 

My updated dockerfile works great感謝@吱吱的澄清的體積是如何工作的。一旦初始文件爲chown ed,則npm install以非root用戶身份運行。並且感謝postinstall掛鉤,npm運行bower install && grunt assets,它負責處理剩餘的安裝步驟,並避免任何需要npm install -g任何節點cli工具(如bower,grunt或coffeescript)。

+0

只是好奇,你肯定'node'用戶是越來越產生的? –

+0

@ a.m。是的,用戶肯定是創建的。當我運行'docker run -it myimage/bin/bash'並運行'whoami'時,我以'node'登錄,這正是我所期望的。 –

回答

14

這一個有點棘手,它實際上是由於你從圖像開始。

如果您look at the source,您注意到/data/是一個卷。因此,您在Dockerfile中執行的所有操作都將在運行時被隨後安裝的卷丟棄和覆蓋。

通過將您的CMD更改爲類似CMD chown -R node /data && npm start的東西,可以在運行時切換。

+0

有趣!我想我沒有/沒有完全理解音量概念(我將開始閱讀),也沒有區分運行時和編譯時間。 –

+2

不幸的是'CMD chown ...'不會工作,因爲這將作爲obv沒有權限更改'root'擁有的文件權限的'node'用戶來運行。 我開始懷疑,如果源代碼在運行時不可寫,那麼應用程序有權訪問可寫位置,如日誌和運行時編譯文件。 可以在運行時創建不屬於root的卷嗎? –

+0

不是我所知道的。另一種方法是不使用USER節點,保持root並以'su節點-c「npm start」'啓動npm。但根據您的需要,只要您有權訪問可寫目錄,就應該以只讀方式運行。 – creack

26

Check this post:http://www.yegor256.com/2014/08/29/docker-non-root.html In rultor.com我們在自己的Docker容器中運行所有構建。每次在容器中運行腳本之前,我們都會切換到非root用戶。這是如何:

adduser --disabled-password --gecos '' r 
adduser r sudo 
echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers 
su -m r -c /home/r/script.sh 

r是我們正在使用的用戶。

+1

您可能必須使用以下命令顯式創建用戶的主目錄:'adduser -m --disabled-password --gecos''r ' – bonh

+0

基於Red Hat的系統,比如Fedora和CentOS,你必須以不同的方式做到這一點。 – gbraad

17

更新2015年9月28日

我已經注意到這個帖子得到一點關注。對任何有興趣做這樣的事情的人來說,建議一句話。我會嘗試使用Python或其他語言作爲腳本執行的包裝。做本地bash腳本當我試圖通過各種參數傳遞給我的容器時遇到問題。具體有問題與解釋/由外殼的「逃逸,」字符。


我需要改變用戶一個稍微不同的原因。

我創建了一個泊塢窗圖像住房一個全功能的安裝ImageMagickFfmpeg希望我可以對我的主機操作系統中的圖像/視頻進行轉換。我的問題是這些是命令行工具,所以通過docker執行它們會稍微棘手一點,然後將結果返回到主機操作系統時間通過安裝碼頭容積來實現。這似乎工作正常,除了圖像/視頻輸出由(即碼頭容器運行的用戶)擁有,而不是執行命令的用戶擁有。

我看着@FrançoisZaninotto在他的answer中提到的方法(您可以看到完整的製作腳本here)。這真的很酷,但我更喜歡創建一個bash shell腳本的選項,然後我將在我的路徑上註冊。我從Makefile方法中獲取了一些概念(特別是用戶/組創建),然後創建了shell腳本。

這是我的dockermagick外殼腳本的一個示例:

#!/bin/bash 

### VARIABLES 

DOCKER_IMAGE='acleancoder/imagemagick-full:latest' 
CONTAINER_USERNAME='dummy' 
CONTAINER_GROUPNAME='dummy' 
HOMEDIR='/home/'$CONTAINER_USERNAME 
GROUP_ID=$(id -g) 
USER_ID=$(id -u) 

### FUNCTIONS 

create_user_cmd() 
{ 
    echo \ 
    groupadd -f -g $GROUP_ID $CONTAINER_GROUPNAME '&&' \ 
    useradd -u $USER_ID -g $CONTAINER_GROUPNAME $CONTAINER_USERNAME '&&' \ 
    mkdir --parent $HOMEDIR '&&' \ 
    chown -R $CONTAINER_USERNAME:$CONTAINER_GROUPNAME $HOMEDIR 
} 

execute_as_cmd() 
{ 
    echo \ 
    sudo -u $CONTAINER_USERNAME HOME=$HOMEDIR 
} 

full_container_cmd() 
{ 
    echo "'$(create_user_cmd) && $(execute_as_cmd) [email protected]'" 
} 

### MAIN 

eval docker run \ 
    --rm=true \ 
    -a stdout \ 
    -v $(pwd):$HOMEDIR \ 
    -w $HOMEDIR \ 
    $DOCKER_IMAGE \ 
    /bin/bash -ci $(full_container_cmd [email protected]) 

該腳本被綁定到「acleancoder/ImageMagick的滿」圖像,但可以通過在頂部編輯變量來改變的腳本。

它通常做的是:

  • 容器中創建一個用戶ID和組誰從主機OS執行腳本的用戶相匹配。
  • 坐騎主機OS(使用泊塢窗卷)轉化爲我們執行泊塢窗容器中創建用戶主目錄的當前工作目錄。
  • 將tmp目錄設置爲容器的工作目錄。
  • 傳遞任何傳遞給該腳本的參數,然後將由正在執行的碼頭容器的'/bin/bash'執行。

現在我能夠在我的主機操作系統上運行鍼對文件的ImageMagick/ffmpeg的命令。例如,假設我想圖像MyImage.jpeg轉換成PNG 文件,我現在能做到以下幾點:

$ cd ~/MyImages 
$ ls 
    MyImage.jpeg 
$ dockermagick convert MyImage.jpeg Foo.png 
$ ls 
    Foo.png MyImage.jpeg 

我還連接到「標準輸出」,所以我可以運行ImageMagick的識別命令獲取的圖像信息我的主機上,用於如:

$ dockermagick identify MyImage.jpeg 
    MyImage.jpeg JPEG 640x426 640x426+0+0 8-bit DirectClass 78.6KB 0.000u 0:00.000 

大約有安裝當前目錄下,並允許沿執行傳遞任意命令定義顯而易見的危險。但是也有很多方法可以使腳本更安全。我在我自己的非生產性個人環境中執行此操作,因此這些對我來說並不是最關心的。但是,如果您選擇擴展此腳本,我強烈建議您考慮危險因素。還值得一提的是,這個腳本不考慮OS X主機。我盜取想法/概念的make file確實考慮到了這一點,所以你可以擴展這個腳本來做到這一點。

需要注意的另一個限制是,我只能引用當前正在執行腳本的路徑中的文件。這是因爲我安裝的卷的方式,所以下面是行不通的:

$ cd ~/MyImages 
$ ls 
    MyImage.jpeg 
$ dockermagick convert ~/DifferentDirectory/AnotherImage.jpeg Foo.png 
$ ls 
    MyImage.jpeg 

它最好只是去包含圖像的目錄,然後直接執行反對。當然,我相信也有辦法繞過這個限制,但是對於我和我目前的需求,這是可以做到的。

+2

這是一個非常整潔的概念,使用docker作爲隔離/端口命令行工具的一種方式! –

+0

這很棒!現在使用它,儘管適應Python並集成到我自己的「docker」包裝器中。 –

+0

(唯一的問題是它對你可以使用的Docker鏡像設置了一定的約束;也就是說,它們支持所有這些命令) –

0

注意給出了這個答案是因爲很多尋找非根用法的人會在這裏結束。請注意,這並沒有解決導致問題的問題,而是解決了標題並澄清了@ yegor256提供的答案,該答案在容器中使用了非root用戶。這個答案解釋瞭如何完成這個非debian/non-Ubuntu的使用案例。這不能解決卷的問題。

在基於Red Hat的系統,比如Fedora和CentOS,這可以通過以下方式進行:

RUN adduser user && \ 
    echo "user ALL=(root) NOPASSWD:ALL" | tee -a /etc/sudoers.d/user && \ 
    chmod 0440 /etc/sudoers.d/user 

在你Dockerfile您可以通過運行該用戶身份的命令:

RUN su - user -c "echo Hello $HOME" 

和命令可以運行爲:

CMD ["su","-","user","-c","/bin/bash"] 

的例如這可以在這裏找到: https://github.com/gbraad/docker-dev/commit/644c51002f4b8e6fe5bb745638542a4c3d908b16

+0

這並沒有解決OP的問題,即他們在不適用於最終映像的捲上做了chown。將echo的輸出發送到管道以便在文件中發球似乎很奇怪,爲什麼不用'>>來追加。並且讓用戶完全sudo訪問根用戶可以取消以非root用戶身份運行容器的所有好處。 – BMitch

+0

這與@ yegor256給出的答案有關。我無法在評論部分澄清......我將在地址 – gbraad

+0

的答案中包含此信息。更新的信息:http://gbraad.nl/blog/non-root-user-inside-a-docker-container。 HTML – gbraad

2

注意我的回答是,因爲在這裏,給出的通用名稱,在谷歌,當你看裏面碼頭工人作爲非解決「運行的應用程序這個問題彈出根用戶「。希望它能幫助那些滯留在這裏的人。

隨着高山 Linux可以創建一個系統用戶是這樣的:在此之後線與myuser執行

RUN adduser -D -H -S -s /bin/false -u 1000 myuser 

一切都在Dockerfile

myuser用戶:

  • 沒有分配
  • 沒有目錄
  • 沒有登錄shell
  • 沒有訪問密碼。

這是adduser --help

-h DIR  Home directory 
-g GECOS GECOS field 
-s SHELL Login shell 
-G GRP  Add user to existing group 
-S   Create a system user 
-D   Don't assign a password 
-H   Don't create home directory 
-u UID  User id 
-k SKEL  Skeleton directory (/etc/skel) 
相關問題