如何在Docker映像中写入文件?

时间:2019-02-26 09:20:31

标签: docker dockerfile docker-image

我已使用以下命令将文件复制到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 语句都会创建一个新层,并在该语句删除后将其删除(?)。

我很困惑。为什么用

安装软件
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

来自Docker Documentation

  

在Dockerfile中更改卷:如果有构建步骤   在声明后更改卷中的数据,那些   更改将被丢弃。

我完全错过了!感谢David指出我在此处:)因此,创建和编写文件确实可以按预期工作,但请注意VOLUME目录。 RUN语句在这里不起作用。 因此,要解决此问题,最佳做法是将文件挂载绑定到该卷中。

3 个答案:

答案 0 :(得分:2)

如果您查看the Dockerfile for that base image,它会部分说明

ENV JIRA_HOME /var/atlassian/application-data/jira
VOLUME ["${JIRA_HOME}"]

在Dockerfile later Dockerfile statements can't make any more changes in that specific directory中执行VOLUME语句后。

鉴于您要更改的种类是非常特定于安装的设置(管理员密码,数据库设置),因此我不会尝试从中构建映像。相反,我会使用docker run -v选项在运行时注入配置文件。

答案 1 :(得分:1)

每个response.Headers.GetValues("x-ms-ratelimit-remaining-subscription-writes").GetValue(0) 语句都不会创建中间容器,而是在联合文件系统上创建一个只读的新层。运行图像时,将为此容器创建一个特殊的可写层,并且您对该容器所做的所有更改都将写入该层。 (除了卷。这是一个不同的概念)。这就是为什么Docker能够在容器之间安全地共享同一图像(甚至是层),而又不会互相影响的原因。您可以检查docker documentation了解更多信息。

对于您的问题,除非您以某种方式删除或覆盖它们,否则应该在该映像的运行实例中看到对构建时间所做的每一次更改。

答案 2 :(得分:1)

请参阅此question

您正在运行的命令正确,并且应该创建文件。我怀疑是,当您运行容器时,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文件夹绑定。

感谢这个有趣的问题:)