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

Docker构建阶段如何定义IP/主机名?解决数据库连接失败

容器构建时数据库连接失败的解决方案

背景

我有一个通过BIN文件和.properties配置文件安装的应用,配置文件包含数据库位置(主机名/IP)、应用访问URL等配置,安装命令为:

bash ./app.bin -s conf.properties

安装过程中,BIN文件会连接指定数据库创建库和用户,但此步骤失败,报错信息:

Create database: failure unable to create database, reason: Connection to 127.0.0.1:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections. org.postgresql.util.PSQLException: Connection to 127.0.0.1:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.

目标

实现无需传入变量/环境变量即可运行容器,同时支持自定义主机名等环境变量。

问题

构建阶段(docker build)中主机名或IP似乎不存在,导致数据库连接错误。如何解决?是否需要将BIN文件安装放到运行阶段(docker run)?这可行吗?

当前Dockerfile

FROM redhat/ubi9:9.0.0 AS RHEL9
LABEL name="Desinger"
RUN mkdir -p /usr/local/designer 

# Update system packages
RUN yum -y update

#Install bzip2
RUN yum install bzip2 -y

#Install PostgreSQL
RUN dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm
RUN dnf install -y postgresql14-server
RUN systemctl enable postgresql-14

#Copy OO files
COPY files/installer-designer.bin /usr/local/designer
COPY files/designer.properties /usr/local/designer
RUN chmod +x /usr/local/designer/installer-designer.bin

#Copy other filers
COPY files/ls /usr/bin/ls
COPY files/sudo /usr/bin/sudo
COPY files/hostname /usr/bin/hostname
COPY files/nano /usr/bin/nano

#Environment variables 
ENV ADMIN=admin
ENV PASS=?Password_123

#Expose ports
EXPOSE 8445
EXPOSE 443
EXPOSE 5432 

# Replace placeholders in configuration file with environment variables
RUN sed -i 's/${ADMIN}/'"$ADMIN"'/' /usr/local/designer/designer.properties
RUN sed -i 's/${PASS}/'"$PASS"'/' /usr/local/designer/designer.properties

# Install Designer
RUN bash /usr/local/designer/installer-designer.bin -s /usr/local/designer/designer.properties

已尝试无效方案

  • echo $(head -1 /etc/hosts | cut -f1) $HOST_NAME >> /etc/hosts
  • 设置ENV HOSTNAME="foo"并执行RUN echo "foo" > /etc/hostname

解决方案

核心问题分析

Docker构建阶段(docker build)中,每个RUN命令都在独立临时容器中执行,PostgreSQL服务在构建阶段不会持续运行。你虽然安装并启用了postgresql-14,但systemctl enable仅设置开机自启,构建阶段并未启动服务,所以安装BIN文件时连接127.0.0.1:5432必然失败。

方案1:将安装步骤移至运行阶段(推荐)

把BIN文件的安装放到容器启动时执行,此时PostgreSQL服务已启动,能正常连接。具体修改如下:

  1. 移除Dockerfile中的RUN bash /usr/local/designer/installer-designer.bin ...命令
  2. 创建启动脚本startup.sh,内容如下:
#!/bin/bash

# 初始化并启动PostgreSQL
postgresql-14-setup initdb
systemctl start postgresql-14

# 等待PostgreSQL就绪(可选但建议)
until pg_isready -h 127.0.0.1 -p 5432; do
    echo "等待PostgreSQL启动..."
    sleep 2
done

# 仅首次启动时执行应用安装
if [ ! -d "/usr/local/designer/installed" ]; then
    bash /usr/local/designer/installer-designer.bin -s /usr/local/designer/designer.properties
    mkdir /usr/local/designer/installed
fi

# 启动应用服务(请替换为实际的应用启动命令)
systemctl start designer-service

# 保持容器运行
tail -f /dev/null
  1. 将启动脚本复制到容器并设置权限:
COPY files/startup.sh /usr/local/designer/
RUN chmod +x /usr/local/designer/startup.sh
  1. 将Dockerfile最后一行改为启动脚本:
CMD ["/usr/local/designer/startup.sh"]

方案2:多阶段构建(适用于安装无需运行时依赖的场景)

如果应用安装仅需数据库连接完成初始化,后续运行不需要容器内的PostgreSQL,可采用多阶段构建:

  1. 第一阶段:安装PostgreSQL并启动,执行BIN安装,导出已安装的应用文件
  2. 第二阶段:从基础镜像复制导出的应用文件,配置启动命令

此方案需确认应用安装后可脱离构建阶段环境运行,灵活性不如方案1。

自定义环境变量支持

在启动脚本中,可根据环境变量动态修改designer.properties,示例:

# 在startup.sh中添加以下内容
if [ ! -z "$DB_HOST" ]; then
    sed -i 's/db.host=.*/db.host='"$DB_HOST"'/' /usr/local/designer/designer.properties
fi

运行容器时可通过-e DB_HOST=xxx自定义数据库地址,默认仍使用127.0.0.1。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 11:57:31