【问题标题】:Docker-compose v3 not persisting postgres databaseDocker-compose v3 不持久化 postgres 数据库
【发布时间】:2018-08-19 14:16:09
【问题描述】:

在关闭并重新启动 docker-compose v3 容器后,我难以持久化 postgres 数据。这似乎是一个常见问题,但经过大量搜索后,我一直无法找到有效的解决方案。

我的问题与此处类似:How to persist data in a dockerized postgres database using volumes,但该解决方案不起作用 - 所以请不要关闭。我将通过以下所有步骤来复制问题。

这是我的 docker-compose 文件:

version: "3"  
services:  
  db:
    image: postgres:latest
    environment:
      POSTGRES_DB: zennify
      POSTGRES_USER: patientplatypus
      POSTGRES_PASSWORD: SUPERSECRETPASSWORD
    volumes:
      - pgdata:/var/lib/postgresql/data:rw
    ports:
      - 5432:5432
  app:
    build: .
    command: ["go", "run", "main.go"]
    ports:
      - 8081:8081
    depends_on:
      - db
    links:
      - db
volumes: 
  pgdata:

这是我启动并写入数据库后的终端输出:

patientplatypus:~/Documents/zennify.me/backend:08:54:03$docker-compose up
Starting backend_db_1 ... done
Starting backend_app_1 ... done
Attaching to backend_db_1, backend_app_1
db_1   | 2018-08-19 13:54:53.661 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
db_1   | 2018-08-19 13:54:53.661 UTC [1] LOG:  listening on IPv6 address "::", port 5432
db_1   | 2018-08-19 13:54:53.664 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
db_1   | 2018-08-19 13:54:53.692 UTC [24] LOG:  database system was shut down at 2018-08-19 13:54:03 UTC
db_1   | 2018-08-19 13:54:53.712 UTC [1] LOG:  database system is ready to accept connections
app_1  | db init successful
app_1  | create_userinfo_table started
app_1  | create_userinfo_table finished
app_1  | inside RegisterUser in Golang
app_1  | here is the users email:
app_1  | %s pwoiioieind@gmail.com
app_1  | here is the users password:
app_1  | %s ANOTHERSECRETPASSWORD
app_1  | value of randSeq,  7NLHzuVRuTSxYZyNP6MxPqdvS0qy1L6k
app_1  | search_userinfo_table started
app_1  | value of OKtoAdd, %t true
app_1  | last inserted id = 1 //I inserted in database!
app_1  | value of initUserRet,  added

我还可以在另一个终端选项卡中连接到 postgres,并验证是否使用 psql -h 0.0.0.0 -p 5432 -U patientplatypus zennify 正确写入了数据库。这是userinfo 表的输出:

zennify=# TABLE userinfo
;
         email         |                           password                           |            regstring             | regbool | uid 
-----------------------+--------------------------------------------------------------+----------------------------------+---------+-----
 pwoiioieind@gmail.com | $2a$14$u.mNBrITUJaVjly15BOV9.Q9XmELYRjYQbhEUi8i4vLWtOr9QnXJ6 | r33ik3Jtf0m9U3zBRelFoWyYzpQp7KzR | f       |   1
(1 row)

所以写入数据库一次就可以了!

但是

现在让我们执行以下操作:

$docker-compose stop
backend_app_1 exited with code 2
db_1   | 2018-08-19 13:55:51.585 UTC [1] LOG:  received smart shutdown request
db_1   | 2018-08-19 13:55:51.589 UTC [1] LOG:  worker process: logical replication launcher (PID 30) exited with exit code 1
db_1   | 2018-08-19 13:55:51.589 UTC [25] LOG:  shutting down
db_1   | 2018-08-19 13:55:51.609 UTC [1] LOG:  database system is shut down
backend_db_1 exited with code 0

从使用docker-compose stop 而不是docker-compose down 阅读有关此主题的其他线程,应该可以持久化本地数据库。但是,如果我再次使用docker-compose up,然后不向数据库写入新值,只需在 postgres 中查询表,它是空的:

zennify=# TABLE userinfo;
 email | password | regstring | regbool | uid 
-------+----------+-----------+---------+-----
(0 rows)

我以为我可能在初始化步骤的代码中覆盖了表格,但我只有(golang sn-p):

_, err2 := db.Exec("CREATE TABLE IF NOT EXISTS userinfo(email varchar(40) NOT NULL, password varchar(240) NOT NULL, regString  varchar(32) NOT NULL, regBool bool NOT NULL, uid serial NOT NULL);")

当然,只有在以前没有创建表的情况下才创建表。

有人对出了什么问题有任何建议吗?据我所知,这一定是 docker-compose 的问题,而不是我的代码。感谢您的帮助!

编辑:

我已经研究过使用版本 2 的 docker,并使用以下 compose 遵循本文 (Docker compose not persisting data) 中显示的格式:

version: "2"  
services:  
  app:
    build: .
    command: ["go", "run", "main.go"]
    ports:
      - "8081:8081"
    depends_on:
      - db
    links:
      - db
  db:
    image: postgres:latest
    environment:
      POSTGRES_DB: zennify
      POSTGRES_USER: patientplatypus
      POSTGRES_PASSWORD: SUPERSECRETPASSWORD
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data/
volumes:
  pgdata: {}

不幸的是,我又遇到了同样的问题 - 数据可以写入,但在关机之间不会持续存在。

编辑编辑:

请注意,使用docker-compose up 实例化服务然后依赖docker-compose stopdocker-compose start 对数据的持久性没有实质性影响。仍然不会在重新启动后持续存在。

编辑编辑编辑:

我发现了更多的东西。如果您想正确执行到 docker 容器中以查看数据库的值,您可以执行以下操作:

docker exec -it backend_db_1 psql -U patientplatypus -W zennify

backend_db_1 是 docker 容器数据库的名称,patientplatypus 是我的用户名,zennify 是数据库容器中的数据库名称。

我也尝试过在 docker-compose 文件中添加一个网桥,但没有成功,如下所示:

version: "3"  
services:  
  db:
    build: ./db
    image: postgres:latest
    environment:
      POSTGRES_USER: patientplatypus
      POSTGRES_PASSWORD: SUPERSECRET
      POSTGRES_DB: zennify
    ports:
      - 5432:5432
    volumes:
      - ./db/pgdata:/var/lib/postgresql/data
    networks:
      - mynet
  app:
    build: ./
    command: bash -c 'while !</dev/tcp/db/5432; do sleep 5; done; go run main.go'
    ports:
      - 8081:8081
    depends_on:
      - db
    links:
      - db
    networks:
      - mynet
networks:
  mynet:
    driver: "bridge"

我目前的工作理论是,无论出于何种原因,我的 golang 容器正在将其具有的 postgres 值写入本地存储而不是共享卷,我不知道为什么。这是我对 golang open 命令的最新想法:

data.InitDB("postgres://patientplatypus:SUPERSECRET@db:5432/zennify/?sslmode=disable")
...
func InitDB(dataSourceName string) {
    db, _ := sql.Open(dataSourceName)
    ...
}

这同样有效,但它不会持久化数据。

【问题讨论】:

  • 嘿,你找到灵魂了吗

标签: database postgresql docker docker-compose persistence


【解决方案1】:

我在使用 docker-compose 运行 postgres db 和 Django 应用时遇到了完全相同的问题。

事实证明,我的应用程序的 Dockerfile 正在使用执行以下命令的入口点:python manage.py flush,它会清除数据库中的所有数据。由于每次应用容器启动时都会执行此操作,因此它会清除所有数据。它与 docker-compose 无关。

【讨论】:

  • 你先生,应该获得奖章!这让我发疯,这是完全相同的问题。我的入口点中有一个python manage.py flush --no-input。天哪
  • 低调的回答!
【解决方案2】:

Docker 命名卷与您使用的原始 docker-compose 保持一致。

version: "3"  
services:  
  db:
    image: postgres:latest
    environment:
      POSTGRES_DB: zennify
      POSTGRES_USER: patientplatypus
      POSTGRES_PASSWORD: SUPERSECRETPASSWORD
    volumes:
      - pgdata:/var/lib/postgresql/data:rw
    ports:
      - 5432:5432
volumes: 
  pgdata:

如何证明?

1) 运行docker-compose up -d 创建容器和卷。

docker-compose up -d
Creating network "docker_default" with the default driver
Creating volume "docker_pgdata" with default driver
Pulling db (postgres:latest)...
latest: Pulling from library/postgres
be8881be8156: Already exists
bcc05f43b4de: Pull complete
....
Digest: sha256:0bbfbfdf7921a06b592e7dc24b3816e25edfe6dbdad334ed227cfd64d19bdb31
Status: Downloaded newer image for postgres:latest
Creating docker_db_1 ... done

2) 在卷位置写入文件

docker-compose exec db /bin/bash -c 'echo "File is persisted" &gt; /var/lib/postgresql/data/file-persisted.txt'

3) 运行docker-compose down

请注意,当您运行时,它不会根据documentation 删除任何卷,只删除容器和网络。您需要使用 -v 运行它才能删除卷。

Stopping docker_db_1 ... done Removing docker_db_1 ... done Removing network docker_default

还要注意您的音量仍然存在 docker volume ls | grep pgdata local docker_pgdata

4) 再次运行 docker-compose up -d 以启动容器并重新挂载卷。

5) 查看文件仍在卷中

docker-compose exec db /bin/bash -c 'ls -la /var/lib/postgresql/data | grep persisted ' -rw-r--r-- 1 postgres root 18 Aug 20 04:40 file-persisted.txt

命名卷不是主机卷。阅读documentation 或查找一些文章来解释差异。另请参阅 Docker 管理存储命名卷文件的位置,您可以使用不同的驱动程序,但目前最好了解基本区别。

【讨论】:

  • 谢谢。这有助于我更多地了解使用 docker-compose updocker-compose down 时挂载卷上发生的情况。它是持久的。
【解决方案3】:

在环境变量下:

PGDATA 此可选环境变量可用于为数据库文件定义另一个位置(例如子目录)。 默认为 /var/lib/postgresql/data,但如果您使用的数据卷是 fs 挂载点(如 GCE 永久磁盘),Postgres initdb 建议使用子目录(用于例如 /var/lib/postgresql/data/pgdata )被创建以包含数据。

更多信息在这里 --> https://hub.docker.com/_/postgres/

【讨论】:

  • 哦,嗨,Trung!嗯....所以我将volumes: - pgdata:/var/lib/postgresql/data/ 编辑为volumes: - pgdata:/var/lib/postgresql/data/pgdata 但这似乎不正确并且无法编译。仅使用 volumes: /var/lib/postgresql/data/pgdata 编译并运行,但不会在重新启动之间持续存在。我想我对标签名应该是什么和路径名应该是什么感到困惑。 docker-compose 文件应该是什么样的?
猜你喜欢
  • 2021-12-28
  • 1970-01-01
  • 2019-06-17
  • 2017-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-13
  • 1970-01-01
相关资源
最近更新 更多