在https://github.com/docker-library/postgres(github repo)和https://registry.hub.docker.com/_/postgres/(码头中心)的背景下
可以看到数据库由Entrypoint和CMD以bash脚本
启动/docker-entrypoint.sh
带
ENTRYPOINT ["/docker-entrypoint.sh"]
EXPOSE 5432
CMD ["postgres"]
为更改数据库提供的另一个脚本钩是
/docker-entrypoint-initdb.d
表示数据库仅在运行时启动(可以是pqsl),当输入docker run命令时。
这会导致问题,我们无法在构建时运行数据库之前对其进行自定义,例如添加扩展并使用数据填充数据库。
当然,它可以在运行时完成。但它有利于每次运行图像时重复操作。
那么,这个设计背后的逻辑是什么,从docker或postgres的角度来看?如何在构建时添加扩展和填充数据?
答案 0 :(得分:3)
如果要在构建时自定义(创建,填充数据)数据库,这意味着数据库数据将写入docker镜像文件系统本身(因为无法在构建时安装卷)。
问题在于docker镜像文件系统是一个特殊的(AUFS或btrfs等),它不能为数据密集型应用程序(如数据库)提供良好的I / O性能服务器。
因此,您希望将数据写在卷而不是docker容器文件系统上。正如您在构建时不知道运行时使用的卷是什么,并且因为无论如何在构建时安装卷都没有意义,因此没有人应该在构建时创建数据库。
此外,如果仔细查看官方PostgreSQL映像的Dockerfile,您将看到有一条VOLUME指令,该指令将数据写入卷的路径。这意味着图像的设计使得数据永远不会到达docker容器文件系统。
如果您查看其他数据库或数据密集型应用程序的其他Dockerfiles,您会发现它们都以这种方式运行。另一个原因是它被接受为good practice以使您的docker容器不可变。
如果要为映像安装其他模块,只要这些模块不依赖于将写入卷上的数据,并且只要确保为任何路径声明卷,它们就可以了。写数据。
应用程序代码/二进制→docker image filesystem
应用程序数据→泊坞窗量
答案 1 :(得分:1)
这是来自postgres图像(library/postgres)的泊坞窗页面:
如果您希望在从此图像派生的图像中执行其他初始化,请在*.sql or *.sh
下添加/docker-entrypoint-initdb.d
脚本(如有必要,请创建目录)。在入口点调用initdb
以创建默认的postgres
用户和数据库之后,它将运行任何*.sql
个文件并获取该目录中找到的任何*.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
由于数据库初始化仅在容器启动时发生,因此我们可以在创建之前设置语言。
您可以像我上面粘贴的文档中显示的那样扩展图像。您还可以使用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