---
title: "docker compose restart Does Not Reload Code in Built Images"
aliases: [docker-restart-stale-code, docker-compose-build-required, docker-restart-vs-build]
tags: [docker, docker-compose, python, deployment, gotcha]
sources:
  - "daily/2026-05-01.md"
created: 2026-05-01
updated: 2026-05-01
---

# `docker compose restart` Does Not Reload Code in Built Images

When a Docker Compose service uses `build:` context (image is baked from source at build time), `docker compose restart <service>` restarts the existing container from the cached image — it does **not** rebuild. Any Python code changes since the last `docker compose build` are completely invisible to the running container.

## Key Points

- `docker compose restart` only recycles the container process; the image layer is unchanged
- After any `.py` file change, the full sequence is: `docker compose build <service> && docker compose up -d <service>`
- Common symptom: bug fix applied and restart done, but the bug persists — the stale image is still running
- Service name precision matters: `docker compose restart backend` fails silently if the actual service is named `api`
- `docker compose logs <service>` will still show the old code running with no error
- Hot-reload (Uvicorn `--reload`) only works if the source directory is **volume-mounted** into the container, not just baked in

## Details

### The Wrong Pattern

```bash
# ❌ Code change deployed, restart done — but stale image still runs
vim app/routes/users.py
docker compose restart api
# Bug still present. No error. Container appears healthy.
```

### The Correct Pattern

```bash
# ✅ Rebuild the image, then recreate the container
docker compose build api && docker compose up -d api
```

### Diagnosing Stale Image

To confirm whether the running container has the latest code:

```bash
# Check when the image was last built
docker images | grep <project_name>

# Exec into the container and inspect the file directly
docker compose exec api cat /app/routes/users.py
```

### Volume-Mount Alternative (Dev Only)

For development, mount the source directory so Uvicorn's `--reload` works without rebuilding:

```yaml
services:
  api:
    build: .
    command: uvicorn app.main:app --reload --host 0.0.0.0
    volumes:
      - ./app:/app/app   # live mount; changes are visible immediately
```

> [!warning] Not for Production
> Volume mounts bypass the baked image in production — secrets and build artifacts may differ between environments.

### Service Name Gotcha

```bash
# ❌ Silently does nothing if the service is named "api" not "backend"
docker compose restart backend

# ✅ Verify service names first
docker compose ps
docker compose restart api
```

## Related Concepts

- [[wiki/tech-patterns/fastapi-python-docker]] — FastAPI + Docker Compose deployment pattern this applies to
- [[wiki/architecture/optical-dev-server-deploy]] — optical-dev deploy workflow where build-before-up is the standard
- [[wiki/concepts/python-service-deployment-dotenv]] — full Python service deploy checklist (includes rebuild step)

## Sources

- [[daily/2026-05-01.md]] — Sessions 12:09 and 19:07: code fix applied, `docker compose restart` run, bug persisted; root cause traced to stale baked image
