【问题标题】:How to avoid changing permissions on node_modules for a non-root user in docker如何避免更改 docker 中非 root 用户对 node_modules 的权限
【发布时间】:2021-12-25 16:35:11
【问题描述】:

我当前文件的问题是,在我的 entrypoint.sh 文件中,我必须将整个项目目录的所有权更改为非管理用户 (chown -R node /node-servers)。但是,当安装了很多npm 包时,这会花费很多时间。有没有办法避免chown node_modules 目录?

背景:我在Dockerfile 中以root 身份创建所有内容的原因是因为这样我可以匹配开发人员本地用户的UIDGID。这使得安装卷更容易。缺点是我必须在entrypoint.sh文件中从root下级,并确保整个项目文件的权限都已更改为非管理员用户。

我的 docker 文件:

FROM node:10.24-alpine

#image already has user node and group node which are 1000, thats what we will use

# grab gosu for easy step-down from root
# https://github.com/tianon/gosu/releases
ENV GOSU_VERSION 1.14

RUN set -eux; \
    \
    apk add --no-cache --virtual .gosu-deps \
        ca-certificates \
        dpkg \
        gnupg \
    ; \
    \
    dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \
    wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \
    wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \
    \
# verify the signature
    export GNUPGHOME="$(mktemp -d)"; \
    gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \
    gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \
    command -v gpgconf && gpgconf --kill all || :; \
    rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \
    \
# clean up fetch dependencies
    apk del --no-network .gosu-deps; \
    \
    chmod +x /usr/local/bin/gosu; \
# verify that the binary works
    gosu --version; \
    gosu nobody true


COPY ./ /node-servers

# Setting the working directory
WORKDIR /node-servers

# Install app dependencies
# Install openssl
RUN apk add --update openssl ca-certificates && \
    apk --no-cache add shadow && \
    apk add libcap && \
    npm install -g && \
    chmod +x /node-servers/entrypoint.sh && \
    setcap cap_net_bind_service=+ep /usr/local/bin/node

# Entrypoint used to load the environment and start the node server
#ENTRYPOINT ["/bin/sh"]

我的入口点.sh

# In Prod, this may be configured with a GID already matching the container
# allowing the container to be run directly as Jenkins. In Dev, or on unknown
# environments, run the container as root to automatically correct docker
# group in container to match the docker.sock GID mounted from the host
set -x
if [ -z ${HOST_UID+x} ]; then
    echo "HOST_UID not set, so we are not changing it"
else
    echo "HOST_UID is set, so we are changing the container UID to match"
    # get group of notadmin inside container
    usermod -u ${HOST_UID} node
    CUR_GID=`getent group node | cut -f3 -d: || true`
    echo ${CUR_GID}
    # if they don't match, adjust
    if [ ! -z "$HOST_GID" -a "$HOST_GID" != "$CUR_GID" ]; then
        groupmod -g ${HOST_GID} -o node
    fi
    if ! groups node | grep -q node; then
        usermod -aG node node
    fi
fi

# gosu drops from root to node user
set -- gosu node "$@"

[ -d "/node-servers" ] && chown -v -R node /node-servers

exec "$@"

【问题讨论】:

    标签: node.js bash docker


    【解决方案1】:

    您根本不需要在这里运行chown。保留 root(或主机用户)拥有的文件。只要它们是世界可读的,应用程序仍然可以运行;但如果存在某种安全问题或其他错误,应用程序将无法意外覆盖自己的源代码。

    然后您可以继续进一步简化。在大多数情况下,Unix 中的用户由他们的 数字 用户 ID 标识;实际上并不要求用户在/etc/passwd 中列出。如果不需要更改node 用户ID 并且不需要chown 文件,则入口点脚本简化为“切换用户ID 并运行主脚本”;但是 Docker 可以通过 docker run -u 选项为您提供备用用户 ID。这意味着您也不需要安装gosu,这是很多 Dockerfile 内容。

    所有这一切意味着您可以将 Dockerfile 缩减为:

    FROM node:10.24-alpine
    
    # Install OS-level dependencies (before you COPY anything in)
    apk add openssl ca-certificates
    
    # (Do not install gosu or its various dependencies)
    
    # Set (and create) the working directory
    WORKDIR /node-servers
    
    # Copy language-level dependencies in
    COPY package.json package-lock.json .
    RUN npm ci
    
    # Copy the rest of the application in
    # (make sure `node_modules` is in .dockerignore)
    COPY . .
    
    # (Do not call setcap here)
    
    # Set the main command to run
    USER node
    CMD npm run start
    

    然后当你运行容器时,你可以使用 Docker 选项来指定当前用户和附加能力。

    docker run                          \
      -d                                \ # in the background
      -u $(id -u)                       \ # as an alternate user
      -v "$PWD/data:/node-servers/data" \ # mounting a data directory
      -p 8080:80                        \ # publishing a port
      my-image
    

    Docker grants the NET_BIND_SERVICE capability by default 所以你不需要专门设置它。

    如果您使用绑定挂载来覆盖应用程序代码,同样的权限设置也将起作用;再次,没有chown 电话。

    docker run ...                  \
      -u $(id -u)                   \
      -v "$PWD:/node-servers"       \ # run the application from the host, not the image
      -v /node-servers/node_modules \ # with libraries that will not be updated ever
      ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-17
      • 2022-01-08
      • 1970-01-01
      • 2019-02-05
      • 2018-08-28
      • 1970-01-01
      • 1970-01-01
      • 2020-11-21
      相关资源
      最近更新 更多