docker 映像中的文件始终归 root 所有

Posted

技术标签:

【中文标题】docker 映像中的文件始终归 root 所有【英文标题】:files in docker image always owned by root 【发布时间】:2021-07-11 03:21:30 【问题描述】:

我的 docker 文件

FROM mcr.microsoft.com/playwright:focal as influencer-scraper

USER root

# Install tools as telnet
RUN apt-get update && apt-get install telnet -y
# RUN apk add chromium

RUN groupadd --gid 888 node \
    && useradd --uid 888 --gid node --shell /bin/bash --create-home node

USER node
WORKDIR /home/node
# Copy package.json and Yarn install (separate for cache)
COPY ./package.json ./
COPY ./yarn.lock ./
RUN yarn
# Copy everything and build
COPY . .
# Copy other config files
COPY ./.env ./.env

# Entry point
ENTRYPOINT ["yarn", "start"]
CMD ["--mongodb", "host.docker.internal:27017"]

但是,当我登录到 docker 镜像后,我发现所有文件都归 root 所有,这在运行时造成了麻烦

➜  influencer-scraper-js git:(master) ✗ docker run -it --entrypoint /bin/bash influencer-scraper:v0.1-6-gfe17ad4962-dirty
node@bce54c1024db:~$ ls -l
total 52
-rw-r--r--. 1 root root   542 Apr 16 04:15 Docker.md
-rw-r--r--. 1 root root   589 Apr 16 05:03 Dockerfile
-rw-r--r--. 1 root root   570 Apr 16 03:58 Makefile
-rw-r--r--. 1 root root   358 Apr 13 01:27 README.md
drwxr-xr-x. 1 root root    20 Apr 16 03:58 config
drwxr-xr-x. 1 root root    16 Apr 16 03:58 data
drwxr-xr-x. 1 root root    14 Apr 12 06:00 docker
-rw-r--r--. 1 root root   558 Apr 16 03:58 docker-compose.yml
drwxr-xr-x. 1 root root   140 Apr 13 01:27 generated
drwxr-xr-x. 1 root root  1676 Apr 16 04:47 node_modules
-rw-r--r--. 1 root root   583 Apr 16 03:58 package.json
drwxr-xr-x. 1 root root    34 Apr 13 01:27 proxy
drwxr-xr-x. 1 root root    40 Apr 13 01:27 src
-rw-r--r--. 1 root root 26230 Apr 16 03:58 yarn.lock

我该如何解决这个问题?我希望 workdir 仍归用户 node 所有。

【问题讨论】:

【参考方案1】:

您显示的文件列表在我看来几乎是正确的。您希望大部分文件归 root 所有,并且不可全局写入:如果代码中存在一些安全问题或其他错误,您不希望意外发生覆盖您的源文件、静态资产或其他内容。

这意味着您需要将实际的可写数据存储在不同的目录中,并且您的列表中包含一个data 目录,它可能充当此角色。你可以在你的 Dockerfile 中chown它。

为了清楚起见,在文件最后一直保持 root 用户身份会有所帮助,然后您可以声明备用用户来实际运行容器。

# USER root (if required)
RUN chown node data
...
USER node
CMD ["yarn", "start"]

当您启动容器时,您可以在该特定目录上挂载一个卷。此设置应按原样与命名卷一起使用

docker run \
  -v app_data:/home/node/data \
  ...

如果您想要/需要使用主机目录来存储数据,您还需要指定拥有该目录的主机用户 ID(通常是当前用户)。同样,应用程序代码将归 root 所有,并且是世界可读的,所以这不会改变;只有data 目录的内容和所有权很重要。

docker run \
  -u $(id -u) \
  -v "$(pwd)/app_data:/home/node/data" \
  ...

(不要使用卷来替换容器中的应用程序代码或库。在这种特殊情况下,这样做会掩盖 Dockerfile 中的此配置问题,并且当您尝试在没有本地构建卷。)

【讨论】:

【参考方案2】:

引用 Docker 文档:https://docs.docker.com/engine/reference/builder/#copy

COPY有两种形式:

COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]

如果--chown中不指定任何用户,则默认使用root

所有新文件和目录都使用 0 的 UID 和 GID 创建,除非可选的 --chown 标志指定给定的用户名、组名或 UID/GID 组合以请求复制内容的特定所有权。


你也可以在复制后尝试chown

chown root:node filename

【讨论】:

以上是关于docker 映像中的文件始终归 root 所有的主要内容,如果未能解决你的问题,请参考以下文章

从放置在本地目录中的摘要文件创建 Docker 映像

将 Docker 映像中的用户切换为非 root 用户

构建 docker 映像的文件所有权

无法从Docker Hub中提取Docker中的Docker映像

在没有 root 访问权限的系统上构建 Docker 映像

我可以控制 Docker 映像中绑定安装卷的所有者吗?