在 dockerfile 中处理用户并在其上安装软件包权限被拒绝
Working on user in dockerfile and installing packages on it permission denied
我想以 /home/user 中的用户身份在 dokefile 上安装软件包。
FROM ubuntu:16.04
ENV user lg
RUN useradd -m -d /home/${user} ${user} \
&& chown -R ${user} /home/${user}
USER ${user}
WORKDIR /home/${user}
RUN apt-get update
RUN apt-get -y install curl
RUN apt-get -y install lsb-core
RUN apt-get -y install lsb
RUN apt-get -y upgrade -f
Docker 在执行时抛出错误 apt-get update
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
谢谢:)
这是因为您的 lg
用户根本没有必要的权限。在这种情况下,ubuntu 被码头化并不重要。就像在任何其他 Linux 发行版中一样 - 您需要权限才能执行某些操作。举个例子:如果你在你的本地系统上创建一个新用户,我打赌命令 apt-get install X
会引发完全相同的错误,不是吗?
为了安装任何东西,您需要sudo
以该用户的根身份进行身份验证。这可以像这样实现:
FROM ubuntu:16.04
RUN apt-get update && \
apt-get -y install sudo
ENV user lg
RUN useradd -m -d /home/${user} ${user} && \
chown -R ${user} /home/${user} && \
adduser ${user} sudo && \
echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
USER ${user}
WORKDIR /home/${user}
RUN sudo apt-get -y install curl && \
sudo apt-get -y install lsb-core && \
sudo apt-get -y install lsb && \
sudo apt-get -y upgrade -f
一点解释:
- 首先,您需要安装 sudo 包
- 将您的用户添加到 sudo
- 并且您还需要将 NOPASSWD 添加到 sudoers 文件(我已经为所有用户添加了它,但您可以轻松地为特定用户设置它)。如果没有这个,您将遇到以下错误:
sudo: no tty present and no askpass program specified
- 现在你可以用这个用户安装东西了
同时尝试避免多次使用相同的 Dockerfile 指令(在您的情况下,您有多余的 4x 运行)。每条指令在以后的构建映像中都是一个单独的层。这就是众所周知的Dockerfile best practice.
Minimize the number of layers In older versions of Docker, it was
important that you minimized the number of layers in your images to
ensure they were performant. The following features were added to
reduce this limitation:
In Docker 1.10 and higher, only the instructions RUN, COPY, ADD create
layers. Other instructions create temporary intermediate images, and
do not directly increase the size of the build.
apt-get
在类 Debian 系统上通常需要 运行 作为 root。在 Dockerfile 中,您可以使用 USER
指令简单地切换用户身份;这通常默认为 运行ning 作为 root。您可以根据需要多次切换用户身份;但通常会先完成所有操作 "installation",然后再切换用户 ID。
(我不会让 "non-root user name" 或 "home directory" 之类的东西可参数化:它们是容器内部的,将它们视为固定的稍微容易一些,你几乎永远不会在容器外看到它们,并且就 docker run -v
之类的东西可以 与它们交互而言,如果它们是固定值就容易多了。)
所以我可能会像这样重写这个 Dockerfile:
FROM ubuntu:16.04
# Do this in one apt-get step for efficiency; and in the
# same Docker layer to avoid the APT cache getting out of
# date.
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get upgrade -f \
&& DEBIAN_FRONTEND=noninteractive apt-get install \
--no-install-recommends --assume-yes \
curl lsb lsb-core
# Set up the local user directory and copy the application in
# (still as root)
WORKDIR /lg
COPY . ./
# Now set up the non-root user
RUN user add -m -d /lg lg
USER lg
# Default thing to run when running the container
CMD ["/lg/lg"]
一般来说,您不应在映像中安装 su
或 sudo
。当 运行 非交互(例如在 Dockerfile 中)时,两者都有一些不直观的行为。在不寻常的情况下,您确实需要 docker exec
才能在 运行ning 容器中获得 shell,您可以轻松地向其添加 -u root
选项以成为任何一个你想要的用户。
我想以 /home/user 中的用户身份在 dokefile 上安装软件包。
FROM ubuntu:16.04
ENV user lg
RUN useradd -m -d /home/${user} ${user} \
&& chown -R ${user} /home/${user}
USER ${user}
WORKDIR /home/${user}
RUN apt-get update
RUN apt-get -y install curl
RUN apt-get -y install lsb-core
RUN apt-get -y install lsb
RUN apt-get -y upgrade -f
Docker 在执行时抛出错误 apt-get update
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
谢谢:)
这是因为您的 lg
用户根本没有必要的权限。在这种情况下,ubuntu 被码头化并不重要。就像在任何其他 Linux 发行版中一样 - 您需要权限才能执行某些操作。举个例子:如果你在你的本地系统上创建一个新用户,我打赌命令 apt-get install X
会引发完全相同的错误,不是吗?
为了安装任何东西,您需要sudo
以该用户的根身份进行身份验证。这可以像这样实现:
FROM ubuntu:16.04
RUN apt-get update && \
apt-get -y install sudo
ENV user lg
RUN useradd -m -d /home/${user} ${user} && \
chown -R ${user} /home/${user} && \
adduser ${user} sudo && \
echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
USER ${user}
WORKDIR /home/${user}
RUN sudo apt-get -y install curl && \
sudo apt-get -y install lsb-core && \
sudo apt-get -y install lsb && \
sudo apt-get -y upgrade -f
一点解释:
- 首先,您需要安装 sudo 包
- 将您的用户添加到 sudo
- 并且您还需要将 NOPASSWD 添加到 sudoers 文件(我已经为所有用户添加了它,但您可以轻松地为特定用户设置它)。如果没有这个,您将遇到以下错误:
sudo: no tty present and no askpass program specified
- 现在你可以用这个用户安装东西了
同时尝试避免多次使用相同的 Dockerfile 指令(在您的情况下,您有多余的 4x 运行)。每条指令在以后的构建映像中都是一个单独的层。这就是众所周知的Dockerfile best practice.
Minimize the number of layers In older versions of Docker, it was important that you minimized the number of layers in your images to ensure they were performant. The following features were added to reduce this limitation:
In Docker 1.10 and higher, only the instructions RUN, COPY, ADD create layers. Other instructions create temporary intermediate images, and do not directly increase the size of the build.
apt-get
在类 Debian 系统上通常需要 运行 作为 root。在 Dockerfile 中,您可以使用 USER
指令简单地切换用户身份;这通常默认为 运行ning 作为 root。您可以根据需要多次切换用户身份;但通常会先完成所有操作 "installation",然后再切换用户 ID。
(我不会让 "non-root user name" 或 "home directory" 之类的东西可参数化:它们是容器内部的,将它们视为固定的稍微容易一些,你几乎永远不会在容器外看到它们,并且就 docker run -v
之类的东西可以 与它们交互而言,如果它们是固定值就容易多了。)
所以我可能会像这样重写这个 Dockerfile:
FROM ubuntu:16.04
# Do this in one apt-get step for efficiency; and in the
# same Docker layer to avoid the APT cache getting out of
# date.
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get upgrade -f \
&& DEBIAN_FRONTEND=noninteractive apt-get install \
--no-install-recommends --assume-yes \
curl lsb lsb-core
# Set up the local user directory and copy the application in
# (still as root)
WORKDIR /lg
COPY . ./
# Now set up the non-root user
RUN user add -m -d /lg lg
USER lg
# Default thing to run when running the container
CMD ["/lg/lg"]
一般来说,您不应在映像中安装 su
或 sudo
。当 运行 非交互(例如在 Dockerfile 中)时,两者都有一些不直观的行为。在不寻常的情况下,您确实需要 docker exec
才能在 运行ning 容器中获得 shell,您可以轻松地向其添加 -u root
选项以成为任何一个你想要的用户。