ChatGPT解决这个技术问题 Extra ChatGPT

如何在 docker 容器中使用 sudo?

通常,docker 容器使用 root 用户运行。我想使用不同的用户,使用 docker 的 USER 指令没问题。但是这个用户应该能够在容器内使用 sudo。缺少此命令。

这是一个用于此目的的简单 Dockerfile:

FROM ubuntu:12.04

RUN useradd docker && echo "docker:docker" | chpasswd
RUN mkdir -p /home/docker && chown -R docker:docker /home/docker

USER docker
CMD /bin/bash

运行这个容器,我使用用户 'docker' 登录。当我尝试使用 sudo 时,找不到该命令。所以我尝试使用在我的 Dockerfile 中安装 sudo 包

RUN apt-get install sudo

这导致 Unable to locate package sudo

只需将 sudo 组提供给用户即可。 askubuntu.com/questions/7477/…

O
Ohmen

刚刚得到它。正如 regan 所指出的,我必须将用户添加到 sudoers 组。但主要原因是我忘记更新存储库缓存,所以 apt-get 找不到 sudo 包。它现在正在工作。这是完成的代码:

FROM ubuntu:12.04

RUN apt-get update && \
      apt-get -y install sudo

RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo

USER docker
CMD /bin/bash

在centos中不起作用。 adduser 命令输出 useradd 的使用帮助
对于 CentOS,您可以添加用户和组,然后在 /etc/sudoers.d/ 下创建一个分片文件并将该文件的权限设置为 440。然后用户将在 CentOS 6 及更高版本下拥有 sudo 访问权限。 5 您必须在 /etc/sudoers 中添加 #includedir /etc/sudoers.d 指令
对我不起作用。我有这些错误: E: 无法打开锁定文件 /var/lib/apt/lists/lock - open (13: Permission denied) E: Unable to lock directory /var/lib/apt/lists/
这似乎不适用于 Ubuntu 18.04 docker 映像
T
Tomáš Záluský

当容器中 sudo 和 apt-get 均不可用时,您也可以使用命令以 root 用户身份跳转到正在运行的容器中

docker exec -u root -t -i container_id /bin/bash

对于 OP 可能想要实现的目标,这是一个更好的解决方案,即使接受的答案给出了请求的解决方案。至少,这是我正在寻找的答案!
这是最好的答案,而不是用 dockerfile 来做这件事。
+1 我在更改 docker 内的权限时遇到问题。我知道只有 root 用户才能执行此操作,这是完成它的唯一方法。这样,我就不需要 sudo 了!
有人给这个人一枚奖章
S
Seth Bergman

其他答案对我不起作用。我不断搜索并找到了一个 blog post,其中介绍了团队如何在 docker 容器内以非 root 用户运行。

这是 TL;DR 版本:

RUN apt-get update \
 && apt-get install -y sudo

RUN adduser --disabled-password --gecos '' docker
RUN adduser docker sudo
RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers

USER docker

# this is where I was running into problems with the other approaches
RUN sudo apt-get update 

我为此使用了 FROM node:9.3,但我怀疑其他类似的容器库也可以使用。


我正在使用 ubuntu:bionic-20180724.1。我使用了这种方法,但是在上述方法之后,它不允许我安装另一个包。我在上面的 Dockerfile 中添加了一行,以便安装带有 RUN apt-get install -y tree 的软件包。但是,它给了我这个错误信息:Step xxxx/xxxx : RUN apt-get install -y tree ---> Running in j5e6gsvwfafa Reading package lists... E: Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied) E: Unable to lock directory /var/lib/apt/lists/
@WR 我认为您需要将该行更改为 RUN sudo apt-get install -y tree。将 USER 设置为 root 以外的其他值后,您需要将 sudo 用于任何需要 root 权限的命令。
C
Chris

对于已经运行的容器存在此问题并且不一定要重建的任何人,以下命令连接到具有 root 权限的正在运行的容器:

docker exec -ti -u root container_name bash

您还可以使用其 ID 而不是其名称进行连接,方法是通过以下方式找到它:

docker ps -l

要保存您的更改,以便下次启动容器(或 docker-compose 集群)时它们仍然存在 - 请注意,如果您从头开始重建,这些更改将不会重复:

docker commit container_id image_name

要回滚到以前的图像版本(警告:这会删除历史记录而不是追加到末尾,因此要保留对当前图像的引用,请首先使用可选步骤对其进行标记):

docker history image_name
docker tag latest_image_id my_descriptive_tag_name  # optional
docker tag desired_history_image_id image_name

要启动未运行的容器并以 root 身份连接:

docker run -ti -u root --entrypoint=/bin/bash image_id_or_name -s

从正在运行的容器中复制:

docker cp <containerId>:/file/path/within/container /host/path/target

要导出图像的副本:

docker save container | gzip > /dir/file.tar.gz

您可以使用以下命令恢复到另一个 Docker 安装:

gzcat /dir/file.tar.gz | docker load

它更快,但需要更多空间来不压缩,使用:

docker save container | dir/file.tar

和:

cat dir/file.tar | docker load

使用 docker execdocker commit 创建新图像不是特别可维护的路径;如果您出于任何原因需要重新创建映像(例如原始基础映像中存在安全问题),则不会在任何地方跟踪这些手动步骤。
您是说将命令放在 Dockerfileentrypoint 中并重建会更好吗?我可能误解了你的观点,我确实从“对于已经运行的容器有这个问题的任何人,他们不一定想要重建”开始,我特别警告我们不能回溯的那一刻。我已添加您的警告“如果您从头开始重建,这些更改将不会重复”。你还有什么要补充的吗?
a
alexander.polomodov

如果您想连接到容器并首先使用 apt-get 安装一些东西,如我们兄弟“Tomáš Záluský”的回答

docker exec -u root -t -i container_id /bin/bash

然后尝试

运行 apt-get update 或 apt-get 'anything you want'

它对我有用,希望对所有人有用


S
Seth Bergman

以下是我使用 ubuntu:18.04 的基本映像设置非 root 用户的方法:

RUN \
    groupadd -g 999 foo && useradd -u 999 -g foo -G sudo -m -s /bin/bash foo && \
    sed -i /etc/sudoers -re 's/^%sudo.*/%sudo ALL=(ALL:ALL) NOPASSWD: ALL/g' && \
    sed -i /etc/sudoers -re 's/^root.*/root ALL=(ALL:ALL) NOPASSWD: ALL/g' && \
    sed -i /etc/sudoers -re 's/^#includedir.*/## **Removed the include directive** ##"/g' && \
    echo "foo ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers && \
    echo "Customized the sudoers file for passwordless access to the foo user!" && \
    echo "foo user:";  su - foo -c id

上面的代码会发生什么:

用户和组 foo 被创建。

用户 foo 被添加到 foo 和 sudo 组中。

uid 和 gid 设置为值 999。

主目录设置为 /home/foo。

外壳设置为 /bin/bash。

sed 命令对 /etc/sudoers 文件进行内联更新,以允许 foo 和 root 用户无密码访问 sudo 组。

sed 命令禁用 #includedir 指令,该指令将允许子目录中的任何文件覆盖这些内联更新。


Y
Yogi Ghorecha

如果容器内无法访问 SUDO 或 apt-get,您可以在运行容器中使用以下选项。

docker exec -u root -it f83b5c5bf413 ash

“f83b5c5bf413”是我的容器 ID,这是来自我的终端的工作示例:

https://i.stack.imgur.com/813r9.png


林果皞

accepted answer 不同,我使用 usermod

假设已经在 docker 中以 root 身份登录,并且“fruit”是我要添加的新的非 root 用户名,只需运行以下命令:

apt update && apt install sudo
adduser fruit
usermod -aG sudo fruit

更新后记得保存图片。使用 docker ps 获取当前运行的 docker 的 <CONTAINER ID>和 <IMAGE>,然后运行 docker commit -m "added sudo user" <CONTAINER ID> <IMAGE> 以保存 docker 映像。

然后测试:

su fruit
sudo whoami

或者在启动 docker 时以非 root 用户身份直接登录(确保先保存图像)进行测试:

docker run -it --user fruit <IMAGE>
sudo whoami

您可以使用 sudo -k 重置密码提示时间戳:

sudo whoami # No password prompt
sudo -k # Invalidates the user's cached credentials
sudo whoami # This will prompt for password

A
Alex Kaszynski

这可能不适用于所有图像,但某些图像已经包含 root 用户,例如在 jupyterhub/singleuser 图像中。使用该图像很简单:

USER root
RUN sudo apt-get update

对于图像“fabric8/java-centos-openjdk8-jdk”,只需在 RUN 命令解决我的问题之前添加 USER root,甚至不需要添加 sudo
X
XtraSimplicity

如果您有一个以 root 身份运行的容器,该容器运行需要访问 sudo 命令的脚本(您无法更改),您只需在 $PATH 中创建一个新的 sudo 脚本来调用传递的命令.

例如在你的 Dockerfile 中:

RUN if type sudo 2>/dev/null; then \ 
     echo "The sudo command already exists... Skipping."; \
    else \
     echo -e "#!/bin/sh\n\${@}" > /usr/sbin/sudo; \
     chmod +x /usr/sbin/sudo; \
    fi

根据您使用的 docker 映像(在我的例子中是 Ubuntu:18.04),您可能需要从 echo 中删除 -e。否则它将出现在文件本身中,使其无法正常工作。
好主意,但是如果原始命令使用 sudo 选项,例如 sudo -E ls,这将不起作用。它将尝试执行 -E ls
A
Animesh

没有关于如何在 CentOS 上执行此操作的答案。在 Centos 上,您可以将以下内容添加到 Dockerfile

RUN echo "user ALL=(root) NOPASSWD:ALL" > /etc/sudoers.d/user && \
    chmod 0440 /etc/sudoers.d/user

但此命令仍然失败:bash Step 6/8 : RUN echo "user ALL=(root) NOPASSWD:ALL" > /etc/sudoers.d/user && chmod 0440 /etc/sudoers.d/user ---> Running in daea0aae031c /bin/sh: 1: cannot create /etc/sudoers.d/user: Permission denied
这实质上使您的“非 root”用户等同于 root,只要攻击者知道在他们的命令前加上 sudo。它比以 root 身份运行要好一些,但我通常不建议在 Docker 设置中使用它。
E
Erkan Şirin

Centos7 的示例 Dockerfile。在此示例中,我们添加了具有 sudo 权限的 prod_user。

FROM centos:7

RUN yum -y update && yum clean all

RUN yum -y install openssh-server  python3 sudo

RUN adduser -m prod_user && \
    echo "MyPass*49?" | passwd prod_user --stdin && \
    usermod -aG wheel prod_user && \
    mkdir /home/prod_user/.ssh && \
    chown prod_user:prod_user -R  /home/prod_user/ && \
    chmod 700 /home/prod_user/.ssh

RUN echo "prod_user ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers && \
    echo "%wheel ALL=(ALL) ALL" >> /etc/sudoers

RUN echo "PasswordAuthentication yes" >> /etc/ssh/sshd_config

RUN systemctl enable sshd.service

VOLUME [ "/sys/fs/cgroup" ]

ENTRYPOINT ["/usr/sbin/init"]

A
ABHISHEK KAMBLE

我使用的是 Ubuntu 映像,而使用 docker 桌面时遇到了这个问题。

以下解决了该问题:

apt-get 更新 apt-get 安装 sudo