107 lines
3.4 KiB
Docker
107 lines
3.4 KiB
Docker
# ================================================
|
||
# Urban Lifeline - PostgreSQL 数据库镜像
|
||
# 支持初始化脚本和自定义配置
|
||
# ================================================
|
||
|
||
FROM postgres:16-alpine
|
||
|
||
# 设置环境变量
|
||
ENV LANG=C.UTF-8 \
|
||
TZ=Asia/Shanghai \
|
||
PGCLIENTENCODING=UTF8
|
||
|
||
# 安装时区数据(contrib 扩展已包含在官方 postgres 镜像中)
|
||
RUN apk add --no-cache tzdata \
|
||
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
|
||
&& echo "Asia/Shanghai" > /etc/timezone
|
||
|
||
# 创建初始化目录
|
||
RUN mkdir -p /docker-entrypoint-initdb.d /opt/sql
|
||
|
||
# 复制初始化脚本和 SQL 文件
|
||
COPY init/sql/ /opt/sql/
|
||
COPY init/bin.sh /opt/bin.sh
|
||
|
||
# 创建 Docker 初始化入口脚本
|
||
RUN cat > /docker-entrypoint-initdb.d/01-init-database.sh <<'EOF'
|
||
#!/bin/bash
|
||
set -e
|
||
|
||
echo "=========================================="
|
||
echo "Urban Lifeline - PostgreSQL 数据库初始化"
|
||
echo "=========================================="
|
||
|
||
# 设置环境变量
|
||
export PGCLIENTENCODING=UTF8
|
||
|
||
# 检查数据库是否已初始化(通过检查初始化状态表)
|
||
check_initialized() {
|
||
# 先检查数据库是否存在
|
||
if ! psql -U "$POSTGRES_USER" -d "postgres" -tAc "SELECT 1 FROM pg_database WHERE datname = '$POSTGRES_DB'" | grep -q 1; then
|
||
return 1 # 数据库不存在,需要初始化
|
||
fi
|
||
|
||
# 检查初始化状态表是否存在且标记为成功
|
||
if psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -tAc "SELECT 1 FROM _db_init_status WHERE script_name = '01-init-database.sh' AND status = 'success'" 2>/dev/null | grep -q 1; then
|
||
return 0 # 已初始化
|
||
fi
|
||
|
||
return 1 # 未初始化
|
||
}
|
||
|
||
# 检查是否已经初始化
|
||
if check_initialized; then
|
||
echo "=========================================="
|
||
echo "✅ 数据库已初始化,跳过初始化步骤"
|
||
echo "=========================================="
|
||
exit 0
|
||
fi
|
||
|
||
echo "首次启动,开始初始化数据库..."
|
||
|
||
cd /opt/sql
|
||
|
||
# 执行 initAll.sql(包含创建数据库、表结构和初始数据)
|
||
echo "执行数据库初始化脚本..."
|
||
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "postgres" -f initAll.sql
|
||
|
||
if [ $? -ne 0 ]; then
|
||
echo "=========================================="
|
||
echo "❌ 数据库初始化失败!"
|
||
echo "=========================================="
|
||
exit 1
|
||
fi
|
||
|
||
# 创建初始化状态表并标记完成
|
||
echo "标记初始化状态..."
|
||
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
|
||
-- 创建初始化状态表
|
||
CREATE TABLE IF NOT EXISTS _db_init_status (
|
||
id SERIAL PRIMARY KEY,
|
||
script_name VARCHAR(255) NOT NULL UNIQUE,
|
||
executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
status VARCHAR(50) DEFAULT 'init'
|
||
);
|
||
|
||
-- 标记初始化完成
|
||
INSERT INTO _db_init_status (script_name, status)
|
||
VALUES ('01-init-database.sh', 'success')
|
||
ON CONFLICT (script_name) DO UPDATE SET status = 'success', executed_at = CURRENT_TIMESTAMP;
|
||
EOSQL
|
||
|
||
echo "=========================================="
|
||
echo "✅ 数据库初始化完成!"
|
||
echo "=========================================="
|
||
EOF
|
||
|
||
# 设置执行权限
|
||
RUN chmod +x /docker-entrypoint-initdb.d/01-init-database.sh \
|
||
&& chmod +x /opt/bin.sh
|
||
|
||
# 暴露端口
|
||
EXPOSE 5432
|
||
|
||
# 健康检查
|
||
HEALTHCHECK --interval=10s --timeout=5s --retries=5 --start-period=60s \
|
||
CMD pg_isready -U ${POSTGRES_USER:-postgres} -d ${POSTGRES_DB:-urban_lifeline} || exit 1
|