【问题标题】:Docker Entrypoint Script Root PermissionDocker 入口点脚本根权限
【发布时间】:2018-07-08 18:27:51
【问题描述】:

我有一个 Dockerfile,它有 3 个约束:

1.) 出于安全考虑,Dockerfile 中的最终 USER 语句必须是 USER tomcat(它是基于 tomcat:8.5.23-jre8-alpine 映像构建的)

2.) 它不能在/root/ 目录或$JAVA_HOME 上运行chmod

3.) 它必须能够修改入口点中的$JAVA_HOME/lib/security 目录,而不是 Dockerfile 中的目录(因为证书是在容器启动时传入的)

到现在为止

FROM tomcat:8.5.23-jre8-alpine

#### OTHER IMAGE COMMANDS ####

COPY ./entrypoint.sh /usr/local/bin/entrypoint.sh

RUN chown root:root /usr/local/bin/entrypoint.sh

RUN chmod 4755 /usr/local/bin/entrypoint.sh

USER tomcat

ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
CMD ["catalina.sh", "run"]

我认为将文件的所有权授予 root 和 chmod 4755 将允许 tomcat 用户执行入口点,但让入口点以 root 身份运行,以便它可以根据需要修改文件系统。但是,当我在入口点运行这一行时

$JAVA_HOME/bin/keytool -import -alias ca_local -keystore $JAVA_HOME/lib/security/cacerts -storepass XXXXX -noprompt -trustcacerts -file /usr/local/tomcat/certificates/ca-local.cer

我收到以下错误:

keytool error: java.io.FileNotFoundException: /usr/lib/jvm/java-1.8-openjdk/jre/lib/security/cacerts (Permission denied)

似乎入口点实际上并未以 root 身份运行,正如 chown/chmod 所暗示的那样。我知道我的所有文件都在正确的位置,因为当我从 Dockerfile 中删除 USER tomcat 时,一切正常。我在设置入口点的权限时缺少什么?

【问题讨论】:

    标签: docker sh chmod keytool chown


    【解决方案1】:

    在这两个步骤中:

    RUN chown root:root /usr/local/bin/entrypoint.sh
    RUN chmod 4755 /usr/local/bin/entrypoint.sh
    

    您确保您的entrypoint.sh 脚本归root 所有,然后您尝试设置setuid 位。不幸的是,这第二步是行不通的:你不能将一个 shell 脚本(或者实际上任何解释脚本)标记为setuid;该位将被忽略。参见,例如,this question

    但是如果这有效,您将遇到另一个问题:您的 ENTRYPOINT 脚本负责处理传递到您的容器的任何命令,无论是在 docker run 命令行上还是通过 Dockerfile 中的 CMD 指令。如果setuid 尝试成功,您的ENTRYPOINT 脚本将以root 身份运行...这意味着您最终将以root 身份运行catalina.sh run,这意味着您的USER 指令完全没有意义。

    您可以通过简单地删除USER 指令,允许入口点以root 运行,然后让您的ENTRYPOINT 脚本以CMD 用户身份运行CMD(例如, 使用susudo):

    FROM tomcat:8.5.23-jre8-alpine
    
    #### OTHER IMAGE COMMANDS ####
    
    COPY ./entrypoint.sh /usr/local/bin/entrypoint.sh
    ENTRYPOINT ["sh", "/usr/local/bin/entrypoint.sh"]
    CMD ["catalina.sh", "run"]
    

    entrypoint.sh:

    #!/bin/sh
    
    # Do stuff as root here.
    $JAVA_HOME/bin/keytool -import -alias ca_local \
      -keystore $JAVA_HOME/lib/security/cacerts 
      -storepass XXXXX -noprompt -trustcacerts \
      -file /usr/local/tomcat/certificates/ca-local.cer
    
    # Now run everything else as a non-root user
    exec su - tomcat -c "$*"
    

    这是一种非常常见的机制,用于处理必须以 root 身份运行而以非 root 用户身份运行其他所有任务的初始设置任务。

    这里还有很多问题:底层tomcat:8.5.23-jre8-alpine没有tomcat用户,/usr/local/tomcat/bin中的脚本只能由root执行。因此,如果您希望此特定图像与非 root 用户一起使用,您可能需要先进行大量配置更改。

    【讨论】:

    • 许多镜像构建使用gosu 而不是susudo 以更兼容Docker
    • runuser 是一个不错的选择,如果您的发行版将其包含在基础映像中。
    • 谢谢!很好的解释,如果我能投 2 票,我会的。 Tomcat 用户配置位于#### OTHER IMAGE COMMANDS #### 部分,因此我将作为tomcat 用户从入口点运行我的CMD。
    猜你喜欢
    • 2016-12-17
    • 1970-01-01
    • 1970-01-01
    • 2016-10-08
    • 2021-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多