I'm new into Docker. I have a problem with uploading file in Flask app that is contained in Docker and accessing it.
Let's say that I have a project in this structure:
/home
| /myProjects
| /myDockers
| | /myApp
| | | /controller
| | | ...
| | | wsgi.py
| | | .gitlab-ci.yml
| | | DockerFile
| | | gunicorn.sh
| /uploads
My Flask app is in /MyApp, while I want to upload file into /uploads. The app was deployed on Docker with these configurations:
.gitlab-ci.yml:
stages:
- build
- deploy
build-image:
stage: build
only:
refs:
- dev
script:
- cd /home/myProjects/myDocker/myApp/
- git checkout dev
- git pull origin dev
- docker container rm -f myApp
- docker image rm -f myApp
- docker build -t myApp -f 20021_DockerfileLmsGeneralRepositoryService .
deploy-container:
stage: deploy
only:
refs:
- dev
script:
- docker run -d --network host -e DATABASE_URL=$DATABASE_URL -e REDIS_HOST=$REDIS_HOST --name myApp myApp
DockerFile:
FROM python:3.8.7-slim-buster AS compile-image
RUN apt-get update && apt-get install -y --no-install-recommends build-essential gcc libpq-dev && apt-get install -y apt-utils
COPY ./requirements.txt .
RUN pip install --upgrade --user -r requirements.txt
RUN pip install injector
COPY . /code
FROM python:3.8.7-slim-buster AS build-image
COPY --from=compile-image /code/ /code
COPY --from=compile-image /root/.local /root/.local
# Make sure scripts in .local are usable:
ENV PATH=/root/.local/bin:$PATH
WORKDIR /code
RUN chmod a+x gunicorn.sh
ENTRYPOINT ["sh","./gunicorn.sh"]
gunicorn.sh:
#!/bin/sh
gunicorn wsgi:application -w 2 --threads 2 --preload -b 0.0.0.0:20021
I already create an API in my Flask app to upload file and succeed in local (Windows) PC, but then when I deploy it into the development server, the structure of folder is different from what I expected. When I checked the project structure using script, it returned:
"/code/controller"
Which is different from the structure of the project in the server, so I ask my senior and he said I should learn about Volume in Docker since the project is contained inside Docker container, but I never used Docker in the first place.
I also already tried to change the script in .gitlab-ci.yml into this (I tried this from this question) and yeah it doesn't work:
- docker run -d --network host -e DATABASE_URL=$DATABASE_URL -e REDIS_HOST=$REDIS_HOST --name myApp -v /home/myProjects/:/root/.local/code myApp
After our talk, I could see another and easier solution. parts of my other answer are still applying.
from your working folder structure, your app seems to try writing to ../../uploads
folder, 2 levels up in directory structure. thus we can create a folder structure in the container to suit this.
in Dockerfile
make these changes:
COPY --from=compile-image /code/ /code
to COPY --from=compile-image /code/ /code/app
WORKDIR /code
to WORKDIR /code/app
RUN mkdir /uploads
anywhere after FROM .. AS build-image
and but before ENTRYPOINT
we copy the app 2 level deep in the container and adding uploads folder into root.
now run change your run command into this:
docker run -d --network host -e DATABASE_URL=$DATABASE_URL -e REDIS_HOST=$REDIS_HOST --name myApp -v /home/myProjects/uploads:/uploads myApp
we bind-mount an uploads folder in the host into the uploads folder in the container. you can have the bind as -v path_to_your_uploads_folder_in_host:/uploads