Postgres Docker容器无法通过自定义Shell脚本启动问题排查
问题分析
你指定的command替换了Postgres官方镜像的默认启动命令,导致容器没有启动Postgres服务,所以脚本里的pg_isready无法连接,且脚本执行完成后容器会直接退出(没有长期运行的前台进程)。
Postgres官方镜像的默认逻辑是:ENTRYPOINT为docker-entrypoint.sh(负责初始化数据库、环境变量处理等),CMD为postgres(启动数据库服务)。正常启动时,entrypoint脚本会执行初始化,然后启动postgres服务并保持前台运行。你现在的command直接执行自定义脚本,完全绕过了这个流程,所以数据库根本没启动。
解决方案
根据你的需求(容器启动后执行脚本),分两种场景处理:
场景1:脚本仅在第一次数据库初始化时执行
如果脚本是用于初始化数据库(比如创建表、导入初始数据),无需自定义command,直接利用官方镜像的自动初始化机制:
- 确保你的脚本放在
{{ docker_compose_dir }}/postgres/initdb目录下(你已经挂载了这个目录到/docker-entrypoint-initdb.d) - 脚本文件名以
.sh、.sql或.sql.gz结尾,官方entrypoint脚本会在第一次创建数据库时自动执行这些脚本 - 移除
docker-compose中的command配置,让容器按默认逻辑启动
场景2:脚本每次容器启动都要执行
如果需要每次启动容器都执行脚本,需要修改自定义脚本,让它先启动Postgres服务,再执行任务,同时保持服务在前台运行:
步骤1:修改自定义脚本custom_entrypoint.sh
#!/bin/bash set -e # 启动Postgres后台进程 postgres & PG_PID=$! # 等待Postgres服务就绪(用localhost,容器内部直接访问) until pg_isready -h localhost -p 5432 -U "$POSTGRES_USER" do echo "Waiting for postgres" sleep 10; done # 执行你的自定义任务 echo "do something ...." # 等待Postgres进程结束,保持容器运行 wait $PG_PID
步骤2:修正docker-compose配置
保留command配置,但建议修正数据目录的拼写错误(postgressql多了一个s,应为postgresql):
services: postgres: image: postgres:latest container_name: postgres volumes: - "{{ docker_dir }}/postgresql/data:/var/lib/postgresql/data" # 修正拼写错误 - "{{ docker_compose_dir }}/postgres/initdb:/docker-entrypoint-initdb.d" environment: POSTGRES_DB : '{{ container_variables.postgres.db }}' POSTGRES_USER : '{{ container_variables.postgres.db_user }}' POSTGRES_PASSWORD : '{{ container_variables.postgres.db_password }}' networks: - backend restart: unless-stopped command: ["sh","-c","chmod +x /docker-entrypoint-initdb.d/custom_entrypoint.sh && /docker-entrypoint-initdb.d/custom_entrypoint.sh"]
额外说明
- 脚本中用
localhost而不是容器名postgres,因为在容器内部直接访问本地服务更可靠,无需依赖DNS解析 wait $PG_PID会让脚本等待Postgres进程结束,确保容器不会因为脚本执行完成而退出- 如果你的自定义脚本需要修改数据库内容,确保使用正确的数据库用户(
$POSTGRES_USER)和密码,或者通过环境变量传递认证信息
内容的提问来源于stack exchange,提问作者Lukas Müller
相关产品推荐
相关产品推荐

