为什么在构build时不postgres官方docker回购启动数据库服务?

在https://github.com/docker-library/postgres(github回购)和https://registry.hub.docker.com/_/postgres/ (docker中心)的背景下,

可以看出数据库是由Entrypoint和CMD用bash脚本启动的

/docker-entrypoint.sh 

 ENTRYPOINT ["/docker-entrypoint.sh"] EXPOSE 5432 CMD ["postgres"] 

提供另一个脚本钩来改变数据库

 /docker-entrypoint-initdb.d 

这意味着只有在运行时键入docker run命令时,数据库才能启动(可以是pqsl)。

这会导致一个问题,我们无法在构build时运行数据库之前自定义数据库,例如添加扩展名和使用数据填充数据库。

当然,这可以在运行时完成。 但每次运行图像时都有重复操作的优点。

那么,从Docker或Postgres的angular度来看,这个devise背后的逻辑是什么? 我怎样才能添加扩展和生成时间填充数据?

如果要在构build时自定义(创build,填充数据)数据库,这意味着将数据库数据本身写入了docker映像文件系统(因为在构build时无法装入卷)。

与此相关的问题是docker映像文件系统是一个特殊的文件系统( AUFS或btrfs等),它不能为诸如数据库服务器等数据密集型应用程序提供良好的I / O性能。

因此,您希望将数据写在一个卷上,而不是写在docker容器文件系统上。 由于在构build时不知道在运行时使用的卷是多less,而且在构build时没有任何意义来装入卷,所以在构build时没有人应该创build数据库。

此外,如果仔细查看官方PostgreSQL映像的Dockerfile ,则会看到有一条VOLUME指令,它使数据写入的path成为一个卷。 这意味着图像的devise使得数据永远不会碰到docker容器文件系统。

如果您查看其他Docker文件来查看其他数据库或数据密集型应用程序,您将会注意到它们都以这种方式运行。 另外一个原因是,将Docker容器设置为不可变是一种很好的做法 。

如果你想在图像上安装额外的模块,只要不依赖于写在卷上的数据,只要你确定为任何path声明一个卷, 。


TL;博士

应用程序代码/二进制→docker镜像文件系统

应用程序数据→泊坞窗卷

这是从postgres图像( 库/ postgres )的docker页面:

如果你想从这个派生的图像中进行额外的初始化,可以在/docker-entrypoint-initdb.d下添加一个*.sql or *.sh脚本(如果需要的话创build目录)。 在入口点调用initdb创build默认的postgres用户和数据库之后,它将运行任何*.sql文件,并在该目录中find任何*.sh脚本以在启动服务之前进行进一步的初始化。

您也可以使用简单的Dockerfile来扩展图像以设置区域设置。 以下示例将将默认语言环境设置为de_DE.utf8

 FROM postgres:9.4 RUN localedef -i de_DE -c -f UTF-8 -A /usr/share/locale/locale.alias de_DE.UTF-8 ENV LANG de_DE.utf8 

由于数据库初始化仅在容器启动时发生,这使我们能够在创build语言之前设置语言。

您可以像上面粘贴的文档那样展示图片。 您也可以使用exec命令,并从主机上直接执行容器内的任何操作。 我花了一点时间去适应,我越来越多地玩弄它,我会继续发现。

更新:

 sudo docker run --name some-postgres -v ~/PATH/TO/some-postgres/data:/var/lib/postgres/data -p 127.0.0.1:5432:5432 -e POSTGRES_PASSWORD=test -d postgres