如何保存Docker镜像变更?解决docker-compose down后Django配置丢失问题
Hey Andy, let's walk through why your Django changes are disappearing after docker-compose down and how to fix this—this is one of the most common pitfalls when getting started with Docker and Django!
Why Your Changes Are Vanishing
Docker containers are ephemeral by default. When you run commands like migrate or createsuperuser, those changes either live in the database (which is inside the db container) or modify the container's filesystem (like if you installed new dependencies). When you run docker-compose down, those containers are deleted, taking all their temporary data with them—unless you explicitly persist or save those changes.
Fix 1: Persist Database Data (Most Critical)
The migrate and createsuperuser commands modify your database, so we need to make sure that database data sticks around even when the db container is deleted. We'll use Docker volumes for this—they're designed to persist data independently of containers.
Update your docker-compose.yml to add a named volume for your database service (example uses PostgreSQL; adjust for MySQL/SQLite if needed):
version: '3.8' services: db: image: postgres:15 volumes: # Mount PostgreSQL's data directory to a named Docker volume - postgres_data:/var/lib/postgresql/data/ environment: - POSTGRES_DB=your_db_name - POSTGRES_USER=your_db_user - POSTGRES_PASSWORD=your_db_pass web: image: your-django-image:latest # Replace with your existing Django image command: python manage.py runserver 0.0.0.0:8000 ports: - "8000:8000" depends_on: - db # Define the named volume at the bottom—Docker handles storing it safely volumes: postgres_data:
Now when you run docker-compose down, the postgres_data volume won't be deleted. Next time you start with docker-compose up -d, the database will load all your previous migrations and the superuser you created.
Fix 2: Save Container Filesystem Changes (If You Modified Code/Dependencies)
If you ran commands inside the web container (like pip install or edited code files), those changes only exist in that specific container. To make them permanent, you have two options:
Option A: Commit the Container to a New Image
This is quick for one-off changes:
- List your containers to get the web container's ID:
docker ps -a - Commit the container to a new image (replace
<container-id>with your actual ID):docker commit <container-id> my-django-app:updated - Update your
docker-compose.ymlto use this new image instead of the original:web: image: my-django-app:updated # Keep other configs the same
Option B: Use a Dockerfile (Recommended for Long-Term)
For reproducible builds, it's better to codify your changes in a Dockerfile. This way, anyone can rebuild the exact same image without manual commits.
Create a Dockerfile in your project root:
# Start with your base Django image FROM python:3.11-slim WORKDIR /app # Copy your requirements file and install dependencies (add any new packages here) COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # Copy your entire Django project code into the image COPY . . # Optional: Automate migrate on startup (but skip createsuperuser unless you use env vars) # CMD ["bash", "-c", "python manage.py migrate && python manage.py runserver 0.0.0.0:8000"]
Then update your docker-compose.yml to build from this Dockerfile instead of using a pre-pulled image:
web: build: . # Tells Docker to use the Dockerfile in the current directory command: bash -c "python manage.py migrate && python manage.py runserver 0.0.0.0:8000" # Add environment vars if you want to auto-create a superuser (only runs once if the user doesn't exist) environment: - DJANGO_SUPERUSER_USERNAME=admin - DJANGO_SUPERUSER_EMAIL=admin@example.com - DJANGO_SUPERUSER_PASSWORD=your_secure_pass # Keep other configs the same
Now run docker-compose build to create the updated image, then docker-compose up -d to start with your persistent changes.
Final Quick Tips
- Never run
docker-compose down -vunless you want to delete all your volumes (including the database data!). - If you're using SQLite instead of a separate db service, you'll need to mount a volume for your
db.sqlite3file in the web service to persist it. - For production, avoid manual container commits—always use Dockerfiles for consistency.
内容的提问来源于stack exchange,提问作者Andy K




