Docker Volume Mistake

I have a simple application that I build with azure devops and push it to the nexus repository.
I’m running it with docker-compose.

There is a docker volume defined. But for example when I make an update to my app.py file. This update is not happening. The old application in the Docker volume is running.

When I delete the Docker volume and deploy the application again, my new update appears. But I don’t want docker volume to be deleted.

My docker-compose file

services:
  web:
    image: nexusrepo1.eastus.cloudapp.azure.com:8083/dockercomposetest:##TAGS##
    ports:
      - 32921:5000
    volumes:
      - omervolume:/code
  redis:
    image: redis:alpine
volumes:
  omervolume:

My dockerfile

# syntax=docker/dockerfile:1
FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["flask", "run"]

image

This is the expected behavior. When you use volumes you don’t want to change the data accidentally every time you update the image. Just think about that what would you say if something like this happened: you have an application image with a “uploads” folder. You don’t want to lose the uploaded files when you remove the container so you mount a volume to that path. Users upload hundreds of photos, then you update the image and the hundreds of photos are gone because the new image of course doesn§'t have any photos just an empty folder.

Volumes are for data like uploaded photos which you want to keep permanently even when the container is removed and you want to mount the same volume next time you create the container again. When you first start the container from an image data from the image will be copied to the volume that you mounted to that specific path, but only if that volume is empty.

If you change the image you usually change the code not uploaded photos. Yes, I know, sometimes you need to move data to a volume just for sharing between two containers. For example in case of HTTPD and PHP when you the application contains PHP files and static files (html, js, css) that cannot be separated and you don’t want PHP to load the static files too.

Here are what you can do.

  1. You can update the conent of the volume in your pipeline. When you deploy the image, you alos run some commands that removes the old data and copies the new from the host to the volume. All you need to use are docker exec and docker cp commands.

  2. You can replace the volume with a bind mount so you manage the data on the host, set proper permissions and mount it to the image. Then your pipeline has to build the image and update the data too on the host.

  3. You can also change the volume name every time when you deploy the new container, but it also means that if the size of the data that needs to be copied is big, it will take more time to copy it again to the empty volume.

  4. You can do something similar with bind mounts. You copy the data to ./docroot/revision-1, mount it to /var/www/html. Next time you copy the new data to ./docroot/revision-2 but mount it to the same folder in the container (/var/www/html`).

  5. and 4. requires to recreate the container since you mount a different volume or different host path. If you use Docker Compose it can happen quickly. Otherwise 1. or 2. is what I would recommend.

You are talking about code in a single container, so in your case it just shouldn’t be on a volume. Can you tell us why you put it on a volume?

Hello
First of all, thank you very much for your reply.
Yes, I’m aware that it’s normal for the /code directory not to be deleted or refreshed because I’ve mapped a volume.

Actually, what I’m trying to understand is this. My codes are under /code and when I distribute a new version, I want my documents to be permanent, not codes.

If there were pictures-documents-etc and I gave an example, if I had a directory called /data, I would actually have to back up omervolume:/data instead of omervolume:/code in docker-compose, right?

I want to test this, but how can I create a directory named /data in the dockerfile? I will define this directory on docker-compose volume.

It is entirely up to you where you mount your data as long as the application can be set to access it. Backup up a volume every time you update an image doesn’t make sense. If you need the data don’t change the volume. If you don’t need the data and you want to replace it, why would you create a backup? Do I misunderstand something?

What do you mean by “named /data”? You don’t need to create an empty folder which is the mount point of a volume. It is created automatically when you mount the volume or hostpath.

Actually I meant, How can I create a directory named /example in Dockerfile? First I’ll create it and then I’ll change the volumes: -omervolume:/code I wrote above in docker-compose to omervolume:/example, so I’ll be backing up only the files under /example. My source codes under the /code directory will be updated with each deployment. Is it true ?

OK, I got it done.
Actually, what I wanted to do was to back up a different directory, not /code directory. Because when the /code sequence was backed up and I made a change in the code, this was not reflected in the deployment.

I changed the dockerfile and docker-compose files as follows.
I added this line to the Dockerfile.

RUN mkdir -p /code/omerco
# syntax=docker/dockerfile:1
FROM python:3.7-alpine
RUN mkdir -p /code/omerco
WORKDIR /code
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["flask", "run"]
services:
  web:
    image: nexusrepo1.eastus.cloudapp.azure.com:8083/dockercomposetest:##TAGS##
    ports:
      - 32921:5000
    volumes:
      - omervolume:/code/omerco
  redis:
    image: redis:alpine
volumes:
  omervolume: