Docker RUN 命令不会保留文件

6
我是一位能帮助您翻译文本的助手。以下是所需翻译内容:

我在使用Docker时遇到了问题,无法持久化通过 "RUN" 启动的命令。

这是我的 Dockerfile:

FROM jenkins:latest

RUN echo "foo" > /var/jenkins_home/toto ; ls -alh  /var/jenkins_home
RUN ls -alh  /var/jenkins_home

RUN rm /var/jenkins_home/.bash_logout  ; ls -alh  /var/jenkins_home
RUN ls -alh  /var/jenkins_home

RUN echo "bar" >> /var/jenkins_home/.profile ; cat /var/jenkins_home/.profile
RUN  cat /var/jenkins_home/.profile

以下是输出结果:

Sending build context to Docker daemon 373.8 kB Step 1 : FROM jenkins:latest  ---> fc39417bd5fb Step 2 : RUN echo "foo" > /var/jenkins_home/toto ; ls -alh  /var/jenkins_home  ---> Using cache 
---> c614b13d9d83 Step 3 : RUN ls -alh  /var/jenkins_home  ---> Using cache  ---> 8a16a0c92f67 Step 4 : RUN rm /var/jenkins_home/.bash_logout  ; ls -alh  /var/jenkins_home  ---> Using cache  ---> f6ca5d5bdc64 Step 5 : RUN ls -alh  /var/jenkins_home
---> Using cache  ---> 3372c3275b1b Step 6 : RUN echo "bar" >> /var/jenkins_home/.profile ; cat /var/jenkins_home/.profile  ---> Running in 79842be2c6e3
# ~/.profile: executed by the command interpreter for login shells.
# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
# exists.
# see /usr/share/doc/bash/examples/startup-files for examples.
# the files are located in the bash-doc package.

# the default umask is set in /etc/profile; for setting the umask
# for ssh logins, install and configure the libpam-umask package.
#umask 022

# if running bash if [ -n "$BASH_VERSION" ]; then
    # include .bashrc if it exists
    if [ -f "$HOME/.bashrc" ]; then     . "$HOME/.bashrc"
    fi fi

# set PATH so it includes user's private bin if it exists if [ -d "$HOME/bin" ] ; then
    PATH="$HOME/bin:$PATH" fi bar  ---> 28559b8fe041 Removing intermediate container 79842be2c6e3 Step 7 : RUN cat /var/jenkins_home/.profile  ---> Running in c694e0cb5866
# ~/.profile: executed by the command interpreter for login shells.
# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
# exists.
# see /usr/share/doc/bash/examples/startup-files for examples.
# the files are located in the bash-doc package.

# the default umask is set in /etc/profile; for setting the umask
# for ssh logins, install and configure the libpam-umask package.
#umask 022

# if running bash if [ -n "$BASH_VERSION" ]; then
    # include .bashrc if it exists
    if [ -f "$HOME/.bashrc" ]; then     . "$HOME/.bashrc"
    fi fi

# set PATH so it includes user's private bin if it exists if [ -d "$HOME/bin" ] ; then
    PATH="$HOME/bin:$PATH" fi  ---> b7e47d65d65e Removing intermediate container c694e0cb5866 Successfully built b7e47d65d65e

你们知道为什么在第三步"foo"文件没有持久化吗?为什么在第五步".bash_logout"文件被重新创建了?为什么在第七步我的".profile"文件中再也找不到"bar"了?

当然,如果我基于这个镜像启动一个容器,我的所有修改都不会被持久化...所以我的Dockerfile是...无用的。有什么线索吗?

1个回答

17
The reason why these changes are not saved is because they are in a volume. In the Jenkins Dockerfile, /var/jenkins_home/ is marked as a VOLUME, and information inside volumes is not saved during docker build. Each build step creates a new volume based on the image's content, discarding the previous one.

How to solve this problem?

I believe the best solution is to:
  • 将您想要修改的文件添加到镜像中jenkins_home不同位置内,例如/var/jenkins_home_overrides/
  • 创建一个自定义入口点,基于默认入口点脚本或"包装",该脚本将在容器第一次启动时将jenkins_home_overrides的内容复制到jenkins_home

实际上...

当我写完这个之后,看起来官方的Jenkins镜像已经支持此功能; https://github.com/jenkinsci/docker/blob/683b0d6ed17016ee3211f247304ef2f265102c2b/jenkins.sh#L5-L23

根据文档, 您需要将文件添加到/usr/share/jenkins/ref/目录中,这些文件将在启动时复制到/var/jenkins/home

还请参见https://issues.jenkins-ci.org/browse/JENKINS-24986


太好了。就是这样。我以前写到另一个文件夹,没有注意到更改目标文件夹会产生如此大的影响。非常感谢。 - Olivier
谢谢兄弟。这个答案应该被添加到官方的Docker Jenkins镜像中。 - egelev
如果你有一行代码像 FROM jenkins:latest,你如何找到相应 Dockerfile 的源代码? - duhaime
寻找镜像的Dockerfile没有直接的方法,但是对于Docker Hub上的官方镜像,每个标签对应的Dockerfile都从Docker Hub的存储库描述中链接。在这种情况下,请查看https://hub.docker.com/_/jenkins下的“支持的标签”部分。请注意,Docker Hub上的“jenkins”镜像已被弃用,推荐使用https://hub.docker.com/r/jenkins/jenkins,该镜像似乎没有链接到Dockerfile。话虽如此,如果没有Dockerfile,您仍然可以`docker image inspect <image>`一个镜像以查找其是否使用卷。 - thaJeztah

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接