如何在 Docker 图像中写入文件?
How to write files in Docker Images?
我已经将文件复制到 docker 图像中:
COPY dbconfig.xml /var/app/dbconfig.xml
之后,我尝试将文件中的一些值替换为:
RUN sed -i "s/PASSWD/$dbpasswd/" /var/app/dbconfig.xml
请注意 $dbpassword 是一个 ENV 变量。
当我检查 config.xml 的内容时,通过启动该图像的容器和其中的 运行 一个 bash,dbconfig.xml 中没有任何变化.
现在我想我误解了 docker 图像的一些基本原理..
我什至测试过创建一个简单的文件:
RUN echo "test" > newfile.txt
调用后好像删除了..
我知道每个 运行 语句都会创建一个 新层 并且在语句之后它会被删除(?)。
我很困惑。为什么用
安装软件之类的东西
RUN apt-get install -y some-package
没有被删除并且创建一个简单的文件确实被删除了?
所以..我如何在图像构建时更改 docker 图像中的文件?
Dockerfile:
FROM dchevell/jira-software:8.0
COPY dbconfig.xml /var/atlassian/application-data/jira/dbconfig.xml
WORKDIR /var/atlassian/application-data/jira
# set default password to admin
ENV dbpasswd=admin
RUN sed -i "s/PASSWD/$dbpasswd/" dbconfig.xml \
&& cat dbconfig.xml
RUN echo "test" > newfile.txt
dbconfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<jira-database-config>
<name>defaultDS</name>
<delegator-name>default</delegator-name>
<database-type>postgres72</database-type>
<schema-name>public</schema-name>
<jdbc-datasource>
<url>jdbc:postgresql://docker-postgres:5432/jiradb</url>
<driver-class>org.postgresql.Driver</driver-class>
<username>atlasdb</username>
<password>PASSWD</password>
<pool-test-while-idle>true</pool-test-while-idle>
</jdbc-datasource>
</jira-database-config>
更新 1
令人困惑的是,当我在 WORKDIR 文件夹中复制某些内容时,它仍然存在,但是当我随后尝试使用 SED 对其进行修改时,这些更改不会持续存在!我认为在后台发生了一些真正的黑暗魔法......
也许我尝试将我预配置的 dbconfig.xml 绑定到 docker-compose 中,看看是否有帮助..
更新 2
Changing the volume from within the Dockerfile: If any build steps
change the data within the volume after it has been declared, those
changes will be discarded.
我完全错过了!感谢 David 指点我:) 所以创建和编写文件确实按预期工作,但要小心 VOLUME 目录。 运行 语句在这里不起作用。
因此,要解决此问题,最佳做法是将文件绑定挂载到该卷中。
每个RUN
语句不会创建一个中间容器,而是在联合文件系统上创建一个新层,它是只读的。当您 运行 图像时,将为该容器创建一个特殊的可写层,并且您对该容器所做的所有更改都将写入该层。 (卷除外。这是一个不同的概念)。这就是为什么 docker 能够在容器之间安全地共享相同的图像(甚至层),而不会相互影响。您可以查看 docker documentation 了解更多信息。
对于您的问题,您应该在构建时在此图像的 运行ning 实例中看到您所做的所有更改,除非您以某种方式删除或覆盖它们。
看到这个。
您运行的命令是正确的,它们应该创建文件。我怀疑的是,当您 运行 您的容器时,jira 应用程序正在覆盖您指定的 WORKDIR
。
试试这个 Dockerfile:
WORKDIR /var/atlassian/application-data/jira
# set default password to admin
ENV dbpasswd=admin
RUN sed -i "s/PASSWD/$dbpasswd/" dbconfig.xml \
&& cat dbconfig.xml
WORKDIR /testtest
RUN touch test.txt
RUN echo "test" > newfile.txt
WORKDIR /var/atlassian/application-data/jira
现在,如果您启动容器,您可以看到文件正在 /testtest 文件夹中创建。
如果您希望对 dbconfig.xml 文件所做的更改持续存在,您应该尝试使用卷将本地 dbconfig.xml 与 jira 文件夹绑定。
感谢这个有趣的问题:)
如果你看the Dockerfile for that base image,它说部分
ENV JIRA_HOME /var/atlassian/application-data/jira
VOLUME ["${JIRA_HOME}"]
在 Dockerfile 中执行 VOLUME 语句后,later Dockerfile statements can't make any more changes in that specific directory。
考虑到您尝试更改的是非常特定于安装的设置(管理员密码、数据库设置),我不会尝试使用这些来构建映像。相反,我会使用 docker run -v
选项在运行时注入配置文件。
我已经将文件复制到 docker 图像中:
COPY dbconfig.xml /var/app/dbconfig.xml
之后,我尝试将文件中的一些值替换为:
RUN sed -i "s/PASSWD/$dbpasswd/" /var/app/dbconfig.xml
请注意 $dbpassword 是一个 ENV 变量。
当我检查 config.xml 的内容时,通过启动该图像的容器和其中的 运行 一个 bash,dbconfig.xml 中没有任何变化.
现在我想我误解了 docker 图像的一些基本原理..
我什至测试过创建一个简单的文件:
RUN echo "test" > newfile.txt
调用后好像删除了.. 我知道每个 运行 语句都会创建一个 新层 并且在语句之后它会被删除(?)。
我很困惑。为什么用
安装软件之类的东西RUN apt-get install -y some-package
没有被删除并且创建一个简单的文件确实被删除了?
所以..我如何在图像构建时更改 docker 图像中的文件?
Dockerfile:
FROM dchevell/jira-software:8.0
COPY dbconfig.xml /var/atlassian/application-data/jira/dbconfig.xml
WORKDIR /var/atlassian/application-data/jira
# set default password to admin
ENV dbpasswd=admin
RUN sed -i "s/PASSWD/$dbpasswd/" dbconfig.xml \
&& cat dbconfig.xml
RUN echo "test" > newfile.txt
dbconfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<jira-database-config>
<name>defaultDS</name>
<delegator-name>default</delegator-name>
<database-type>postgres72</database-type>
<schema-name>public</schema-name>
<jdbc-datasource>
<url>jdbc:postgresql://docker-postgres:5432/jiradb</url>
<driver-class>org.postgresql.Driver</driver-class>
<username>atlasdb</username>
<password>PASSWD</password>
<pool-test-while-idle>true</pool-test-while-idle>
</jdbc-datasource>
</jira-database-config>
更新 1
令人困惑的是,当我在 WORKDIR 文件夹中复制某些内容时,它仍然存在,但是当我随后尝试使用 SED 对其进行修改时,这些更改不会持续存在!我认为在后台发生了一些真正的黑暗魔法...... 也许我尝试将我预配置的 dbconfig.xml 绑定到 docker-compose 中,看看是否有帮助..
更新 2
Changing the volume from within the Dockerfile: If any build steps change the data within the volume after it has been declared, those changes will be discarded.
我完全错过了!感谢 David 指点我:) 所以创建和编写文件确实按预期工作,但要小心 VOLUME 目录。 运行 语句在这里不起作用。 因此,要解决此问题,最佳做法是将文件绑定挂载到该卷中。
每个RUN
语句不会创建一个中间容器,而是在联合文件系统上创建一个新层,它是只读的。当您 运行 图像时,将为该容器创建一个特殊的可写层,并且您对该容器所做的所有更改都将写入该层。 (卷除外。这是一个不同的概念)。这就是为什么 docker 能够在容器之间安全地共享相同的图像(甚至层),而不会相互影响。您可以查看 docker documentation 了解更多信息。
对于您的问题,您应该在构建时在此图像的 运行ning 实例中看到您所做的所有更改,除非您以某种方式删除或覆盖它们。
看到这个
您运行的命令是正确的,它们应该创建文件。我怀疑的是,当您 运行 您的容器时,jira 应用程序正在覆盖您指定的 WORKDIR
。
试试这个 Dockerfile:
WORKDIR /var/atlassian/application-data/jira
# set default password to admin
ENV dbpasswd=admin
RUN sed -i "s/PASSWD/$dbpasswd/" dbconfig.xml \
&& cat dbconfig.xml
WORKDIR /testtest
RUN touch test.txt
RUN echo "test" > newfile.txt
WORKDIR /var/atlassian/application-data/jira
现在,如果您启动容器,您可以看到文件正在 /testtest 文件夹中创建。
如果您希望对 dbconfig.xml 文件所做的更改持续存在,您应该尝试使用卷将本地 dbconfig.xml 与 jira 文件夹绑定。
感谢这个有趣的问题:)
如果你看the Dockerfile for that base image,它说部分
ENV JIRA_HOME /var/atlassian/application-data/jira
VOLUME ["${JIRA_HOME}"]
在 Dockerfile 中执行 VOLUME 语句后,later Dockerfile statements can't make any more changes in that specific directory。
考虑到您尝试更改的是非常特定于安装的设置(管理员密码、数据库设置),我不会尝试使用这些来构建映像。相反,我会使用 docker run -v
选项在运行时注入配置文件。