Reputation: 68
I want to build a multi container docker app with docker compose. My project structure looks like this:
docker-compose.yml
...
webapp/
...
Dockerfile
api/
...
Dockerfile
Currently, I am just trying to build and run the webapp
via docker compose up
with the correct build context. When building the webapp
container directly via docker build
, everything runs smoothly.
However, with my current specifications in the docker-compose.yml
the line COPY . /webapp/
in webapp/Dockerfile
(see below) copies the whole parent project to the container, i.e. the directory which contains the docker-compose.yml
, and not just the webapp/
sub directory.
For some reason the line COPY requirements.txt /webapp/
works as expected.
What is the correct way of specifying the build context in docker compose
? Why is the .
in the Dockerfile interpretet as relative to the docker-compose.yml
, while the requirements.txt
is relative to the Dockerfile
as expected? What am I missing?
Here are the contents of the docker-compose.yml
:
version: "3.8"
services:
frontend:
container_name: "pc-frontend"
volumes:
- .:/webapp
env_file:
- ./webapp/.env
build:
context: ./webapp
ports:
- 5000:5000
and webapp/Dockerfile
:
FROM python:3.9-slim
# set environment variables
ENV PYTHONWRITEBYTECODE 1
ENV PYTHONBUFFERED 1
# set working directory
WORKDIR /webapp
# copy dependencies
COPY requirements.txt /webapp/
# install dependencies
RUN pip install -r requirements.txt
# copy project
COPY . /webapp/ # does not work as intended
# add entrypoint to app
# ENTRYPOINT ["start-gunicorn.sh"]
CMD [ "ls", "-la" ] # for debugging
# expose port
EXPOSE 5000
Upvotes: 0
Views: 251
Reputation: 159722
The COPY
directive is (probably) working the way you expect. But, you have volumes:
that are overwriting the image content with something else. Delete the volumes:
block.
The image build sequence is working exactly the way you expect. build: { context: ./webapp }
uses the webapp
subdirectory as the build context and sends it to the Docker daemon. When the Dockerfile for example COPY requirements.txt .
it comes out of this directory. If you, for example, docker-compose run frontend pip freeze
, you should see the installed Python packages.
After the image is built, Compose starts a container, and at that point volumes:
take effect. When you say volumes: ['.:/webapp']
, here the .
before the colon refers to the directory containing the docker-compose.yml
file (and not the webapp
subdirectory), and then it hides everything in the /webapp
directory in the container. So you're replacing the image's /webapp
(which had been built from the webapp
subdirectory) with the current directory on the host (one directory higher).
You should usually be able to successfully combine an ordinary host-based development environment and a Docker deployment setup. Use a non-Docker Python virtual environment to build the application and run its unit tests, then use docker-compose up --build
to run integration tests and the complete application. With a setup like this, you don't need to deal with the inconveniences of the Python runtime being "somewhere else" as you're developing, and you can safely remove the volumes:
block.
Upvotes: 1