两种PostgreSQL Docker实例创建方式差异及报错原因咨询
为何两种PostgreSQL Docker实例创建方式效果不同?
方式1:直接使用官方镜像的docker-compose配置
services: postgres: image: postgres:15 restart: always volumes: - db_data:/var/lib/postgresql/data environment: POSTGRES_PASSWORD: password ports: - "5432:5432"
方式2:通过Dockerfile构建镜像的docker-compose配置
docker-compose配置
services: postgres: build: context: . dockerfile: Dockerfile restart: always volumes: - db_data:/var/lib/postgresql/data environment: POSTGRES_PASSWORD: password ports: - "5432:5432"
搭配的Dockerfile内容
FROM postgres:15
问题现象
方式1可正常运行,但方式2启动时报错:
2024-02-24 20:50:07 2024-02-25 04:50:07.584 UTC [1] LOG: invalid value for parameter "lc_messages": "en_US.utf8" 2024-02-24 20:50:07 2024-02-25 04:50:07.584 UTC [1] LOG: invalid value for parameter "lc_monetary": "en_US.utf8" 2024-02-24 20:50:07 2024-02-25 04:50:07.584 UTC [1] LOG: invalid value for parameter "lc_numeric": "en_US.utf8" 2024-02-24 20:50:07 2024-02-25 04:50:07.584 UTC [1] LOG: invalid value for parameter "lc_time": "en_US.utf8" 2024-02-24 20:50:07 2024-02-25 04:50:07.584 UTC [1] FATAL: configuration file "/var/lib/postgresql/data/postgresql.conf" contains errors 2024-02-24 20:47:25 2024-02-24 20:47:25 PostgreSQL Database directory appears to contain a database; Skipping initialization
同时在方式2的容器内看不到/var/lib/postgresql/data目录,这是什么原因?
问题原因分析
容器内看不到data目录的原因
使用Docker卷(db_data:/var/lib/postgresql/data)时,卷会挂载到容器的该路径,覆盖镜像中原有的目录内容。如果卷未被正确初始化(比如容器启动失败),进入容器后看到的是卷的空内容,而非镜像里的原目录结构。另外,PostgreSQL启动失败时,无法完成数据库目录的初始化流程,导致卷中没有生成对应的目录和文件。两种方式差异的核心原因
官方postgres镜像构建时已预配置适配自身环境的区域设置(locale),但通过自定义Dockerfile构建镜像时,Docker构建环境与官方镜像的运行环境可能存在locale差异,或构建过程中丢失了官方镜像的locale配置。
具体来说,官方postgres镜像的启动脚本会自动检测并设置合适的locale参数,但重新构建镜像时,可能受本地环境locale设置影响,导致生成的镜像中缺少en_US.utf8这个locale。而方式1启动时已在db_data卷中生成了基于官方镜像locale的postgresql.conf,方式2启动时读取该配置文件,但自身环境没有对应locale,因此触发报错。
解决方案
- 清理现有卷并重新初始化
删除已有的db_data卷,让方式2的容器重新生成适配当前镜像环境的数据库目录和配置:
docker volume rm $(docker volume ls -q | grep db_data)
之后重新启动容器即可。
- 在Dockerfile中显式配置locale
如果需要保留现有卷,或确保构建的镜像locale与官方一致,可在Dockerfile中添加locale配置:
FROM postgres:15 RUN apt-get update && apt-get install -y locales && \ locale-gen en_US.UTF-8 && \ update-locale LANG=en_US.UTF-8 ENV LANG en_US.UTF-8 ENV LC_ALL en_US.UTF-8
- 直接使用官方镜像
若无需自定义镜像逻辑,方式1直接使用官方镜像的方式更稳定,可避免构建过程引入的环境差异问题。
内容的提问来源于stack exchange,提问作者Qiang Li
相关产品推荐
相关产品推荐

