为什么简单的Dockerfile会给出;许可被拒绝;?

为什么简单的Dockerfile会给出;许可被拒绝;?,docker,Docker,我正在学习与ROS一起使用Docker,我对以下错误消息感到惊讶: FROM ros:kinetic-robot-xenial # create non-root user ENV USERNAME ros RUN adduser --ingroup sudo --disabled-password --gecos "" --shell /bin/bash --home /home/$USERNAME $USERNAME RUN bash -c 'echo $USERNAME:ros | ch

我正在学习与ROS一起使用Docker,我对以下错误消息感到惊讶:

FROM ros:kinetic-robot-xenial

# create non-root user
ENV USERNAME ros
RUN adduser --ingroup sudo --disabled-password --gecos "" --shell /bin/bash --home /home/$USERNAME $USERNAME
RUN bash -c 'echo $USERNAME:ros | chpasswd'
ENV HOME /home/$USERNAME
USER $USERNAME

RUN apt-get update
给出此错误消息

Step 7/7 : RUN apt-get update
 ---> Running in 95c40d1faadc
Reading package lists...
E: List directory /var/lib/apt/lists/partial is missing. - Acquire (13: Permission denied)
The command '/bin/sh -c apt-get update' returned a non-zero code: 100

您将用户
ros
添加到组
sudo
,但您尝试
apt-get-update
,而不使用sudo。因此,您以非特权方式运行该命令,并获得被拒绝的
权限

使用do运行命令(t):

总而言之,这没有多大意义。可以准备一个docker映像(例如安装软件等)及其根用户。如果您担心安全性(这是一件好事),请保留sudo内容,并确保与您的非特权用户一起执行映像(如创建容器)时运行的进程

还考虑多阶段构建,如果你想将图像的准备与实际可运行的事物分开:


apt get
通常需要以root用户身份运行,但一旦运行了
USER
命令,命令就不再以root用户身份运行

在Dockerfile开始时,您经常会运行这样的命令:如果可以,您希望利用Docker层缓存,并且通常会安装Dockerfile其余部分所需的依赖项。同样出于层缓存的原因,在一个步骤中运行
apt get update
和其他安装步骤也很重要。所以您的Dockerfile通常看起来像

来自ros的
:动力机器人xenial
#静根
运行apt获取更新\
&&apt获取安装。。。
#在应用程序中复制(仍为根用户,其他用户无法写入)
复制
CMD[“…”]
#现在,作为最后一步,创建一个用户并默认按其运行
运行adduser ros
用户ros
如果需要,您可以显式地
USER root
切换回root以执行后续命令,但通常更容易读取和维护DockerFile,用户切换更少


还要注意的是,无论是
sudo
还是用户密码在Docker中都不是真正有用的。一般来说,很难在脚本中运行
sudo
,很多Docker的事情都发生在脚本中。容器也几乎从不运行可能接受用户密码的
getty
sshd
之类的东西,而且它们从
docker历史记录
中读取也很简单,所以设置密码没有意义。相反,如果您要在容器中获取shell,则始终可以将
-u root
传递给
docker run
docker exec
命令以获取根shell。

尝试将此行放在dockerfile的末尾

用户$USERNAME(一旦这一行出现在dockerfile中…u将假定此用户权限…在这种情况下不必安装任何内容)
默认情况下,您是root用户

通过以下方式切换到root用户:

USER root

然后每个命令都应该起作用

您是否尝试过“RUN sudo apt…”奇怪的是,在ENV用户名之前将RUN apt移动到使问题消失。但我不知道为什么。在“RUN apt get…”之前加上“RUN whoami”,这两种情况下,
USER$USERNAME
行都会更改当前用户。在这一行之后,所有进一步的命令都以用户权限执行。将RUN-apt-get行放在该行之前会导致它作为root运行,从而具有正确的权限
USER root