簡體   English   中英

Docker:當 Dockerfile 位於子目錄中時使用 COPY

[英]Docker: Using COPY when the Dockerfile is located in a subdirectory

我正在使用多個 dockerfile (每個服務一個)構建一個應用程序。 我的應用程序的目錄結構如下:

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

這些解決方案很糟糕,因為對所有內容都使用一個 dockerfile/container 並不是最佳實踐(1),並且以這種方式組織多個 dockerfile 看起來很混亂 (2)。


所以,我的問題是:

我們如何在不改變我們原來的目錄結構的情況下解決這個問題?

  • 需要對 dockerfiles、docker docker-compose.yml或基本運行時命令進行哪些更改?
  • 有沒有更好的方法來組織一切?
  • WORKDIR命令呢?

理想情況下,最好的解決方案應該適用於開發(本地)和生產(遠程)環境,所以現在讓我們避免卷......

您需要在這里做的就是添加context: . dockerfile在您的 docker-compose.yml 文件中的構建部分,以便您的服務了解完整的目錄結構。

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

正如在其他地方已經闡明的那樣, contextdockerfile的組合可以解決問題。 我只想補充一點,您甚至不需要在應用程序的根目錄中找到docker-compose.yml文件本身即可工作。

例如,在我的一個項目中,我有多個 compose 配置來支持多個環境( developmentstagingproduction等),我決定將所有內容放在它們自己的子目錄中,以保持整潔。 我的目錄樹如下:

.
+-- 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

一切都像魅力一樣!

我知道這聽起來有點令人費解,而且可能確實如此,但是當涉及將應用程序部署到三個(或更多!)不同的環境時,所花費的時間將得到回報。

COPY指令的作用域是 Dockerfile 所在的文件夾。 我的建議是將您的 Dockerfile 更改為 public 文件夾並將指令更改為COPY . /var/www/html COPY . /var/www/html

不完全是 OP 的場景,但如果您不使用docker-compose ,您還可以分別指定 context 和 Dockerfile :

docker build . -f app/dockerfiles/webserver/Dockerfile

這與當前目錄一起構建. 作為上下文,但使用子目錄中的Dockerfile

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM