【问题标题】:How to add users to Docker container?如何将用户添加到 Docker 容器?
【发布时间】:2015-02-26 09:50:51
【问题描述】:

我有一个 docker 容器,里面运行着一些进程(uwsgi 和 celery)。我想为这些进程创建一个 celery 用户和一个 uwsgi 用户,以及一个它们都属于的工作组,以便分配权限。

我尝试将 RUN adduser uwsgiRUN adduser celery 添加到我的 Dockerfile 中,但这会导致问题,因为这些命令会提示输入(我已经发布了来自下面构建的响应)。

将用户添加到 Docker 容器以便为在容器中运行的工作人员设置权限的最佳方法是什么?

我的 Docker 镜像是从官方的 Ubuntu14.04 基础构建的。

这是运行 adduser 命令时 Dockerfile 的输出:

Adding user `uwsgi' ...
Adding new group `uwsgi' (1000) ... 
Adding new user `uwsgi' (1000) with group `uwsgi' ... 
Creating home directory `/home/uwsgi' ...
Copying files from `/etc/skel' ... 
[91mEnter new UNIX password: Retype new UNIX password: [0m 
[91mpasswd: Authentication token manipulation error
passwd: password unchanged
[0m 
[91mUse of uninitialized value $answer in chop at /usr/sbin/adduser line 563.
[0m 
[91mUse of uninitialized value $answer in pattern match (m//) at /usr/sbin/adduser line 564.
[0m 
Try again? [y/N] 
Changing the user information for uwsgi
Enter the new value, or press ENTER for the default
    Full Name []: 
Room Number []:     Work Phone []:  Home Phone []:  Other []: 
[91mUse of uninitialized value $answer in chop at /usr/sbin/adduser line 589.
[0m 
[91mUse of uninitialized value $answer in pattern match (m//) at /usr/sbin/adduser line 590.
[0m 
Is the information correct? [Y/n] 
---> 258f2f2f13df 
Removing intermediate container 59948863162a 
Step 5 : RUN adduser celery 
---> Running in be06f1e20f64 
Adding user `celery' ...
Adding new group `celery' (1001) ... 
Adding new user `celery' (1001) with group `celery' ... 
Creating home directory `/home/celery' ...
Copying files from `/etc/skel' ... 
[91mEnter new UNIX password: Retype new UNIX password: [0m 
[91mpasswd: Authentication token manipulation error
passwd: password unchanged
[0m 
[91mUse of uninitialized value $answer in chop at /usr/sbin/adduser line 563.
[0m 
[91mUse of uninitialized value $answer in pattern match (m//) at /usr/sbin/adduser line 564.
[0m 
Try again? [y/N] 
Changing the user information for celery
Enter the new value, or press ENTER for the default
    Full Name []:   Room Number []:     Work Phone []: 
Home Phone []:  Other []: 
[91mUse of uninitialized value $answer in chop at /usr/sbin/adduser line 589.
[0m 
[91mUse of uninitialized value $answer in pattern match (m//) at /usr/sbin/adduser line 590.
[0m 
Is the information correct? [Y/n] 

【问题讨论】:

    标签: linux ubuntu dockerfile


    【解决方案1】:

    诀窍是使用useradd 而不是它的交互式包装器adduser。 我通常使用以下方式创建用户:

    RUN useradd -ms /bin/bash newuser
    

    它为用户创建一个主目录并确保 bash 是默认 shell。

    然后你可以添加:

    USER newuser
    WORKDIR /home/newuser
    

    到你的 dockerfile。之后的每个命令以及交互式会话都将以用户 newuser 的身份执行:

    docker run -t -i image
    newuser@131b7ad86360:~$
    

    在调用用户命令之前,您可能必须授予 newuser 执行您打算运行的程序的权限。

    出于安全原因,在容器内使用非特权用户是一个好主意。它也有一些缺点。最重要的是,从您的图像派生图像的人必须切换回 root 才能以超级用户权限执行命令。

    【讨论】:

    • 我建议在 Dockerfile 中使用全名选项,就像在脚本中一样,而不是短名称(在 IMO 交互使用时使用更多)。 useradd --create-home --shell /bin/bash 对同事来说更容易理解/可读。
    • 为了设置密码,你可以使用 chpasswd 像:RUN echo 'newuser:newpassword' | chpasswd
    • 请注意,如果您正在创建具有大用户 ID 的新用户,docker 可能会在尝试创建 lastlog - 一个巨大的稀疏文件时挂起/崩溃。使用--no-log-init 选项到useradd 来避免这种情况。
    • 不错的提示,@iuridiniz!不要忘记在USER newuser 之前调用它。如果还需要用户拥有root权限,还可以包含adduser <username> sudo
    • /bin/sh: useradd: not found alpine linux
    【解决方案2】:

    为避免 adduser 的交互式问题,您可以使用以下参数调用它:

    RUN adduser --disabled-password --gecos '' newuser
    

    --gecos 参数用于设置附加信息。在这种情况下,它只是空的。

    在带有busybox的系统(如Alpine)上,使用

    RUN adduser -D -g '' newuser
    

    busybox adduser

    【讨论】:

    • 谢谢!看起来adduser 高级解决方案通常比使用useradd 等低级功能更受欢迎。
    • adduser: unrecognized option: gecos 这似乎不适用于 Alpine。
    • --disabled-password 有什么作用,如何在 Dockerfile 中同时给用户设置密码?
    【解决方案3】:

    将此行添加到您的 Dockerfile(您可以通过这种方式运行任何 linux 命令)

    RUN useradd -ms /bin/bash yourNewUserName
    

    【讨论】:

      【解决方案4】:

      Ubuntu

      Dockerfile 中尝试以下行:

      RUN useradd -rm -d /home/ubuntu -s /bin/bash -g root -G sudo -u 1001 ubuntu
      USER ubuntu
      WORKDIR /home/ubuntu
      

      useradd 选项(参见:man useradd):

      • -r, --system 创建系统帐号。 见:Implications creating system accounts
      • -m, --create-home 创建用户的主目录。
      • -d, --home-dir HOME_DIR 新帐号的主目录。
      • -s, --shell SHELL 新账号的登录shell。
      • -g, --gid GROUP 主要组的名称或 ID。
      • -G, --groups GROUPS 补充组名单。
      • -u, --uid UID 指定用户 ID。 见:Understanding how uid and gid work in Docker containers
      • -p, --password PASSWORD 新账号的加密密码(如ubuntu)。

      设置默认用户密码

      要设置用户密码,请将-p "$(openssl passwd -1 ubuntu)" 添加到useradd 命令。

      或者将以下行添加到您的Dockerfile

      SHELL ["/bin/bash", "-o", "pipefail", "-c"]
      RUN echo 'ubuntu:ubuntu' | chpasswd
      

      第一个shell instruction 是确保-o pipefail 选项在RUN 之前启用,其中包含管道。阅读更多:Hadolint: Linting your Dockerfile

      【讨论】:

      • 为什么用户会在根组中?这不是为了安全目的而拥有一个非root用户吗
      • @Novaterata 取决于用途。 root group 并不表示他们有 root 访问权限,只是他们对某些文件(如日志)有更多的读取权限,这很有用,但取决于项目。
      • 我可以看到这行得通,我自动以用户身份登录,但我仍在生成 root 拥有的文件。我什至只使用了“用户用户”,因为我在本地用户和组上的用户名是“用户”。仍然生成根拥有的文件。还有什么我应该做的吗?我基本上是在制作一个 docker 容器来编译我们的代码库。所以它从 svn 中检查代码,使用 bash 源设置变量。即使我从未被要求输入 root 密码,bash 命令是否可以以 root 身份执行操作?
      • SHELL ["/bin/bash", "-o", "pipefail", "-c"] RUN echo 'ubuntu:ubuntu' | chpasswd 交互设置密码对我不起作用,容器刚刚构建,没有要求我输入密码。我做错了什么?
      • 为了安全,我推荐-p "$(openssl passwd -6 YOUR_PASS_HERE)"-1 选项使用不安全的基于 MD5 的哈希(以防数据库泄漏)。
      【解决方案5】:

      从安全角度来看,在 docker 中添加用户并在该用户下运行您的应用程序是非常好的做法。为此,我建议执行以下步骤:

      FROM node:10-alpine
      
      # Copy source to container
      RUN mkdir -p /usr/app/src
      
      # Copy source code
      COPY src /usr/app/src
      COPY package.json /usr/app
      COPY package-lock.json /usr/app
      
      WORKDIR /usr/app
      
      # Running npm install for production purpose will not run dev dependencies.
      RUN npm install -only=production    
      
      # Create a user group 'xyzgroup'
      RUN addgroup -S xyzgroup
      
      # Create a user 'appuser' under 'xyzgroup'
      RUN adduser -S -D -h /usr/app/src appuser xyzgroup
      
      # Chown all the files to the app user.
      RUN chown -R appuser:xyzgroup /usr/app
      
      # Switch to 'appuser'
      USER appuser
      
      # Open the mapped port
      EXPOSE 3000
      
      # Start the process
      CMD ["npm", "start"]
      

      以上步骤是复制 NodeJS 项目文件、创建用户组和用户、为用户分配项目文件夹的权限、切换到新创建的用户并在该用户下运行应用程序的完整示例。

      【讨论】:

      • addgroup 对我来说失败了,步骤 11/15:运行 addgroup -S 用户名 ---> 在 db9fd22d469d 中运行选项 s 不明确 (shell, system) adduser [--home DIR] [--shell SHELL] [--no-create-home] [--uid ID] [--firstuid ID] [--lastuid ID] [--gecos GECOS] [--ingroup GROUP | --gid ID] [--disabled-password] [--disabled-login] [--encrypt-home] USER 添加普通用户
      • 谢谢!经过多次尝试,这对我有用
      【解决方案6】:

      可以模仿开源的Dockerfile,例如:

      节点:node12-github

      RUN groupadd --gid 1000 node \
          && useradd --uid 1000 --gid node --shell /bin/bash --create-home node
      

      超集:superset-github

      RUN useradd --user-group --create-home --no-log-init --shell /bin/bash 
          superset
      

      我认为这是遵循开源的好方法。

      【讨论】:

        【解决方案7】:

        每个人都有自己的最爱,这是我的:

        RUN useradd --user-group --system --create-home --no-log-init app
        USER app
        

        参考:man useradd

        RUN 行将添加用户和组app

        root@ef3e54b60048:/# id app
        uid=999(app) gid=999(app) groups=999(app)
        

        如果要将图像用作基础图像,请使用比app 更具体的名称。顺便说一句,如果您确实需要,请添加 --shell /bin/bash


        部分归功于:answer by Ryan M

        【讨论】:

          【解决方案8】:

          您也可以这样做。

          RUN addgroup demo && adduser -DH -G demo demo
          

          第一个命令创建名为 demo 的组。第二个命令创建 demo 用户并将他添加到先前创建的 demo 组。

          标志代表:

          -G Group
          -D Don't assign password
          -H Don't create home directory
          

          【讨论】:

          • P.S 此命令可能会因 Linux 发行版而略有不同。
          猜你喜欢
          • 2019-09-19
          • 1970-01-01
          • 2021-12-18
          • 2017-07-11
          • 1970-01-01
          • 1970-01-01
          • 2015-04-02
          相关资源
          最近更新 更多