Docker Compose部署PostgreSQL时Entrypoint Shell脚本无法找到SQL文件的问题排查
咱们来拆解你遇到的两个核心问题,一步步帮你修复:
1. Docker Compose挂载脚本时找不到SQL文件的原因
当你只挂载create_tables.sh到容器的/docker-entrypoint-initdb.d/目录时,create_tables.sql并没有同步到容器内,脚本里的psql -U postgres -f create_tables.sql自然会报“找不到文件”——容器里这个路径下根本没有对应的SQL文件。
修复方案(Docker Compose方式)
只需要在docker-compose.yml的volumes里同时挂载SQL文件和Shell脚本,确保两者都在容器的初始化目录下:
version: '3.9' services: postgres: image: postgres:12.7 environment: - POSTGRES_USER=postgres - POSTGRES_PASSWORD=postgres logging: options: max-size: 10m max-file: "3" ports: - '5438:5432' volumes: - ./postgres-data:/var/lib/postgresql/data # 同时挂载SQL文件和Shell脚本到初始化目录 - ./sql/create_tables.sql:/docker-entrypoint-initdb.d/create_tables.sql - ./sql/create_tables.sh:/docker-entrypoint-initdb.d/create_tables.sh
容器启动时,/docker-entrypoint-initdb.d/下会同时存在脚本和SQL文件,脚本就能正常找到并执行SQL了。
2. Dockerfile中RUN脚本的错误
你的Dockerfile里用RUN ./docker-entrypoint-initdb.d/create_tables.sh是完全错误的——构建镜像阶段PostgreSQL服务并没有启动,此时执行psql命令必然失败,数据库都没运行呢!
PostgreSQL官方镜像的机制是:容器启动时会自动执行/docker-entrypoint-initdb.d/目录下的所有.sql、.sh、.sql.gz文件,不需要在构建镜像时手动RUN。
修复方案(Dockerfile方式)
修改Dockerfile,去掉RUN命令,只需要把文件复制到指定目录,同时给Shell脚本添加执行权限:
FROM postgres:12.7 # 把SQL和Shell脚本复制到初始化目录 ADD ./sql/create_tables.sql /docker-entrypoint-initdb.d/create_tables.sql ADD ./sql/create_tables.sh /docker-entrypoint-initdb.d/create_tables.sh # 给Shell脚本添加执行权限,否则容器启动时无法执行 RUN chmod +x /docker-entrypoint-initdb.d/create_tables.sh
然后在docker-compose.yml里使用自己构建的镜像,替换官方镜像:
version: '3.9' services: postgres: build: . # 构建当前目录下的Dockerfile #restart: always environment: - POSTGRES_USER=postgres - POSTGRES_PASSWORD=postgres logging: options: max-size: 10m max-file: "3" ports: - '5438:5432' volumes: - ./postgres-data:/var/lib/postgresql/data
容器启动时,会自动按顺序执行/docker-entrypoint-initdb.d/里的脚本,此时数据库已经正常启动,不会再报错。
另外建议:把Shell脚本里的SQL路径改成绝对路径,比如psql -U postgres -f /docker-entrypoint-initdb.d/create_tables.sql,这样能彻底避免路径歧义问题。
内容的提问来源于stack exchange,提问作者racofernandez

