I'm building an app using multiple dockerfiles (one for each service). My app's directory structure is as follows:
app
├── dockerfiles
│ ├── webserver
│ │ └── Dockerfile
│ └── database
│ └── Dockerfile
├── public
└── <frontend>
├── db
└── <data>
[...]
├── LICENSE
├── README.md
└── docker-compose.yml
In my webserver's Dockerfile
, I want to copy in my existing code using the COPY
command:
# Dockerfile
COPY ./public /var/www/html
And I want to deploy the app using my docker-compose.yml
file:
# docker-compose.yml
version: "3"
services:
webserver:
build: ./dockerfiles/webserver
image: webserver:php-apache
However, when I run docker-compose
from the working directory (app
), I get the following error:
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
This error disappears if I move my webserver's Dockerfile
to the app's root, so I know that it's being caused by a paths or build context issue.
And knowing this, we can fix the problem one of two ways, by either:
(1) Using one Dockerfile
for the entire app (in the app's root), or
app
└── Dockerfile
(2) Using multiple Dockerfiles
for each service (in the app's root).
app
├── Dockerfile.webserver
└── Dockerfile.database
These solutions are bad because using one dockerfile/container for everything is not best practice (1), and having multiple dockerfiles organized in this way just looks messy (2).
So, My Question is:
How do we fix this problem without changing our original directory structure?
- What changes need to be made to the dockerfiles, to
docker-compose.yml
, or to the basic runtime commands? - Is there a better way to organize everything?
- What about the
WORKDIR
command?
Ideally, the best solution should work for both dev (local) and production (remote) environments, so let's avoid volumes for now...
The scope for the
COPY
instruction is the folder where Dockerfile is. My suggestion is to change your Dockerfile to public folder and change the instruction toCOPY . /var/www/html
.All you need to do here is add
context: .
anddockerfile
in your build section inside your docker-compose.yml file so that your service understands the complete directory structure.