Home > Blockchain >  Trouble accessing file in a docker volume
Trouble accessing file in a docker volume

Time:01-17

I have a simple flask project that is running fine with docker, but one step of the build is confusing me. Initially I had trouble getting pip to install the requirements.txt file. It would fail indicating that the requirements file couldn't be found, #0 2.664 ERROR: Could not open requirements file: [Errno 2] No such file or directory: 'requirements.txt'. I accidentally got it to run by adding a line in the flask Dockerfile to copy the requirements.txt file to the flask container's /app directory, but I'm confused about what it's actually doing because the file seems to already be in that directory. I also don't have to copy over any other files and it runs fine.

I looked through docker's best practices documentation for the COPY command and saw this. COPY only supports the basic copying of local files into the container.... So COPY isn't just the same as the linux cp command to copy contents within a container, it's from local into a container? Does this mean that commands in a Dockerfile don't actually have access to bind mounted volume data during the build unless it's copied over from the local side? If this is the case then I believe that solves my issue! Project structure below for reference of what lead to the issue.

This is the general structure of the project

project_root /
    flask_app /
        ...
        Dockerfile
        requirements.txt
    database /
    nginx /
        ...
        Dockerfile
    docker-compose.yml

Here are the contents of docker-compose.yml located in the root directory of the project.

services:
  nginx:
    ...
  flask-app:
    build: flask_app
    volumes:
      - ./flask_app:/app
      - ./database:/database
    command: sh -c "gunicorn -w 4 -b 0.0.0.0:8001 'server:create_app()'"
    # tty: true # used for testing to ssh into container

Here's the flask_app/Dockerfile contents

FROM python:3.11.1-alpine3.17

COPY requirements.txt /app/ <-- Removing this causes the "no such file" error

WORKDIR /app

RUN pip install -r requirements.txt
# also tried as /app/requirements.txt and it fails without the copy command

What exactly is the copy doing that enables the requirements file to be found? I don't have to copy over any of the other flask related files to the container's /app directory and it still runs. There is no requirements.txt file in the project root either.

The requirements file seems to be present in the container's /app directory even without the copy command. I checked by first commenting out the flask Dockerfile contents to be...

FROM python:3.11.1-alpine3.17

#COPY requirements.txt /app/
#
#WORKDIR /app
#
#RUN pip install -r requirements.txt

And then in the docker-compose.yml file I swap the commented out tty line with the gunicorn command line above it. Then I can ssh into the flask container and see everything there, including the requirements.txt file in the /app directory. I've verified this with a clean build by removing all the images using docker rmi $(docker images -a -q) then building w/out cache using docker-compose build --no-cache and then run it.

Thanks

CodePudding user response:

So COPY isn't just the same as the linux cp command to copy contents within a container, it's from local into a container? Does this mean that commands in a Dockerfile don't actually have access to bind mounted volume data during the build unless it's copied over from the local side?

This is correct, because those are 2 different steps. I think what you are confused about is the general workflow of Docker. There are essentially 2 steps that docker executes to start your application:

1. Building the Docker Image

This uses the Dockerfile to build an docker image. You can imagine a docker image for our purposes as a tar/zip of all the files you specify with your instructions inside the Dockerfile. The cool thing about Dockerfiles is, that you don't need to specify all the files. You can just run commands and Docker will automatically detect all the files installed by pip. The docker image should represent your finished product. Everything your application needs to run should be inside the docker image.

2. Running the Docker Container

Running a docker container actually first creates the container from the docker image and then does all the things specified in the docker-compose.yml, such as doing port binding, mounting volumes, etc. For convenience the docker-compose.yml actually includes the `build` instruction which triggers a new docker image build every time the container is started.

If your setup is a development setup binding the source code as a volume is fine, but as I said earlier, if you want to deploy your code everything should be inside the docker image.

Now to answer your question on why it doesn't work: The RUN pip install step is run while building your Docker image. At this point in time docker doesn't know about any bind mounts or volumes yet, so naturally nothing is in the app directory. After you started your container the files are there, because you are specifying the bind mount in your docker-compose.yml.

  • Related