首页 文章

在Docker中运行app作为非root用户

提问于
浏览
73

yesterday's news of 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"]

非常简单,但是当我仍然拥有所有东西时:

[ 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/

My updated dockerfile works great感谢@ creak对卷如何工作的澄清 . 初始文件为 chown 之后, npm install 将作为非root用户运行 . 并且由于 postinstall 钩子,npm运行 bower install && grunt assets ,它负责剩余的安装步骤,并避免任何节点cli工具如bower,grunt或coffeescript .

5 回答

  • 18

    这个有点棘手,实际上是由于你开始的图像 .

    如果您look at the source,您会注意到 /data/ 是一个卷 . 因此,您在 Dockerfile 中执行的所有操作都将被丢弃并在运行时被安装的卷覆盖 .

    您可以通过将CMD更改为 CMD chown -R node /data && npm start 来在运行时显示 .

  • 3

    查看这篇文章: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 是我们正在使用的用户 .

  • 0

    更新2015-09-28

    我注意到这篇文章引起了一些关注 . 对于有可能对此类事情感兴趣的任何人的建议 . 我会尝试使用Python或其他语言作为脚本执行的包装器 . 做本机bash脚本我试图通过各种参数传递给我的容器时遇到了问题 . 具体来说,shell解释/转义“和”字符存在问题 .


    我需要更改用户的原因略有不同 .

    我创建了一个docker图像,其中包含ImageMagick和Ffmpeg的全功能安装,希望我可以对我的主机操作系统中的图像/视频进行转换 . 我的问题是这些是命令行工具,因此通过docker执行它们然后将结果返回到主机操作系统稍微麻烦一些 . 我设法通过安装docker音量允许这个 . 这似乎没有问题,除了图像/视频输出是由root(即docker容器正在运行的用户)所拥有的,而不是执行命令的用户 .

    我看了@FrançoisZaninotto在他的answer中提到的方法(你可以看到完整的make脚本here) . 这真的很酷,但我更喜欢创建一个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 file确实将此考虑在内,因此您可以扩展此脚本来执行此操作 .

    需要注意的另一个限制是我只能引用当前在我执行脚本的路径中的文件 . 这是因为我安装卷的方式,所以以下方法不起作用:

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

    最好只是转到包含图像的目录并直接执行它 . 当然,我确信有办法解决这个限制,但对我和我目前的需求,这样做 .

  • 26

    Note :我在这里回答是因为,鉴于通用 Headers ,当你寻找"Running app inside Docker as non-root user"的解决方案时,谷歌会弹出这个问题 . 希望它能帮助那些滞留在这里的人 .

    使用 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)
    
  • 14

    Note :给出了这个答案,因为很多寻找非root用户的人都会在这里结束 . 请注意,这并没有解决导致问题的问题,而是解决了@ yegor256给出的答案的 Headers 和澄清,它使用了容器内的非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

相关问题