【问题标题】:Docker: Using COPY when the Dockerfile is located in a subdirectoryDocker:当 Dockerfile 位于子目录中时使用 COPY
【发布时间】:2018-05-26 21:51:48
【问题描述】:

我正在使用multiple dockerfiles 构建一个应用程序(每个服务一个)。我的应用的目录结构如下:

app
├── dockerfiles
│   ├── webserver
│   │   └── Dockerfile
│   └── database
│       └── Dockerfile
├── public
    └── <frontend>
├── db
    └── <data>
  [...]
├── LICENSE
├── README.md
└── docker-compose.yml

在我的网络服务器的Dockerfile 中,我想使用COPY 命令复制我现有的代码:

# Dockerfile
COPY ./public /var/www/html

我想使用我的docker-compose.yml 文件部署应用程序:

# docker-compose.yml
version: "3"
services:
   webserver:
      build: ./dockerfiles/webserver
      image: webserver:php-apache

但是,当我从工作目录 (app) 运行 docker-compose 时,我收到以下错误:

Building webserver
Step 1/2 : FROM php:7.1.11-apache-jessie
 ---> cb6a5015ad72
Step 2/2 : COPY ./public /var/www/html
Service 'webserver' failed to build: COPY failed: stat /var/lib/docker/tmp/docker-builder193736188/public: no such file or directory

如果我将网络服务器的 Dockerfile 移动到应用程序的根目录,此错误就会消失,因此我知道它是由路径或构建上下文问题引起的。

知道了这一点,我们可以通过以下两种方法之一解决问题:

(1) 为整个应用(在应用的根目录中)使用一个Dockerfile,或者

app
└── Dockerfile

(2) 为每个服务使用多个Dockerfiles(在应用的根目录中)。

app
├── Dockerfile.webserver
└── Dockerfile.database

这些解决方案很糟糕,因为不是best practice (1) 对所有内容都使用一个 dockerfile/container,而且以这种方式组织多个 dockerfile 看起来很混乱 (2)。


所以,我的问题是:

我们如何在不改变我们原来的目录结构的情况下解决这个问题?

  • 需要对 dockerfiles、docker-compose.yml 或基本运行时命令进行哪些更改?
  • 有没有更好的方法来组织所有内容?
  • WORKDIR 命令呢?

理想情况下,最好的解决方案应该同时适用于开发(本地)和生产(远程)环境,所以让我们暂时避免卷...

【问题讨论】:

    标签: docker copy docker-compose dockerfile directory-structure


    【解决方案1】:

    正如在其他地方已经阐明的那样,contextdockerfile 的组合可以解决问题。我只想补充一点,您甚至不需要在应用程序的根目录中找到 docker-compose.yml 文件本身即可。

    例如,在我的一个项目中,我有多种组合配置来支持多种环境(开发暂存生产等。 ) 我决定把所有东西都放在他们自己的子目录中,以保持清洁。我的目录树如下:

    .
    +-- README.md
    +-- scripts
    |   +-- docker
    |       +-- compose.yml
    |       +-- compose-stage.yml
    |       +-- compose-prod.yml
    |       +-- dockerfile
    |       +-- ...
    |   +-- ...
    

    compose.yml 如下所示:

    # compose.yml
    version: "3.9"
    services:
      web:
        build:
          context: ../../
          dockerfile: ./scripts/docker/dockerfile
    ....
    

    注意context,它指向应用程序的根目录——在compose.yml文件所在目录的上两层——和dockerfile,它与context相关。

    有了上面的目录树和compose.yml文件,我们要做的就是从应用程序的根目录(即README.md所在的目录)运行以下命令:

    > docker compose -f scripts/docker/compose.yml up
    

    一切都像魅力一样!

    我知道这听起来有点令人费解,而且可能确实如此,但是当涉及将应用程序部署到三个(或更多!)不同的环境时,所花费的时间将得到回报。

    【讨论】:

    • 这正是我想做的。感谢分享!
    【解决方案2】:

    您只需在 docker-compose.yml 文件中的构建部分添加 context: .dockerfile,以便您的服务了解完整的目录结构。

    # docker-compose.yml
    version: "3"
    services:
      webserver:
        build:
          context: .
          dockerfile: ./dockerfiles/webserver/Dockerfile
        image: webserver:php-apache
    

    【讨论】:

    • 这很完美!我知道这一定是构建上下文的问题,但我在寻找解决方案时遇到了很多麻烦......希望这将在不久的将来帮助处于类似情况的人!
    【解决方案3】:

    COPY 指令的作用域是 Dockerfile 所在的文件夹。我的建议是将您的 Dockerfile 更改为公共文件夹并将指令更改为 COPY . /var/www/html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-02
      • 1970-01-01
      • 2015-01-08
      • 2018-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-10
      相关资源
      最近更新 更多