Search code examples
dockerdocker-composecopy

Files in docker container not updated with docker compose


I have setup for my django project using nginx and uwsgi, similar to what is described here

I am now trying to use docker / docker compose to maintain it.

For the container with the django application, everything seems to be working fine when I use docker build, but when I use docker compose, the files do not seem to be updated properly.

The Dockerfile is:

FROM python:3.10-alpine

# Install Imagemagick package
# gcc and more are required to build the uswgi wheel
RUN apk add imagemagick imagemagick-dev imagemagick-pdf gcc python3-dev build-base linux-headers pcre-dev curl

# set environment variables
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1

COPY requirements.txt /

RUN pip install -r requirements.txt

COPY django_app/ /app

COPY uwsgi.ini /

WORKDIR /app

RUN python ./manage.py migrate
RUN python ./manage.py collectstatic --noinput

docker-compoose.yml:

services:
  redis:
    image: redis:7-alpine

  celery_worker:
    build:
      context: .
      dockerfile: ./Dockerfile
    image: celery
    command: celery -A bg_upgrades worker -l info
    env_file:
      - ./docker_env
    depends_on:
      - redis

  uwsgi:
    build:
      context: .
      dockerfile: ./Dockerfile
    image: uwsgi
    env_file:
      - ./docker_env
    command: uwsgi --ini /uwsgi.ini
    volumes:
      - django_app:/app/
      - socket:/sock/
    depends_on:
      - redis

  nginx:
    build:
      context: ./nginx
      dockerfile: ./Dockerfile
    volumes:
      - django_app:/app/
      - socket:/sock/
    depends_on:
      - redis
      - uwsgi
      - celery_worker
    ports:
      - 80:80

volumes:
  django_app:
  socket:

Looking at other answers, here are a few things I've tried:

  • docker compose up -d --build --force-recreate
  • docker compose build --no-cache
  • Deleting all containers and images in the Docker UI
  • Changing the names of the images in the docker-compose.yml file
  • Adding a command RUN rm -Rf /app/* before the COPY in the Dockerfile
  • docker compose down before restarting

Specifically, the file I am changing (and I don't see the changes reflected int he container) is at django_app/my_app/template/pattern_form.html.j2

Again, when I use docker build -t my_app:0.1 ., the file is updated properly (no change to the Dockerfile).


Solution

  • This volume mount is causing the behavior:

    volumes:
      - django_app:/app/
    

    Whatever content is in the django_app named volume will be mounted on /app, hiding whatever was in your image. Nothing will ever update this volume's content, and it's an unusual behavior of Docker that anything is in this volume at all. (A similar setup using a host directory or a Kubernetes volume would yield an empty directory.)

    Never mount anything over your application code. Avoid relying on Docker's behavior of automatically copying content into volumes.


    The easiest way to fix this is to make sure you've configured Django's static-file service. If you have, remove any sort of static-file handling from Nginx. Its configuration should pretty much just have

    upstream django {
      server uwsgi:8001
    }
    
    server {
      # No /media or /static paths
      location / {
        uwsgi_pass django;
      }
    }
    

    Once you've done that then you can delete the volumes: blocks from all of the non-database containers and the corresponding entries in the top-level volumes:. Since you're not mounting a stale named volume over your application code, you'll see the updates when your image is rebuilt.