Docker RUN不保存文件 [英] Docker RUN does NOT persist files
问题描述
我的Docker文件是这样的:
FROM jenkins:latest
RUN echofoo> / 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 echobar>> /var/jenkins_home/.profile; cat /var/jenkins_home/.profile
RUN cat /var/jenkins_home/.profile
这里是输出:
将构建上下文发送到Docker守护程序373.8 kB步骤1:FROM jenkins:latest ---> fc39417bd5fb步骤2:RUN echofoo> / var / jenkins_home / toto; ls -alh / var / jenkins_home --->使用缓存
---> c614b13d9d83步骤3:运行ls -alh / var / jenkins_home --->使用缓存---> 8a16a0c92f67步骤4:运行rm /var/jenkins_home/.bash_logout; ls -alh / var / jenkins_home --->使用缓存---> f6ca5d5bdc64步骤5:运行ls -alh / var / jenkins_home
--->使用缓存---> 3372c3275b1b步骤6:RUN echobar>> /var/jenkins_home/.profile; cat /var/jenkins_home/.profile --->运行在79842be2c6e3
#〜/ .profile:由命令解释器执行登录shell。
#如果〜/ .bash_profile或〜/ .bash_login
#存在,则此文件不会被bash(1)读取。
#看到/ usr / share / doc / bash / examples / startup-files的例子。
#文件位于bash-doc包中。
#默认的umask设置在/ etc / profile中;要为ssh登录设置umask
#,请安装和配置libpam-umask包。
#umask 022
#如果运行bash,如果[-n$ BASH_VERSION];那么
#include .bashrc如果它存在
如果[-f$ HOME / .bashrc];然后 。 $ HOME / .bashrc
fi fi
#设置PATH,所以如果[-d$ HOME / bin];如果存在,它包含用户的私有bin;然后
PATH =$ HOME / bin:$ PATHfi bar ---> 28559b8fe041删除中间容器79842be2c6e3步骤7:运行cat /var/jenkins_home/.profile --->运行在c694e0cb5866
#〜/ .profile:由命令解释程序执行登录shell。
#如果〜/ .bash_profile或〜/ .bash_login
#存在,则此文件不会被bash(1)读取。
#看到/ usr / share / doc / bash / examples / startup-files的例子。
#文件位于bash-doc包中。
#默认的umask设置在/ etc / profile中;要为ssh登录设置umask
#,请安装和配置libpam-umask包。
#umask 022
#如果运行bash,如果[-n$ BASH_VERSION];那么
#include .bashrc如果它存在
如果[-f$ HOME / .bashrc];然后 。 $ HOME / .bashrc
fi fi
#设置PATH,所以如果[-d$ HOME / bin];如果存在,它包含用户的私有bin;然后
PATH =$ HOME / bin:$ PATHfi ---> b7e47d65d65e删除中间容器c694e0cb5866成功构建b7e47d65d65e
你们知道为什么foo文件不会持久存在步骤3?为什么在第5步上重新创建.bash_logout文件?为什么bar不在第7步中的.profile文件中?
当然,如果我根据这个图像启动一个容器,我的修改是持久的...所以我的Dockerfile是无用的。任何线索?
这些更改不会持续存在的原因是,它们位于卷 Jenkins Docker文件标记 / var / jenkins_home /
作为 VOLUME
。
卷内的信息在 docker build
,或更精确地;每个构建步骤基于图像的内容创建一个新的卷,丢弃在上一个构建步骤中使用的卷。
如何解决这个问题?
我认为解决这个问题的最好办法就是:
- 在图像内的其他位置添加要修改的文件,例如:
jenkins_home
/ var / jenkins_home_overrides /
- 根据或wrap创建一个自定义入口点,默认的entrypoint脚本复制您的
jenkins_home_overrides的内容
到jenkins_home
首次启动集装箱。
其实...
只要我写了这个;看起来像官方的詹金斯图像已经支持这个开箱即用;
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
I have a problem with Docker which does not persist commands launch via "RUN".
Here is my 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
And here is the output :
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
Do you guys know why "foo" file is not persisted on step 3? Why ".bash_logout" file is recreated on step 5? Why "bar" is not in my ".profile" file anymore on step 7?
And of course, if I start a container based on this image, none of my modifications are persisted... so my Dockerfile is... useless. Any clue?
The reason those changes are not persisted, is that they are inside a volume the Jenkins Dockerfile marks /var/jenkins_home/
as a VOLUME
.
Information inside volumes is not persisted during docker build
, or more precisely; each build-step creates a new volume based on the image's content, discarding the volume that was used in the previous build step.
How to resolve this?
I think the best way to resolve this, is to;
- Add the files you want to modify inside
jenkins_home
in a different location inside the image, e.g./var/jenkins_home_overrides/
- Create a custom entrypoint based on, or "wrapping", the default entrypoint script that copies the content of your
jenkins_home_overrides
tojenkins_home
the first time the container is started.
Actually...
And just when I wrote that up; It looks like the official Jenkins image already support this out of the box; https://github.com/jenkinsci/docker/blob/683b0d6ed17016ee3211f247304ef2f265102c2b/jenkins.sh#L5-L23
According to the documentation, you need to add your files to the /usr/share/jenkins/ref/
directory, and those will be copied to /var/jenkins/home
upon start.
Also see https://issues.jenkins-ci.org/browse/JENKINS-24986
这篇关于Docker RUN不保存文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!