在 docker-compose build 或 docker-compose up 过程中创建文件/文件夹

25

我正在尝试进入 Docker 的世界,所以我尝试创建一个 Dockerfile 来创建一个简单的 index.html 文件和一个 images 目录(请见下方代码)

然后我运行 docker-compose build 来创建镜像,再运行 docker-compose up 来启动服务器。但是我没有得到 index.html 文件或 images 目录。

这是我的 Dockerfile:

FROM php:apache
MAINTAINER me@example.com

WORKDIR /var/www/html

RUN touch index.html \
    && mkdir images

这是我的 docker-compose.yml 文件

version: '2'
services:
  web:
    build: .docker/web
    ports:
      - "80:80"
    volumes:
      - ./docroot:/var/www/html

我期望这会创建一个带有图像目录和index.html的docroot文件夹,但我只得到了docroot。
1个回答

34

该镜像包含这些文件

Dockerfile 包含关于如何构建镜像的指令。你从该 Dockerfile 构建的镜像包含 index.htmlimages/

但是,在容器中,你覆盖了它们

在运行时,你从构建的镜像创建了一个容器。在该容器中,你将外部目录./docroot挂载为/var/www/html

挂载会隐藏之前路径上的任何内容,因此该挂载将隐藏/var/www/html中的先前内容,并用./docroot中的内容替换它们。

把东西放在你的挂载中

在评论中,你提出了问题

那么有可能先挂载然后再创建文件或其他东西吗?还是不可能?

按照你现在的方式做,你挂载了原始文件,所以一旦创建容器,它们就无法访问了。

处理这个问题的方法有几种。

更改它们在镜像中的路径

如果你将这些文件放在镜像的不同路径中,那么它们就不会被挂载覆盖。

WORKDIR /var/www/alternate-html

RUN touch index.html \
    && mkdir images

WORKDIR /var/www/html

现在,运行时您仍将在/var/www/html处拥有此挂载点,其中包含来自外部目录的内容。这个目录可能是空的或非空的。如果需要,您可以在容器启动时告诉它运行一个脚本并将东西复制到那里。

COPY entrypoint.sh /entrypoint.sh
RUN chmod 0755 /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

(假设您没有定义入口点 - 如果有,您可能只需要调整现有脚本即可。)

entrypoint.sh:

#!/bin/sh

cp -r /var/www/alternate-html/* /var/www/html
exec "$@"

这将运行cp命令,然后将控制权移交给此镜像的任何CMD.

外部处理

您还可以选择在外部预先填充想要放入./docroot中的文件。然后当容器启动并添加目录挂载时,它们将已经存在。


好的,谢谢,那个答案非常清晰 :D 但是有没有可能先挂载然后再创建文件或其他什么东西?还是不可能的? - Brentg
@Brentg 我更新了我的答案,并在那个问题上做了一些备注。 - Dan Lowe
哇,这些是一些非常好的评论,非常感谢你:D - Brentg
2
我仍在寻找如何让docker-compose为绑定卷在主机上创建文件夹的答案。 - DUzun

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