Docker Entrypoint脚本trap函数内echo输出无法在docker-compose中显示
Docker-Compose中SIGINT陷阱函数输出无法实时显示的问题及解决方案
问题背景
使用docker-compose管理Postgres容器时,自定义Entrypoint脚本通过trap捕获SIGINT信号,执行数据库备份后再停止容器。实际测试中,备份操作正常执行,但shutdown函数中的echo输出无法在docker-compose up的附加模式下实时显示,仅能通过docker logs查看。
相关代码
自定义Entrypoint脚本
#!/bin/bash backup_dir="/backup" # Define a function to handle the SIGINT signal (graceful shutdown) echo "[+] Postgres customer_entrypoint ran." shutdown() { echo "[+] Backing up database before shutdown." pg_dumpall --on-conflict-do-nothing --column-inserts -U "$POSTGRES_USER" > "/backups/backup_$(date +%Y-%m-%d_%H-%M-%S).sql" pg_ctl -D "$PGDATA" -m fast -w stop } trap shutdown SIGINT /usr/local/bin/docker-entrypoint.sh postgres & wait $!
docker-compose配置
version: '3.3' services: postgres: container_name: postgres build: context: ./postgres dockerfile: Dockerfile-postgres.dev image: postgres-my:latest restart: always env_file: - ./.env.dev.db ports: - '127.0.0.1:5432:5432' volumes: - ./postgres/backups:/backups - postgres_data_dev:/var/lib/postgresql/data stop_signal: SIGINT volumes: postgres_data_dev:
执行命令
sudo docker-compose -f docker-compose.dev up --build
原因分析
- 输出缓冲问题:bash默认会对stdout进行缓冲,脚本处理信号时,缓冲的输出可能无法及时刷新到终端,直到进程退出后才写入日志。
- docker-compose输出流关闭时机:按下Ctrl+C后,docker-compose触发容器停止流程,可能提前关闭与容器的输出流连接,导致陷阱函数的输出无法传输到前端终端。
- 进程结构影响:脚本将官方postgres入口脚本放在后台运行,主进程处于
wait状态,信号处理过程中的输出转发机制受限。
解决方案
1. 将陷阱函数输出定向到stderr
docker-compose附加模式下,stderr通常无缓冲实时转发,修改shutdown函数的echo语句,将输出发送到stderr:
shutdown() { echo "[+] Backing up database before shutdown." >&2 pg_dumpall --on-conflict-do-nothing --column-inserts -U "$POSTGRES_USER" > "/backups/backup_$(date +%Y-%m-%d_%H-%M-%S).sql" pg_ctl -D "$PGDATA" -m fast -w stop }
2. 增加优雅停止超时时间
在docker-compose.yml中添加stop_grace_period,给陷阱函数足够的执行和输出时间,避免docker-compose提前关闭输出流:
services: postgres: # ... 原有配置 stop_signal: SIGINT stop_grace_period: 30s
3. 禁用脚本输出缓冲
在自定义Entrypoint脚本开头添加以下语句,强制关闭stdout和stderr的缓冲:
#!/bin/bash # 禁用输出缓冲 exec 1>&0 exec 2>&0 backup_dir="/backup" # ... 后续脚本内容
4. 调整后台进程的启动方式
使用stdbuf命令启动postgres入口脚本,强制其输出无缓冲:
# 替换原有的后台启动命令 stdbuf -i0 -o0 -e0 /usr/local/bin/docker-entrypoint.sh postgres &
验证效果
修改后重新执行docker-compose up --build,按下Ctrl+C后,即可在终端实时看到shutdown函数的输出信息,同时备份操作正常执行。
内容的提问来源于stack exchange,提问作者Dave
相关产品推荐
相关产品推荐

