通常,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
刚刚得到它。正如 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
当容器中 sudo 和 apt-get 均不可用时,您也可以使用命令以 root 用户身份跳转到正在运行的容器中
docker exec -u root -t -i container_id /bin/bash
其他答案对我不起作用。我不断搜索并找到了一个 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/
RUN sudo apt-get install -y tree
。将 USER
设置为 root
以外的其他值后,您需要将 sudo
用于任何需要 root
权限的命令。
对于已经运行的容器存在此问题并且不一定要重建的任何人,以下命令连接到具有 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
中并重建会更好吗?我可能误解了你的观点,我确实从“对于已经运行的容器有这个问题的任何人,他们不一定想要重建”开始,我特别警告我们不能回溯的那一刻。我已添加您的警告“如果您从头开始重建,这些更改将不会重复”。你还有什么要补充的吗?
如果您想连接到容器并首先使用 apt-get 安装一些东西,如我们兄弟“Tomáš Záluský”的回答
docker exec -u root -t -i container_id /bin/bash
然后尝试
运行 apt-get update 或 apt-get 'anything you want'
它对我有用,希望对所有人有用
以下是我使用 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 指令,该指令将允许子目录中的任何文件覆盖这些内联更新。
如果容器内无法访问 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
这可能不适用于所有图像,但某些图像已经包含 root 用户,例如在 jupyterhub/singleuser 图像中。使用该图像很简单:
USER root
RUN sudo apt-get update
如果您有一个以 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
echo
中删除 -e
。否则它将出现在文件本身中,使其无法正常工作。
sudo -E ls
,这将不起作用。它将尝试执行 -E ls
。
没有关于如何在 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
sudo
。它比以 root 身份运行要好一些,但我通常不建议在 Docker 设置中使用它。
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"]
我使用的是 Ubuntu 映像,而使用 docker 桌面时遇到了这个问题。
以下解决了该问题:
apt-get 更新 apt-get 安装 sudo
adduser
命令输出useradd
的使用帮助/etc/sudoers.d/
下创建一个分片文件并将该文件的权限设置为440
。然后用户将在 CentOS 6 及更高版本下拥有 sudo 访问权限。 5 您必须在/etc/sudoers
中添加#includedir /etc/sudoers.d
指令