问题 Postgres与Docker:Postgres在持久化数据时无法加载


我是Postgres的新手。

我更新了我使用的Dockerfile并成功安装了Postgresql。 (我的图像运行Ubuntu 16.04,我正在使用Postgres 9.6。)

一切正常,直到我试图将数据库移动到 Volume 同 docker-compose (那是在制作了容器文件夹的副本之后 cp -R /var/lib/postgresql /somevolume/。)

问题在于Postgres一直在崩溃,正如supervisord所见:

2017-07-26 18:55:38,346 INFO exited: postgresql (exit status 1; not expected)
2017-07-26 18:55:39,355 INFO spawned: 'postgresql' with pid 195
2017-07-26 18:55:40,430 INFO success: postgresql entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2017-07-26 18:55:40,763 INFO exited: postgresql (exit status 1; not expected)
2017-07-26 18:55:41,767 INFO spawned: 'postgresql' with pid 197
2017-07-26 18:55:42,841 INFO success: postgresql entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2017-07-26 18:55:43,179 INFO exited: postgresql (exit status 1; not expected)
(and so on…)

日志

我不清楚发生了什么 /var/log/postgresql 仍然是空的。

CHOWN?

我怀疑它与用户有关。如果我将容器内的数据文件夹和我制作的副本与卷进行比较,唯一的区别是原件属于 postgres 而副本由...拥有 root

我试过跑 chown -R postgres:postgres 在副本上。但是,该操作成功完成 postmaster.pid 仍属于 root 我认为那就是问题所在。

问题

  • 如何获得有关崩溃原因的更多信息?
  • 我怎么能这样做呢 postmaster.id 归自己所有 postgres ?
  • 我应该考虑运行postgres root 代替?

任何暗示欢迎。


编辑:链接到 Dockerfile 和 泊坞窗,compose.xml


11639
2017-07-26 17:15


起源

如果可能的话,请你加我 docker-compose.yml 和 Dockerfile 它将帮助你理解你的问题。 - vedarthk
从文件看起来你试图在一个容器中运行所有东西,我建议你将要运行的每个进程分成单独的容器。同样对于PosgreSQL数据,我建议你转储SQL并恢复它,或者su到postgres并进行备份。 - vedarthk
只要应用程序未运行,就可以安全地删除任何.pid文件。只需这样做再试一次。你在这里也有一个错字:“但是postmaster.pid仍属于 Postgres的“你想说 根 - Robert
@Robert谢谢你修正了错字。随着postgres不断崩溃和重启,.pid不断消失并重新出现。 - Fabien Snauwaert
你在postgres的主管中运行什么命令?如果在容器内手动运行它会得到什么错误? - Miguel Marques


答案:


我会回答我自己的问题:

日志和错误

更重要的是我没有得到任何具体的错误信息。

为了改变这种状况,我禁用了 [program:postgresql] 在supervisord部分,而是从命令行手动启动postgres(感谢Miguel Marques通过他的评论让我走上正确的轨道。)

然后我终于得到了一些有用的错误消息:

2017-08-02 08:27:09.134 UTC [37] LOG:  could not open temporary statistics file "/var/run/postgresql/9.6-main.pg_stat_tmp/global.tmp": No such file or directory

修复配置

我用这个修复了上面的错误,最后将它们添加到我的 Dockerfile

mkdir -p /var/run/postgresql/9.6-main.pg_stat_tmp
chown postgres.postgres /var/run/postgresql/9.6-main.pg_stat_tmp -R

(感谢 这家伙 为修复。)

为了使数据永久化,我还必须这样做,因为postgres可以访问卷:

mkdir -p /var/lib/postgresql/9.6/main
chmod 700 /var/lib/postgresql/9.6/main 

我也用过 initdb 初始化数据目录。谨防!这将删除该文件夹中的所有数据。像这样:

rm -R /var/lib/postgresql/9.6/main/*
ls /var/lib/postgresql/9.6/main/
/usr/lib/postgresql/9.6/bin/initdb  -D /var/lib/postgresql/9.6/main

测试

在上面之后,我终于可以正确运行postgres了。我使用此命令来运行它并从命令行进行测试:

su postgres
/usr/lib/postgresql/9.6/bin/postgres -D /var/lib/postgresql/9.6/main -c config_file=/etc/postgresql/9.6/main/postgresql.conf # as per the Docker docs

为了测试,我保持运行,然后,从另一个提示,检查一切运行正常与此:

su postgres
psql
CREATE TABLE cities ( name varchar(80), location point );
INSERT INTO cities VALUES ('San Francisco', '(-194.0, 53.0)');
select * from cities; # repeat this command after restarting the container to check that the data does persist

...确保重新启动容器并再次测试以检查数据是否仍然存在。

然后终于恢复了 [program:postgresql] 在supervisord中,重建图像并重新启动容器,确保一切正常(特别是supervisord: tail /var/log/supervisor/supervisord.log),它做到了。

(我在supervisord.conf中使用的命令也是 /usr/lib/postgresql/9.6/bin/postgres -D /var/lib/postgresql/9.6/main -c config_file=/etc/postgresql/9.6/main/postgresql.conf, 按照 这篇Docker文章 和其他postgres + supervisord的例子。其他选项一直在使用 pg_ctl 或者 init.d 脚本,但我不清楚为什么/何时会使用这些。)


我花了很多时间在这上面。希望详细的答案可以帮助有人下线。

P.S。:我最终制作了一个我的问题的最小例子。如果这可以帮助任何人,他们在这里: Dockerfilesupervisord.conf 和 泊坞窗,compose.yml


5
2017-08-02 10:32





我不知道这是否是实现相同结果的另一种方式(我也是Docker和Postgres的新手),但你是否尝试过Postgres的官方存储库图像(https://hub.docker.com/_/postgres/)?

我从容器中获取数据,将环境变量PGDATA设置为'/ var / lib / postgresql / data / pgdata'并将其绑定到运行命令上的外部卷:

docker run --name bd_TEST --network=my_network --restart=always -e POSTGRES_USER="superuser" -e POSTGRES_PASSWORD="myawesomepass" -e PGDATA="/var/lib/postgresql/data/pgdata" -v /var/local/db_data:/var/lib/postgresql/data/pgdata -itd -p 5432:5432 postgres:9.6

当卷为空时,所有文件都由映像启动脚本创建,如果它们已经存在,则数据库开始使用它。


3
2017-08-05 03:16





根据过去的经验,我可以看到可能存在的问题。我不能说这是否会有所帮助,但值得一试。 我会添加这个作为评论,但我不能,因为我的代表不够高。

我在你的Dockerfile中如何构建你的语句时遇到了一些问题。您已多次安装各种内容,并且还通过代码偶尔更新。在我自己的文件中,我注意到这可能导致我的服务和安装有些随机的行为,因为不同的层。

这似乎不能直接解决您的问题,但是最佳实践中概述的清理文件已经解决了我过去的许多Dockerfile问题。

发现这些问题的第一个地方之一就是从这里开始 RUN的最佳实践。这帮助我解决过去棘手的问题,我希望它能解决或者至少让它变得更容易。

特别注意这部分:

构建映像后,所有层都在Docker缓存中。假设您稍后通过添加额外的包来修改apt-get install:

 FROM ubuntu:14.04
 RUN apt-get update
 RUN apt-get install -y curl nginx 

Docker将初始和修改的指令视为相同,并重用以前的缓存   脚步。因此,apt-get更新不会被执行,因为   build使用缓存版本。因为apt-get更新没有运行,   你的构建可能会得到一个过时的卷曲和版本   nginx包。

阅读本文之后,我将首先整合所有依赖项。


1
2017-08-01 21:51