Node.js 以非root用户身份在Docker内部运行应用程序

Node.js 以非root用户身份在Docker内部运行应用程序,node.js,docker,lxc,Node.js,Docker,Lxc,之后,Docker容器中的应用程序似乎不应该以root用户身份运行。我试图更新我的Dockerfile以创建应用程序用户,但是更改应用程序文件的权限(仍为root)似乎不起作用。我猜这是因为某些LXC权限没有被授予根用户,可能吧 这是我的Dockerfile: # Node.js app Docker file FROM dockerfile/nodejs MAINTAINER Thom Nichols "thom@thomnichols.org" RUN useradd -ms /bin/

之后,Docker容器中的应用程序似乎不应该以root用户身份运行。我试图更新我的
Dockerfile
以创建应用程序用户,但是更改应用程序文件的权限(仍为root)似乎不起作用。我猜这是因为某些LXC权限没有被授予根用户,可能吧

这是我的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"]
非常简单,但是当I
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对卷如何工作的澄清。初始化文件后,
chown
ed将以非root用户身份运行
npm安装。多亏了一个
postinstall
hook,npm运行
bower安装和&grunt资产
,它负责剩下的安装步骤,并且避免了对
npm安装-g
任何节点cli工具(如bower、grunt或coffeescript)的任何需要。

这一个有点棘手,实际上是由于您从映像开始的缘故

如果您这样做,您会注意到
/data/
是一个卷。因此,您在
Dockerfile
中执行的所有操作都将被丢弃,并在运行时被装载的卷覆盖

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

查看此帖子:在中,我们在自己的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对“and”字符的解释/转义存在问题


我需要更改用户,原因稍有不同

我创建了一个docker映像,其中包含了ImageMagick和Ffmpeg的全功能安装,我希望能够在我的主机操作系统中对图像/视频进行转换。我的问题是,这些都是命令行工具,因此通过docker执行它们,然后将结果返回到主机操作系统中要稍微复杂一些。我设法做到了这一点通过装载docker卷。这似乎可以正常工作,但图像/视频输出由root用户(即docker容器运行时的用户)而不是执行命令的用户所有

我看了@François Zaninotto在他的文章中提到的方法(你可以看到完整的make脚本)。这真的很酷,但我更喜欢创建一个bash shell脚本,然后在我的路径上注册。我从Makefile方法(特别是用户/组创建)中获取了一些概念然后我创建了shell脚本

下面是我的dockermagick shell脚本的一个示例:

!/bin/bash
###变数
DOCKER_IMAGE='acleancoder/imagemagick full:最新'
容器\u USERNAME='dummy'
容器\u GROUPNAME='dummy'
HOMEDIR='/home/'$CONTAINER\u用户名
组ID=$(ID-g)
用户_ID=$(ID-u)
###功能
创建用户命令
{
回音\
groupadd-f-g$GROUP\u ID$CONTAINER\u GROUPNAME'&&&'\
useradd-u$USER\u ID-g$CONTAINER\u GROUPNAME$CONTAINER\u USERNAME'&&&'\
mkdir--父$HOMEDIR'&&&'\
chown-R$CONTAINER\u用户名:$CONTAINER\u组名$HOMEDIR
}
执行_作为_cmd()
{
回音\
sudo-u$CONTAINER\u USERNAME HOME=$HOMEDIR
}
完整容器(cmd)()
{
echo“$(创建用户命令)和&$(按命令执行)$@”
}
###主要
评估码头运行\
--rm=真\
-标准\
-v$(pwd):$HOMEDIR\
-w$HOMEDIR\
$DOCKER_图像\
/bin/bash-ci$(完整容器\u cmd$@)
此脚本绑定到“acleancoder/imagemagick full”图像,但可以通过编辑脚本顶部的变量来更改

它的基本功能是:

  • 在容器中创建用户id和组,以匹配从主机操作系统执行脚本的用户
  • 将主机操作系统的当前工作目录(使用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 identify命令来获取主机上图像的信息,例如:

$dockermagick标识MyImage.jpeg
MyImage.jpeg jpeg 640x426 640x426+0+0 8位DirectClass 78.6KB 0.000u 0:00.000
挂载当前目录并允许传递任意命令定义以供执行存在明显的危险。但还有许多方法可以使脚本更安全。我在自己的非生产个人环境中执行此脚本,因此这些不是我最关心的问题。但我会高度重视M如果您选择扩展此脚本,请考虑其中的危险。我还需要指出的是,此脚本没有考虑OS X主机。我从中窃取的想法/概念确实考虑到了这一点,因此您可以扩展此脚本

另一个需要注意的限制是,我只能引用当前在我执行脚本的路径中的文件
RUN adduser user && \
    echo "user ALL=(root) NOPASSWD:ALL" | tee -a /etc/sudoers.d/user && \
    chmod 0440 /etc/sudoers.d/user
RUN su - user -c "echo Hello $HOME"
CMD ["su","-","user","-c","/bin/bash"]
RUN adduser -D -H -S -s /bin/false -u 1000 myuser
-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)