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

  发布于 2023-01-08 14:55

在昨天有关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编辑初始文件后,npm install将以非root用户身份运行.并且由于一个postinstall钩子,npm运行bower install && grunt assets它负责剩余的安装步骤,并避免npm install -g任何节点cli工具,如bower,grunt或coffeescript.

3 个回答
  • 查看这篇文章:http://www.yegor256.com/2014/08/29/docker-non-root.html在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 是我们正在使用的用户.

    2023-01-08 14:57 回答
  • 这个有点棘手,实际上是由于你开始的图像.

    如果查看源代码,您会注意到它/data/是一个卷.因此,您在此处执行的所有操作都Dockerfile将被丢弃并在运行时被安装的卷覆盖.

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

    2023-01-08 14:57 回答
  • 更新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
    

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

    2023-01-08 15:00 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有