【问题标题】:chmod in Dockerfile does not permanently change permissionsDockerfile 中的 chmod 不会永久更改权限
【发布时间】:2020-04-13 17:02:04
【问题描述】:

我有下面的 Dockerfile 来创建一个 nodejs 服务器。它克隆了一个包含启动节点服务器的脚本的存储库,但该脚本需要是可执行的。

我第一次启动这个 docker 容器时,它按预期工作。我知道 chown 正在做某事,因为没有它,脚本“不存在”,因为它没有 x 权限。 但是,如果我随后在容器中打开一个 TTY 并检查该文件,则权限并没有改变。如果容器重新启动,则会给出文件不存在的错误(缺少 x 权限)。如果我在第一次运行后手动执行 chmod,我可以毫无问题地重新启动容器。

我已经尝试将它作为组合 RUN 命令的一部分(如下所示)和单独的 RUN 命令,两者都正常编写和RUN ["chmod", "755" "/opt/youtube4me/start_all.sh"] 以及755+x。所有这些方式在第一次启动时都有效,但不会永久更改权限。

我对 docker 很陌生,我认为我缺少一些基本概念来解释 chmod 在某种上下文中运行(也许?)

FROM node:10.19.0-alpine
RUN apk update && \
    apk add git && \
    git clone https://github.com/0502-crew/youtube4me.git /opt/youtube4me && \
    chmod 755 /opt/youtube4me/start_all.sh
COPY config/. /opt/youtube4me/
EXPOSE 45011
WORKDIR /opt/youtube4me
CMD ["/opt/youtube4me/start_all.sh"]

更新 1 我用 docker 运行这些命令:

  • sudo docker build . -t 0502-crew/youtube4me
  • sudo docker container run -d --name youtube4me --network host 0502-crew/youtube4me

start_all.sh

#!/bin/sh

# Reset to master in case any force pushes were done
git reset --hard origin/master
# Start client server
cd client && npm i && npm run build && nohup npm run prod &
# Start api server
cd api && npm i && npm run build && nohup npm run prod &
# Keep server running by tailing nothing, forever...
tail -f /dev/null

我从中复制的配置文件夹仅包含 .gitignore 中的 2 个 .ts 文件,因此需要手动添加:

  • config/api/src/config/Config.ts
  • config/client/src/config/Config.ts

更新 2

如果我用CMD ["sh", "-c", "tail -f /dev/null"] 替换 CMD 行,那么 x 权限将保留在 sh 文件中。似乎执行脚本会删除权限...

【问题讨论】:

  • 您是否有可能在config 中也有一个start_all.sh
  • 你是如何运行容器的? start_all.sh 的内容是什么(特别是它的第一行 #! 是什么,它是否退出)?
  • 我已经更新了这个问题。配置中没有任何影响这一点(很确定这个问题在我添加配置副本之前发生)并且 start_all.sh 使用 sh 因为图像没有 bash。同样,脚本在我第一次启动容器时完美运行,但之后却没有。

标签: docker


【解决方案1】:

正如@dennisvandehoef 指出的那样,我的方法的基本原理是错误的。例如,在 Dockerfile 中包含 git clone 会产生副作用,即第二次构建映像不会再次克隆 repo,即使文件已更改。

不过,我确实找到了这种方法的解决方案,所以为了知识共享,我不妨分享一下:

我在 Windows 上开发,所以我不需要为脚本设置权限,但 Linux 确实需要它。我发现您仍然可以在 Windows 上使用 git 设置 +x 权限位并提交它。当 docker 克隆 repo 时,chmod 就不再需要了。

git update-index --chmod=+x start_all.sh

如果你然后用这个命令 ls 文件

git ls-files --stage

您会看到所有其他文件都是 100644,但 sh 文件是 100755(因此权限为 755)。

接下来直接提交

git commit -m"Made sh executable"

之后我不得不删除我的 docker 镜像并重建它以确保再次执行 git clone。 我稍后会重写我的 dockerfile,但现在它可以正常工作。

当 chmod 是 Dockerfile 的一部分时,x 位会消失,这对我来说仍然是个谜

【讨论】:

    【解决方案2】:

    您正在为您从 git 提取的项目构建一个 docker 文件,并且您的 start_all 脚本包含一个 git reset --hard origin/master,这是一种不好的做法,因为现在您无法创建 docker 映像的版本。

    您也将这两个文件复制到错误的目录。使用COPY config/. /opt/youtube4me/ 将它们直接复制到项目的根目录。而不是config/api/src/config/config/client/src/config/Config.ts中的给定位置

    我意识到修复这些问题并不能解决这个 chmod 问题本身。但对于您的特定用例,它可能会让它消失。

    此外,如果它是您从 git 中排除的秘密,那么您也不应该在构建时将它们添加到您的 docker-image 中(在您将其推送到 docker 之后),它将再次公开。因此,最好不要在构建时添加它们。

    你有没有尝试过这样的事情:

    Docker 文件

    FROM node:10.19.0-alpine
    
    RUN mkdir /opt/youtube4me    
    COPY . /opt/youtube4me/
    WORKDIR /opt/youtube4me
    
    RUN chmod 755 /opt/youtube4me/start_all.sh
    
    EXPOSE 45011
    CMD ["/opt/youtube4me/start_all.sh"]
    

    dockerignore

    api/src/config/Config.ts
    client/src/config/Config.ts
    

    脚本

    # Start client server
    cd client && npm i && npm run build && nohup npm run prod &
    # Start api server
    cd api && npm i && npm run build && nohup npm run prod &
    # Keep server running by tailing nothing, forever...
    tail -f /dev/null
    

    然后您需要使用 2 个卷运行 docker run 以将配置添加到其中。这是通过 -v 完成的。例如:docker run -v $(pwd)config/api/src/config/:api/src/config/ -v $(pwd)config/client/src/config/:client/src/config/

    我总是想知道为什么您在一个 docker 映像中运行这两种服务。如果这只是为了本地执行,您还可以考虑创建 2 个单独的 docker 镜像,并使用 docker-compose 来生成它们。

    加法1:

    我对此进行了一些思考,使用环境变量来配置 docker-image 而不是向其添加文件也是一个好习惯。你可能也想切换到那个。我建议阅读 this article 以更好地了解这样做的原因和其他可能性。

    加法2: 我创建了一个pull request on your code,这是一个使用 docker-compose 的示例。由于配置选项,它目前无法构建。但它会给你一些更多的见解。

    【讨论】:

    • 随着我对 docker 了解的增加,在过去的几个小时里,我开始意识到很多优点。我以这种方式设置它是因为我希望容器是自包含的,而主机上没有 repo 或卷。我确实明白你的意思,除了“附加 1”部分。你会用环境变量设置什么配置?配置文件夹中的秘密而不是使用卷?
    • 至少所有的秘密都应该设置为环境变量。您可以保留其他硬编码,因为它们是针对此特定项目的,并且对于使用 docker 映像的其他用户不会更改。我将在我的答案中添加一篇好文章的链接,该链接指出了有关此主题的更多信息。
    猜你喜欢
    • 2011-08-04
    • 2020-07-24
    • 2013-06-19
    • 2016-01-20
    • 2021-08-26
    • 2016-01-16
    • 2017-05-08
    • 2013-02-16
    • 2011-12-31
    相关资源
    最近更新 更多