Docker:当Dockerfile位于子目录中时使用COPY

Cod*_*yAE 6 copy directory-structure docker dockerfile docker-compose

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

app
??? dockerfiles
?   ??? webserver
?   ?   ??? Dockerfile
?   ??? database
?       ??? Dockerfile
??? public
    ??? <frontend>
??? db
    ??? <data>
  [...]
??? LICENSE
??? README.md
??? docker-compose.yml
Run Code Online (Sandbox Code Playgroud)

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

# Dockerfile
COPY ./public /var/www/html
Run Code Online (Sandbox Code Playgroud)

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

# docker-compose.yml
version: "3"
services:
   webserver:
      build: ./dockerfiles/webserver
      image: webserver:php-apache
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

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

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

(1)使用一个Dockerfile用于整个应用程序(在应用程序的根目录中),或

app
??? Dockerfile
Run Code Online (Sandbox Code Playgroud)

(2)Dockerfiles为每个服务使用multiple (在应用程序的根目录中).

app
??? Dockerfile.webserver
??? Dockerfile.database
Run Code Online (Sandbox Code Playgroud)

这些解决方案很糟糕,因为对一切使用一个dockerfile /容器不是最佳实践(1),并且以这种方式组织多个dockerfiles看起来很混乱(2).


所以,我的问题是:

如何在不更改原始目录结构的情况下解决此问题?

  • 需要对dockerfiles,to docker-compose.yml或基本运行时命令进行哪些更改?
  • 是否有更好的方法来组织一切?
  • WORKDIR命令怎么样?

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

mar*_*ett 26

不完全是OP的场景,但如果你不使用docker-compose,你也可以分别指定上下文和Dockerfile:

docker build . -f app/dockerfiles/webserver/Dockerfile
Run Code Online (Sandbox Code Playgroud)

这使用当前目录.作为上下文进行构建,但使用Dockerfile子目录。


viv*_*d4v 11

你需要做的就是在docker-compose.yml文件中的build部分中添加context: .,dockerfile以便你的服务理解完整的目录结构.

# docker-compose.yml
version: "3"
services:
  webserver:
    build:
      context: .
      dockerfile: ./dockerfiles/webserver/Dockerfile
    image: webserver:php-apache
Run Code Online (Sandbox Code Playgroud)


Sal*_*lli 9

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

例如,在我的一个项目中,我有多个 compose 配置来支持多种环境(开发登台生产等),并且我决定将所有内容都放在自己的子目录中,以保持整洁。我的目录树如下:

.
+-- README.md
+-- scripts
|   +-- docker
|       +-- compose.yml
|       +-- compose-stage.yml
|       +-- compose-prod.yml
|       +-- dockerfile
|       +-- ...
|   +-- ...
Run Code Online (Sandbox Code Playgroud)

其中compose.yml如下:

# compose.yml
version: "3.9"
services:
  web:
    build:
      context: ../../
      dockerfile: ./scripts/docker/dockerfile
....
Run Code Online (Sandbox Code Playgroud)

请注意context,它指向应用程序的根目录(比compose.yml文件所在目录向上两级),而dockerfile,它相对于context.

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

> docker compose -f scripts/docker/compose.yml up
Run Code Online (Sandbox Code Playgroud)

一切都很有魅力!

我知道听起来有点复杂,可能确实如此,但是当需要处理将应用程序部署到三个(或更多!)不同环境时,所花费的时间将会得到回报。