将 Docker 映像中的用户切换为非 root 用户

Posted

技术标签:

【中文标题】将 Docker 映像中的用户切换为非 root 用户【英文标题】:Switching users inside Docker image to a non-root user 【发布时间】:2014-08-24 08:15:12 【问题描述】:

我正在尝试将用户切换到 tomcat7 用户以设置 SSH 证书。

当我执行su tomcat7 时,什么都没有发生。

whoami 在做su tomcat7 之后仍然是 ruturns 根

执行more /etc/passwd,我得到以下结果,清楚地表明存在一个tomcat7用户:

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
www-data:x:33:33:www-data:/var/www:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
list:x:38:38:Mailing List Manager:/var/list:/bin/sh
irc:x:39:39:ircd:/var/run/ircd:/bin/sh
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
libuuid:x:100:101::/var/lib/libuuid:/bin/sh
messagebus:x:101:104::/var/run/dbus:/bin/false
colord:x:102:105:colord colour management daemon,,,:/var/lib/colord:/bin/false
saned:x:103:106::/home/saned:/bin/false
tomcat7:x:104:107::/usr/share/tomcat7:/bin/false

我要解决的是 Hudson 中的这个错误:

Command "git fetch -t git@________.co.za:_______/_____________.git +refs/heads/*:refs/remotes/origin/*" returned status code 128: Host key verification failed.

这是我的 Dockerfile,它需要一个现有的 hudson war 文件和 tarred 并构建映像的配置,hudson 运行良好,但由于用户 tomcat7 不存在证书,它无法访问 git。

FROM debian:wheezy

# install java on image
RUN apt-get update
RUN apt-get install -y openjdk-7-jdk tomcat7

# install hudson on image
RUN rm -rf /var/lib/tomcat7/webapps/*
ADD ./ROOT.tar.gz /var/lib/tomcat7/webapps/

# copy hudson config over to image
RUN mkdir /usr/share/tomcat7/.hudson
ADD ./dothudson.tar.gz /usr/share/tomcat7/
RUN chown -R tomcat7:tomcat7 /usr/share/tomcat7/

# add ssh certificates
RUN mkdir /root/.ssh
ADD ssh.tar.gz /root/

# install some dependencies
RUN apt-get update
RUN apt-get install --y maven
RUN apt-get install --y git
RUN apt-get install --y subversion

# background script
ADD run.sh /root/run.sh
RUN chmod +x /root/run.sh

# expose port 8080
EXPOSE 8080


CMD ["/root/run.sh"]

我正在使用最新版本的 Docker(Docker 版本 1.0.0,构建 63fe64c/1.0.0),这是 Docker 中的错误还是我的 Dockerfile 中缺少某些内容?

【问题讨论】:

你知道USER Dockerfile 指令吗? 不,你建议我用它做什么? 是否可以使用 USER 指令通过 Dockerfile 生成证书? RUNUSER 指令之后所做的一切都是在相应的 uid 下完成的,所以虽然我不确定我是否完全理解你的问题,但它看起来可能就是你要找的东西. @icecrime 不是所有的东西,不幸的是。 COPY 将文件创建为 uid 0,这意味着它们不能被非 root 用户写入,除非当前用户也是 root,否则在这些文件上运行 RUN chown ... 将不起作用。因此,一个人最终会在整个 Dockerfile 中在 root 和另一个用户之间来回切换。 【参考方案1】:

如果您需要执行特权任务,例如更改文件夹的权限,您可以以 root 用户身份执行这些任务,然后创建一个非特权用户并切换到它。

FROM <some-base-image:tag>

# Switch to root user
USER root # <--- Usually you won't be needed it - Depends on base image

# Run privileged command
RUN apt install <packages>
RUN apt <privileged command>

# Set user and group
ARG user=appuser
ARG group=appuser
ARG uid=1000
ARG gid=1000
RUN groupadd -g $gid $group
RUN useradd -u $uid -g $group -s /bin/sh -m $user # <--- the '-m' create a user home directory

# Switch to user
USER $uid:$gid

# Run non-privileged command
RUN apt <non-privileged command>

【讨论】:

【参考方案2】:

将此行添加到 docker 文件中

USER <your_user_name>

使用docker指令USER

【讨论】:

【参考方案3】:

你也应该能够做到:

apt install sudo

sudo -i -u tomcat

那么你应该是tomcat用户。目前尚不清楚您使用的是哪个 Linux 发行版,但例如,它适用于 Ubuntu 18.04 LTS。

【讨论】:

【参考方案4】:

您不应该在 dockerfile 中使用 su,但是您应该在 Dockerfile 中使用 USER 指令。

在Dockerfile 构建的每个阶段,都会创建一个新容器,因此您对用户所做的任何更改都不会在下一个构建阶段持续存在。

例如:

RUN whoami
RUN su test
RUN whoami

这绝不会说用户是test,因为在第二个 whoami 上生成了一个新容器。两者的输出都是 root(当然,除非您事先运行 USER)。

如果你这样做:

RUN whoami
USER test
RUN whoami

您应该看到root,然后是test

或者,您可以使用 sudo 以不同的用户身份运行命令,例如

sudo -u test whoami

不过好像还是用官方支持的指令比较好。

【讨论】:

我很好奇如何确保之前运行的命令对 Dockerfile 中设置的用户可用。 I have a question 在使用 USER 指令切换到另一个用户后,以前由 root 设置的文件夹和权限不可用。 你可能需要COPY --chown=myuser ... 如何在一次 RUN 中以不同用户的身份运行多个命令? RUN sudo su user &amp;&amp; command1 &amp;&amp; sudo su user2 &amp;&amp; command2 会起作用吗?【参考方案5】:

作为另一个答案的不同方法,您可以通过特定容器上的命令行作为每个命令来执行此操作,而不是在 Dockerfile 上创建映像时指示用户。

使用docker exec,使用--user指定交互式终端将使用哪个用户帐户(容器应该正在运行并且用户必须存在于容器化系统中):

docker exec -it --user [username] [container] bash

见https://docs.docker.com/engine/reference/commandline/exec/

【讨论】:

【参考方案6】:

没有真正的方法可以做到这一点。结果,像 mysqld_safe 这样的东西失败了,你不能在 Debian docker 容器中安装 mysql-server 而不跳过 40 圈,因为......好吧......如果它不是 root,它就会中止。

您可以使用 USER,但如果您不是 root,则无法进行 apt-get install。

【讨论】:

以上是关于将 Docker 映像中的用户切换为非 root 用户的主要内容,如果未能解决你的问题,请参考以下文章

docker 映像中的文件始终归 root 所有

如何在官方 docker php 映像上以非 root 用户身份运行 composer

不支持 Ubuntu 中的 Docker 将文件系统切换到覆盖?

在没有 root 访问权限的系统上构建 Docker 映像

如何在 docker 中以非 root 用户身份写入卷容器?

无法从Docker Hub中提取Docker中的Docker映像