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

Docker容器Postgres数据丢失:提交镜像后为何数据库为空?

Postgres容器提交镜像后数据丢失的原因及解决办法

问题描述

我用以下docker-compose配置创建了Postgres容器:

services:
  db:
    image: postgres
    restart: always
    # set shared memory limit when using docker-compose
    shm_size: 128mb
    # or set shared memory limit when deploy via swarm stack
    #volumes:
    #  - type: tmpfs
    #    target: /dev/shm
    #    tmpfs:
    #      size: 134217728 # 128*2^20 bytes = 128Mb
    ports:
      - "5433:5432"
    environment:
      POSTGRES_PASSWORD: example

连接容器修改数据库内容后,执行docker commit f3a8955f3df6提交容器,再用docker tag f3a8955f3df6 myimage打标签。但运行该镜像后,数据库却是清空状态,这是为什么?(采用手动操作方式)

原因分析

核心问题在于Postgres官方镜像的Dockerfile中,已经将数据库数据目录(默认是/var/lib/postgresql/data)声明为了VOLUME。Docker卷有两个关键特性:

  • 卷的数据独立于容器的可写层,容器运行时卷内的数据不会写入到容器自身的可写层中
  • docker commit命令只会提交容器的可写层内容,卷里的所有数据都不会被包含到新生成的镜像里

你修改的数据库数据实际存在于这个独立卷中,commit后的镜像不包含这些数据,运行新容器时会重新初始化一个空卷,自然看不到之前的修改内容。

解决办法

推荐的持久化方式

不要用docker commit保存数据库数据,应该通过数据卷或绑定挂载来持久化:

  • 在docker-compose中添加卷配置,把数据目录挂载到命名卷:
    services:
      db:
        # 其他配置保持不变
        volumes:
          - postgres_data:/var/lib/postgresql/data
    volumes:
      postgres_data:
    
  • 后续启动新容器时,只要复用这个postgres_data卷,就能直接读取之前的数据

生成包含数据的镜像(不推荐)

如果一定要生成带数据的镜像,需要修改官方镜像的Dockerfile:

  1. 复制官方Postgres的Dockerfile,删除其中的VOLUME /var/lib/postgresql/data声明
  2. 用修改后的Dockerfile重新构建自定义镜像
  3. 运行该自定义镜像的容器,修改数据后再执行docker commit,此时数据会被包含进新镜像

这种方式不推荐,因为数据和镜像耦合后会导致镜像体积过大,备份、迁移数据也会变得繁琐,不符合Docker的最佳实践。

内容的提问来源于stack exchange,提问作者Андрей Дов

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 05:53:24