簡體   English   中英

在Docker中運行app作為非root用戶

[英]Running app inside Docker as non-root user

昨天有關Shocker的消息之后 ,似乎Docker容器中的應用程序不應該以root身份運行。 我嘗試更新我的Dockerfile以創建應用程序用戶,但是更改應用程序文件的權限(仍然是root用戶)似乎不起作用。 我猜這是因為某些LXC權限未被授予root用戶可能嗎?

這是我的Dockerfile:

# Node.js app Docker file

FROM dockerfile/nodejs
MAINTAINER Thom Nichols "thom@thomnichols.org"

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所有:

[ node@ed7ae33e76e1:/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/

由於@ creak對卷的工作原理的澄清, 我更新的dockerfile非常有用 一旦初始文件被chown ed, npm install作為非root用戶運行。 並且由於一個postinstall掛鈎,npm運行bower install && grunt assets來處理剩余的安裝步驟並避免任何需要npm install -g任何節點cli工具,如bower,grunt或coffeescript。

查看這篇文章: http//www.yegor256.com/2014/08/29/docker-non-root.htmlrultor.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是我們正在使用的用戶。

更新2015-09-28

我注意到這篇文章引起了一些關注。 對於有可能對此類事情感興趣的任何人的建議。 我會嘗試使用Python或其他語言作為腳本執行的包裝器。 做本機bash腳本我試圖通過各種參數傳遞給我的容器時遇到了問題。 具體來說,shell解釋/轉義“和”字符存在問題。


我需要更改用戶的原因略有不同。

我創建了一個docker圖像,其中包含ImageMagickFfmpeg的全功能安裝,希望我可以對我的主機操作系統中的圖像/視頻進行轉換。 我的問題是這些是命令行工具,因此通過docker執行它們然后將結果返回到主機操作系統稍微麻煩一些。 我設法通過安裝docker音量允許這個。 這似乎沒有用,除了圖像/視頻輸出是由root (即docker容器正在運行的用戶)所擁有的,而不是執行命令的用戶。

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

這是我的dockermagick shell腳本的一個例子:

#!/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) $@'"
}

### MAIN

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

此腳本綁定到'acleancoder / imagemagick-full'圖像,但可以通過編輯腳本頂部的變量來更改。

它基本上是做什么的:

  • 容器中創建用戶標識和組,以匹配從主機操作系統執行腳本的用戶。
  • 主機操作系統的當前工作目錄(使用docker卷)安裝到我們在執行的docker容器中創建的用戶的主目錄
  • 將tmp目錄設置為容器的工作目錄。
  • 傳遞傳遞給腳本的任何參數,然后由執行的docker容器的' / bin / bash '執行。

現在,我可以對主機操作系統上的文件運行ImageMagick / Ffmpeg命令。 例如,假設我想將圖像MyImage.jpeg轉換為PNG文件,我現在可以執行以下操作:

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

我還附加了'stdout',因此我可以運行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文件確實將此考慮在內,因此您可以擴展此腳本來執行此操作。

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

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

最好只是轉到包含圖像的目錄並直接執行它。 當然,我確信有辦法解決這個限制,但對我和我目前的需求,這樣做。

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

如果查看源代碼 ,您會注意到/data/是一個卷。 因此,您在Dockerfile執行的所有操作Dockerfile將被丟棄並在運行時被安裝的卷覆蓋。

您可以在運行時通過將CMD更改為CMD chown -R node /data && npm start

注意我在這里回答是因為,鑒於通用標題,當您尋找“以非root用戶身份在Docker中運行應用程序”的解決方案時,此問題會在Google中彈出。 希望它能幫助那些滯留在這里的人。

使用Alpine Linux,您可以創建如下系統用戶:

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

使用myuser執行此行之后Dockerfile所有內容。

myuser用戶有:

  • 沒有密碼分配
  • 沒有家庭目錄
  • 沒有登錄shell
  • 沒有root訪問權限。

這是來自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)

注意給出這個答案是因為許多尋找非root用法的人最終都會在這里結束。 請注意,這並沒有解決導致問題的問題,而是解決了@ yegor256給出的答案的標題和澄清,它使用了容器內的非root用戶。 這個答案解釋了如何為非debian /非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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM