You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker部署Supabase时安装Apache AGE扩展失败求助

问题:Supabase PostgreSQL容器无法识别Apache AGE扩展

基于supabase/postgres:15.8.1.020构建了包含Apache AGE的自定义镜像,使用dbmate执行迁移添加AGE扩展时,报错extension 'age' is not available。但进入容器后能看到/usr/share/postgresql/15/extension/下存在AGE相关文件,尝试将age加入shared_preload_libraries也未解决。

相关配置文件

Dockerfile

FROM supabase/postgres:15.8.1.020 AS builder

# Add proxy configuration
RUN echo 'Acquire::http::Pipeline-Depth 0;' > /etc/apt/apt.conf.d/99fixbadproxy && \
    echo 'Acquire::http::No-Cache true;' >> /etc/apt/apt.conf.d/99fixbadproxy && \
    echo 'Acquire::BrokenProxy true;' >> /etc/apt/apt.conf.d/99fixbadproxy

# Add PostgreSQL repository
RUN apt-get update && apt-get install -y curl ca-certificates gnupg lsb-release
RUN curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor -o /usr/share/keyrings/postgresql-keyring.gpg
RUN echo "deb [signed-by=/usr/share/keyrings/postgresql-keyring.gpg] http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list

# Install build dependencies
RUN apt-get update 

RUN apt-get install -y --no-install-recommends --no-install-suggests \
    bison \
    build-essential \
    flex \
    git \
    postgresql-server-dev-15

# Clone and build Apache AGE
RUN git clone https://github.com/apache/age.git /age
WORKDIR /age
RUN git checkout release/PG15/1.5.0
RUN make install

# Final stage - clean image with just the extension files
FROM supabase/postgres:15.8.1.020

# Copy only the compiled extension files
COPY --from=0 /usr/lib/postgresql/15/lib/age.so /usr/lib/postgresql/15/lib/
COPY --from=0 /usr/share/postgresql/15/extension/age* /usr/share/postgresql/15/extension/

docker-compose.yml

db:
    container_name: supabase-db
    image: localhost:5000/supabase-with-age
    restart: unless-stopped
    volumes:
      - ./volumes/db/realtime.sql:/docker-entrypoint-initdb.d/migrations/99-realtime.sql:Z
      # Must be superuser to create event trigger
      - ./volumes/db/webhooks.sql:/docker-entrypoint-initdb.d/init-scripts/98-webhooks.sql:Z
      # Must be superuser to alter reserved role
      - ./volumes/db/roles.sql:/docker-entrypoint-initdb.d/init-scripts/99-roles.sql:Z
      # Initialize the database settings with JWT_SECRET and JWT_EXP
      - ./volumes/db/jwt.sql:/docker-entrypoint-initdb.d/init-scripts/99-jwt.sql:Z
      # PGDATA directory is persisted between restarts
      - ./volumes/db/data:/var/lib/postgresql/data:Z
      # Changes required for internal supabase data such as _analytics
      - ./volumes/db/_supabase.sql:/docker-entrypoint-initdb.d/migrations/97-_supabase.sql:Z
      # Changes required for Analytics support
      - ./volumes/db/logs.sql:/docker-entrypoint-initdb.d/migrations/99-logs.sql:Z
      # Changes required for Pooler support
      - ./volumes/db/pooler.sql:/docker-entrypoint-initdb.d/migrations/99-pooler.sql:Z
      # Use named volume to persist pgsodium decryption key between restarts
      - db-config:/etc/postgresql-custom
    healthcheck:
      test:
        [
        "CMD",
        "pg_isready",
        "-U",
        "postgres",
        "-h",
        "localhost"
        ]
      interval: 5s
      timeout: 5s
      retries: 10
    depends_on:
      vector:
        condition: service_healthy
    environment:
      POSTGRES_HOST: /var/run/postgresql
      PGPORT: ${POSTGRES_PORT}
      POSTGRES_PORT: ${POSTGRES_PORT}
      PGPASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      PGDATABASE: ${POSTGRES_DB}
      POSTGRES_DB: ${POSTGRES_DB}
      JWT_SECRET: ${JWT_SECRET}
      JWT_EXP: ${JWT_EXPIRY}
    command:
      [
        "postgres",
        "-c",
        "config_file=/etc/postgresql/postgresql.conf",
        "-c",
        "log_min_messages=fatal" # prevents Realtime polling queries from appearing in logs
      ]
  dbmate:
    image: amacneil/dbmate
    command: --wait up  # auto apply migrations
    restart: on-failure:3  # Limit restart attempts
    volumes:
      - ./db/migrations:/db/migrations:Z
    environment:
      DATABASE_URL: "postgres://postgres:postgres@db:5432/postgres?sslmode=disable"
      DBMATE_SCHEMA_MIGRATIONS_TABLE: "schema_migrations"  # Explicitly name tracking table
      DBMATE_NO_DUMP_SCHEMA: "true"  # Skip schema dumping for performance
    depends_on:
      db:
        condition: service_healthy  # Requires the healthcheck defined above
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

排查与解决办法

1. 确认PostgreSQL扩展搜索路径

Supabase的PostgreSQL可能自定义了extension_directory,导致默认路径下的AGE文件不被识别。进入容器执行SQL命令确认:

SHOW extension_directory;

如果输出不是/usr/share/postgresql/15/extension,需要在docker-compose的db服务command中添加指定路径的参数:

command:
  [
    "postgres",
    "-c", "config_file=/etc/postgresql/postgresql.conf",
    "-c", "log_min_messages=fatal",
    "-c", "extension_directory=/usr/share/postgresql/15/extension"
  ]

2. 修复AGE编译兼容性

Supabase的PostgreSQL镜像带有定制化补丁,直接用官方PG开发包编译的AGE可能存在兼容性问题。修改Dockerfile的依赖安装步骤,移除官方PG开发包,确保使用与镜像匹配的编译环境:

# 替换原PG开发包安装命令
RUN apt-get install -y --no-install-recommends --no-install-suggests \
    bison \
    build-essential \
    flex \
    git
# 无需安装postgresql-server-dev-15,直接使用Supabase镜像内置的PostgreSQL开发文件

3. 修正AGE文件权限

AGE的.so文件和扩展脚本需要PostgreSQL进程有权限读取。在Dockerfile中添加权限修正步骤:

COPY --from=0 /usr/lib/postgresql/15/lib/age.so /usr/lib/postgresql/15/lib/
COPY --from=0 /usr/share/postgresql/15/extension/age* /usr/share/postgresql/15/extension/
# 修正文件权限
RUN chown postgres:postgres /usr/lib/postgresql/15/lib/age.so \
    && chmod 644 /usr/lib/postgresql/15/lib/age.so \
    && chown -R postgres:postgres /usr/share/postgresql/15/extension/age* \
    && chmod -R 644 /usr/share/postgresql/15/extension/age*

4. 正确配置预加载库

确保age被正确加入shared_preload_libraries,并重启PostgreSQL生效。在docker-compose的db服务command中添加:

command:
  [
    "postgres",
    "-c", "config_file=/etc/postgresql/postgresql.conf",
    "-c", "log_min_messages=fatal",
    "-c", "shared_preload_libraries=age"
  ]

如果原本已有其他预加载库,用逗号分隔,例如shared_preload_libraries=pg_stat_statements,age。

5. 调整初始化顺序

dbmate的迁移可能在AGE完全加载前执行,可通过两种方式解决:

  • 将创建AGE扩展的语句放入Supabase初始化目录(/docker-entrypoint-initdb.d/)的脚本中,优先执行
  • 修改dbmate的command,增加等待时间:
command: sh -c "sleep 10 && dbmate --wait up"

6. 手动验证扩展可用性

进入容器,用psql连接数据库手动执行创建命令,查看详细错误信息:

CREATE EXTENSION age;

如果报错,错误信息会直接指向问题根源(如文件缺失、权限不足等)。

内容的提问来源于stack exchange,提问作者Niall

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 23:45:06