如何在docker容器内使用sudo ?

通常,docker容器使用用户运行。我想使用一个不同的用户,这是没有问题使用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

568472 次浏览

刚刚明白。正如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

其他答案对我不起作用。我继续搜索并找到了一个博客,它涵盖了一个团队如何在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来实现这一点,但我怀疑其他类似的容器基也可以工作。

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

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

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

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

然后试着

运行apt-get update或apt-get '任何你想要的东西'

它对我有效 希望它对所有

有用

如果你有一个以根身份运行的容器,它运行一个需要访问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 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

下面是我如何使用ubuntu:18.04的基本映像设置一个非根用户:

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被添加到foosudo组中。
  • uidgid被设置为999的值。
  • 主目录被设置为/home/foo
  • shell被设置为/bin/bash
  • sed命令对/etc/sudoers文件进行内联更新,以允许fooroot用户无密码访问sudo组。
  • sed命令禁用了#includedir指令,该指令将允许子目录中的任何文件覆盖这些内联更新。

这可能不适用于所有映像,但有些映像已经包含根用户,例如jupyterhub/singleuser映像。对于这个图像,它很简单:

USER root
RUN sudo apt-get update

如果SUDOapt-get在容器内不可访问,你可以在运行的容器中使用下面的选项。

docker exec -u root -it f83b5c5bf413 ash

f83b5c5bf413”是我的容器ID,下面是我终端的工作示例:

enter image description here

接受的答案不同,我使用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 image。

然后测试:

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
关于如何在CentOS上做到这一点没有答案。 在Centos上,您可以在Dockerfile

中添加以下内容
RUN echo "user ALL=(root) NOPASSWD:ALL" > /etc/sudoers.d/user && \
chmod 0440 /etc/sudoers.d/user

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桌面时曾遇到过这个问题。

解决方法如下:

  1. apt-get更新
  2. 安装sudo

主要思想是,您需要根据容器创建一个根用户。

主要命令:

RUN echo "bot:bot" | chpasswd
RUN adduser bot sudo

第一个将字面值bot:bot发送给chpasswd,它创建了密码为bot的用户bot, chpasswd做的是:

The chpasswd command reads a list of user name and password pairs from standard input and uses this information to update a group of existing users. Each line is of the format:


user_name:password


By default the supplied password must be in clear-text, and is encrypted by chpasswd. Also the password age will be updated, if present.

我假设第二个命令将用户bot添加为sudo。

完整的docker容器来玩:

FROM continuumio/miniconda3
# FROM --platform=linux/amd64 continuumio/miniconda3


MAINTAINER Brando Miranda "me@gmail.com"


RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ssh \
git \
m4 \
libgmp-dev \
opam \
wget \
ca-certificates \
rsync \
strace \
gcc \
rlwrap \
sudo


# https://github.com/giampaolo/psutil/pull/2103


RUN useradd -m bot
# format for chpasswd user_name:password
RUN echo "bot:bot" | chpasswd
RUN adduser bot sudo


WORKDIR /home/bot
USER bot
#CMD /bin/bash