Why doesn't my alembic sync to my docker database but it works in production?
14:25 20 Mar 2026

I have an Alembic and SQLAlchemy defined database that's working just fine updating my database when I run

alembic -c traveler/db/alembic.ini upgrade head

Everything gets updated to the new models.

I'm trying to run this in a development environment now and creating a Postgres DB in a Docker container and syncing the SQL model with Alembic. The database starts up but when I connect to it there are no tables in the database.

 services:
  postgres:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: traveler
      POSTGRES_USER: traveler
      POSTGRES_PASSWORD: traveler
    ports:
      - "5432:5432"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U traveler -d traveler"]
      interval: 5s
      timeout: 5s
      retries: 10
    volumes:
      - postgres_data:/var/lib/postgresql/data

  migrate:
    image: python:3.11-slim
    working_dir: /app
    depends_on:
      postgres:
        condition: service_healthy
    environment:
      TRAVELER_DB_HOST: postgresql+psycopg://traveler:traveler@postgres:5432/traveler
    volumes:
      - ./:/app
    command: >
      bash -lc "
      pip install --no-cache-dir -e . &&
      alembic -c traveler/db/alembic.ini upgrade head
      "
    restart: "no"

volumes:
  postgres_data:

Here's the output

$ docker compose up
Attaching to migrate-1, postgres-1
postgres-1  | 
postgres-1  | PostgreSQL Database directory appears to contain a database; Skipping initialization
postgres-1  | 
postgres-1  | 2026-03-20 19:16:20.109 UTC [1] LOG:  starting PostgreSQL 15.17 on x86_64-pc-linux-musl, compiled by gcc (Alpine 15.2.0) 15.2.0, 64-bit
postgres-1  | 2026-03-20 19:16:20.109 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
postgres-1  | 2026-03-20 19:16:20.109 UTC [1] LOG:  listening on IPv6 address "::", port 5432
postgres-1  | 2026-03-20 19:16:20.111 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
postgres-1  | 2026-03-20 19:16:20.117 UTC [29] LOG:  database system was shut down at 2026-03-20 19:16:07 UTC
postgres-1  | 2026-03-20 19:16:20.125 UTC [1] LOG:  database system is ready to accept connections
migrate-1   | Obtaining file:///app
migrate-1   |   Installing build dependencies: started
migrate-1   |   Installing build dependencies: finished with status 'done'
migrate-1   |   Checking if build backend supports build_editable: started
migrate-1   |   Checking if build backend supports build_editable: finished with status 'done'
migrate-1   |   Getting requirements to build editable: started
migrate-1   |   Getting requirements to build editable: finished with status 'done'
migrate-1   |   Preparing editable metadata (pyproject.toml): started
migrate-1   |   Preparing editable metadata (pyproject.toml): finished with status 'done'
migrate-1   | Requirement already satisfied: sqlmodel>=0.0.21 in /usr/local/lib/python3.11/site-packages (from traveler==0.1.0) (0.0.37)
migrate-1   | Requirement already satisfied: alembic>=1.13 in /usr/local/lib/python3.11/site-packages (from traveler==0.1.0) (1.18.4)
migrate-1   | Requirement already satisfied: boto3>=1.40.50 in /usr/local/lib/python3.11/site-packages (from traveler==0.1.0) (1.42.72)
migrate-1   | Requirement already satisfied: psycopg>=3.2.10 in /usr/local/lib/python3.11/site-packages (from psycopg[binary]>=3.2.10->traveler==0.1.0) (3.3.3)
migrate-1   | Requirement already satisfied: SQLAlchemy>=1.4.23 in /usr/local/lib/python3.11/site-packages (from alembic>=1.13->traveler==0.1.0) (2.0.48)
migrate-1   | Requirement already satisfied: Mako in /usr/local/lib/python3.11/site-packages (from alembic>=1.13->traveler==0.1.0) (1.3.10)
migrate-1   | Requirement already satisfied: typing-extensions>=4.12 in /usr/local/lib/python3.11/site-packages (from alembic>=1.13->traveler==0.1.0) (4.15.0)
migrate-1   | Requirement already satisfied: botocore<1.43.0,>=1.42.72 in /usr/local/lib/python3.11/site-packages (from boto3>=1.40.50->traveler==0.1.0) (1.42.72)
migrate-1   | Requirement already satisfied: jmespath<2.0.0,>=0.7.1 in /usr/local/lib/python3.11/site-packages (from boto3>=1.40.50->traveler==0.1.0) (1.1.0)
migrate-1   | Requirement already satisfied: s3transfer<0.17.0,>=0.16.0 in /usr/local/lib/python3.11/site-packages (from boto3>=1.40.50->traveler==0.1.0) (0.16.0)
migrate-1   | Requirement already satisfied: psycopg-binary==3.3.3 in /usr/local/lib/python3.11/site-packages (from psycopg[binary]>=3.2.10->traveler==0.1.0) (3.3.3)
migrate-1   | Requirement already satisfied: pydantic>=2.11.0 in /usr/local/lib/python3.11/site-packages (from sqlmodel>=0.0.21->traveler==0.1.0) (2.12.5)
migrate-1   | Requirement already satisfied: python-dateutil<3.0.0,>=2.1 in /usr/local/lib/python3.11/site-packages (from botocore<1.43.0,>=1.42.72->boto3>=1.40.50->traveler==0.1.0) (2.9.0.post0)
migrate-1   | Requirement already satisfied: urllib3!=2.2.0,<3,>=1.25.4 in /usr/local/lib/python3.11/site-packages (from botocore<1.43.0,>=1.42.72->boto3>=1.40.50->traveler==0.1.0) (2.6.3)
migrate-1   | Requirement already satisfied: annotated-types>=0.6.0 in /usr/local/lib/python3.11/site-packages (from pydantic>=2.11.0->sqlmodel>=0.0.21->traveler==0.1.0) (0.7.0)
migrate-1   | Requirement already satisfied: pydantic-core==2.41.5 in /usr/local/lib/python3.11/site-packages (from pydantic>=2.11.0->sqlmodel>=0.0.21->traveler==0.1.0) (2.41.5)
migrate-1   | Requirement already satisfied: typing-inspection>=0.4.2 in /usr/local/lib/python3.11/site-packages (from pydantic>=2.11.0->sqlmodel>=0.0.21->traveler==0.1.0) (0.4.2)
migrate-1   | Requirement already satisfied: greenlet>=1 in /usr/local/lib/python3.11/site-packages (from SQLAlchemy>=1.4.23->alembic>=1.13->traveler==0.1.0) (3.3.2)
migrate-1   | Requirement already satisfied: MarkupSafe>=0.9.2 in /usr/local/lib/python3.11/site-packages (from Mako->alembic>=1.13->traveler==0.1.0) (3.0.3)
migrate-1   | Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.11/site-packages (from python-dateutil<3.0.0,>=2.1->botocore<1.43.0,>=1.42.72->boto3>=1.40.50->traveler==0.1.0) (1.17.0)
migrate-1   | Building wheels for collected packages: traveler
migrate-1   |   Building editable for traveler (pyproject.toml): started
migrate-1   |   Building editable for traveler (pyproject.toml): finished with status 'done'
migrate-1   |   Created wheel for traveler: filename=traveler-0.1.0-0.editable-py3-none-any.whl size=4369 sha256=038bc67e548d76e34a7ed7b6cf40ccc6c3ac482dea46c86d3d717612609f8923
migrate-1   |   Stored in directory: /tmp/pip-ephem-wheel-cache-w4ryh0u8/wheels/57/0f/98/bb57b2b57b95807699b822a35c022f139d38a02c27922f27ce
migrate-1   | Successfully built traveler
migrate-1   | Installing collected packages: traveler
migrate-1   |   Attempting uninstall: traveler
migrate-1   |     Found existing installation: traveler 0.1.0
migrate-1   |     Uninstalling traveler-0.1.0:
migrate-1   |       Successfully uninstalled traveler-0.1.0
migrate-1   | Successfully installed traveler-0.1.0
migrate-1   | WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
migrate-1   | 
migrate-1   | [notice] A new release of pip is available: 24.0 -> 26.0.1
migrate-1   | [notice] To update, run: pip install --upgrade pip
migrate-1   | INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
migrate-1   | INFO  [alembic.runtime.migration] Will assume transactional DDL.
migrate-1 exited with code 0
postgres-1  | 2026-03-20 19:21:20.185 UTC [27] LOG:  checkpoint starting: time
postgres-1  | 2026-03-20 19:21:20.203 UTC [27] LOG:  checkpoint complete: wrote 3 buffers (0.0%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.003 s, sync=0.002 s, total=0.019 s; sync files=2, longest=0.001 s, average=0.001 s; distance=0 kB, estimate=0 kB


w Enable Watch

Anyone know what's going on?

docker docker-compose sqlalchemy alembic