使用Docker的Postgres:Postgres在持久化数据时无法加载
我是Postgres的新手。
我更新了我使用的Dockerfile,并在其上成功安装了Postgresql。 (我的图像运行Ubuntu 16.04,我使用的是Postgres 9.6。)
一切工作正常,直到我试图将数据库移动到一个与docker-compose
一个Volume
(这是用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
所拥有? - 我应该考虑用
root
来运行postgres吗?
任何提示欢迎。
编辑:链接到Dockerfile和docker-compose.xml 。
我会回答我自己的问题:
日志和错误
更重要的是我没有收到任何具体的错误信息。
为了改变这种情况,我禁用了supervisord中的[program:postgresql]
部分,而是从命令行手动启动了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
修复configuration
我解决了这个错误,最终将它们添加到我的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
来初始化数据目录。 谨防! 这将清除在该文件夹中find的任何数据。 像这样:
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
testing
上述之后,我终于可以正常运行postgres了。 我使用这个命令来运行它并从命令行进行testing:
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
为了testing,我保持运行,然后,从另一个提示,检查一切正常运行:
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
…确保重新启动容器并再次testing以检查数据是否持续。
然后最后恢复supervisord中的[program:postgresql]
部分,重build图像并重新启动容器,确保一切正常(特别是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
脚本,但是我不清楚为什么/何时使用这些脚本。)
我在这花了很多时间。 希望详细的答案将帮助某人下线。
PS:我最终做出了一个我的问题的最小例子。 如果这可以帮助任何人,在这里他们是: Dockerfile , supervisord.conf和docker-compose.yml 。
我不知道这是否会是另一种获得相同结果的方法(我也是Docker和Postgres的新手),但是您是否尝试使用PostgreSQL的官方存储库映像( https://hub.docker.com/_/ postgres / )?
我将容器中的数据从环境variablesPGDATA设置为'/ 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
当卷为空时,所有文件都由映像启动脚本创build,如果它们已经存在,数据库就开始使用它。
根据以往的经验,我可以看到可能是一个问题。 我不能说这是否会有所帮助,但值得一试。 我会添加这个作为评论,但我不能因为我的代表不够高。
我已经看到了一些关于如何在Dockerfile中构build语句的问题。 你已经多次安装了各种东西,并且通过代码偶尔更新。 在我自己的文件中,我已经注意到,这可能会导致我的服务和安装由于不同的层次有些随意的行为。
这似乎不能直接解决您的问题,但按照最佳实践中所述清理文件,为我解决了许多Dockerfile问题。
find这些问题的第一个地方之一就是从这里开始运行的最佳实践 。 这帮助我解决了过去棘手的问题,希望能够解决或者至less使问题更容易解决。
要特别注意这个部分:
构build完成后,所有的图层都在Dockercaching中。 假设您稍后通过添加额外的软件包来修改apt-get install:
FROM ubuntu:14.04 RUN apt-get update RUN apt-get install -y curl nginx
Docker将初始和修改后的指令视为相同,并重用先前步骤中的caching。 因此,不会执行apt-get更新,因为构build使用caching版本。 因为apt-get更新没有运行,所以你的构build可能会得到curl和nginx包的过时版本。
读完这些之后,我将首先整理所有的依赖关系。