如何在 docker 容器中使用 sudo?
Posted
技术标签:
【中文标题】如何在 docker 容器中使用 sudo?【英文标题】:How to use sudo inside a docker container? 【发布时间】:2014-11-08 19:57:32 【问题描述】:通常,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
这导致 无法找到包 sudo
【问题讨论】:
只需给用户 sudo 组。 askubuntu.com/questions/7477/… 【参考方案1】:刚刚收到。正如 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 映像【参考方案2】:
当容器中 sudo 和 apt-get 均不可用时,您也可以使用命令以 root 用户身份跳转到正在运行的容器中
docker exec -u root -t -i container_id /bin/bash
【讨论】:
这对于 OP 可能想要实现的目标来说是一个更好的解决方案,即使接受的答案给出了请求的解决方案。至少,这是我一直在寻找的答案! 这是最好的答案,而不是用 dockerfile 来做这件事。 +1 我在更改 docker 内的权限时遇到问题。我知道只有 root 用户才能执行此操作,这是完成此操作的唯一方法。这样我就不需要sudo了! 有人给这个人一枚勋章【参考方案3】:其他答案对我不起作用。我一直在搜索并找到了一个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
权限的命令。【参考方案4】:
对于已经运行的容器存在此问题并且不一定要重建的任何人,以下命令连接到具有 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 exec
和docker commit
来创建一个新镜像并不是一个特别可维护的路径;如果您出于任何原因需要重新创建映像(例如原始基础映像中存在安全问题),则不会在任何地方跟踪这些手动步骤。
您是说将命令放在Dockerfile
或entrypoint
中并重建会更好吗?我可能误解了您的观点,我确实从“对于已经运行的容器遇到此问题的任何人,并且他们不一定想要重建”开始,并且我特别警告我们不能回溯的那一刻。我已经添加了您的警告“如果您从头开始重建,这些更改将不会重复”。你还有什么要补充的吗?【参考方案5】:
如果你想连接到容器并安装一些东西 使用 apt-get 首先是我们兄弟“Tomáš Záluský”的上述回答
docker exec -u root -t -i container_id /bin/bash
然后尝试
运行 apt-get update 或 apt-get 'anything you want'
它对我有用 希望对大家有用
【讨论】:
【参考方案6】:以下是我使用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
。
shell 设置为/bin/bash
。
sed
命令对/etc/sudoers
文件进行内联更新,以允许foo
和root
用户无密码访问sudo
组。
sed
命令禁用#includedir
指令,该指令将允许子目录中的任何文件覆盖这些内联更新。
【讨论】:
【参考方案7】:如果容器内无法访问 SUDO 或 apt-get,您可以在运行容器时使用以下选项。
docker exec -u root -it f83b5c5bf413 ash
"f83b5c5bf413" 是我的容器 ID & 这里是来自我的终端的工作示例:
【讨论】:
【参考方案8】:与accepted answer 不同,我使用usermod
代替。
假设已经在 docker 中以 root 身份登录,并且“fruit”是我要添加的新的非 root 用户名,只需运行以下命令:
apt update && apt install sudo
adduser fruit
usermod -aG sudo fruit
更新后记得保存图片。使用docker ps
获取当前运行的docker的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
【讨论】:
【参考方案9】:这可能不适用于所有图像,但某些图像已经包含 root 用户,例如在 jupyterhub/singleuser 图像中。使用该图像很简单:
USER root
RUN sudo apt-get update
【讨论】:
对于图像“fabric8/java-centos-openjdk8-jdk”,只需在 RUN 命令解决我的问题之前添加 USER root,甚至不需要添加 sudo【参考方案10】:如果您有一个以 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
。【参考方案11】:
没有关于如何在 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 设置中这样做。以上是关于如何在 docker 容器中使用 sudo?的主要内容,如果未能解决你的问题,请参考以下文章