简体   繁体   English

将 Docker Postgres 容器连接到现有的空数据库

[英]Connecting Docker Postgres container to an existing empty database

I want to create a tarball that contains an empty db (ie a series of empty tables) and a shell script launching a Postgres container that would connect to the empty db.我想创建一个包含空数据库(即一系列空表)的 tarball 和一个 shell 脚本,该脚本启动将连接到空数据库的 Postgres 容器。 The end product is a .tar.gz that has a copy of the db, a start script and a stop script.最终产品是一个 .tar.gz,它有一个 db 的副本、一个启动脚本和一个停止脚本。 All this is meant to work in macOS所有这些都适用于 macOS

To create the db I started a Postgres server locally on my laptop and created a db called 'postgres-15year'.为了创建数据库,我在笔记本电脑上本地启动了一个 Postgres 服务器,并创建了一个名为“postgres-15year”的数据库。 Using 'DBeaver' database manager and 'psql' at the CLI I can see that the dbase is correctly created and functional.在 CLI 中使用“DBeaver”数据库管理器和“psql”,我可以看到 dbase 已正确创建且功能正常。

I then created the following scripts:然后我创建了以下脚本:

start.sh启动文件

#!/bin/bash
echo $(pwd)
docker run --rm --name payments-15years -e POSTGRES_PASSWORD=docker -d -p5432:5432 -v$(pwd)/postgres-15year/data:/var/lib/postgresql/data:delegated postgres:11.6

stop.sh停止.sh

#!/bin/bash
docker stop payments-15years
echo "docker stop payments-15years"

I then put all this in a directory that I would like to tarball.然后我将所有这些放在我想要压缩的目录中。

在此处输入图片说明

So user would receiver the tarball, unpack it and run the start script and be able to connect to a db that has a predefined structure and schemas.因此,用户将接收 tarball,解压缩并运行启动脚本,并能够连接到具有预定义结构和模式的数据库。 Here is what I think 'my start.sh' script is doing:这是我认为“我的 start.sh”脚本正在做的事情:

  1. creating a container name 'payments-15years'创建容器名称“payments-15years”
  2. setting the db password for a generic user ('postgres')为通用用户设置数据库密码('postgres')
  3. setting the db port to 5432 and also mapping it to local server port 5432 (not sure if that's necessary but all the examples seem to do it)将 db 端口设置为 5432 并将其映射到本地服务器端口 5432(不确定是否有必要,但所有示例似乎都这样做)
  4. mapping the db to the container's var/lib and 'delegated' as opposed to 'cache' so changes persist将数据库映射到容器的 var/lib 和“委托”而不是“缓存”,因此更改会持续存在
  5. specifying the Postgres docker image as 11.6将 Postgres docker 镜像指定为 11.6

My challenge is that after running the start script 'docker ps' returns:我的挑战是在运行启动脚本 'docker ps' 后返回:

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
14d2cba6abe2        postgres:11.6       "docker-entrypoint.s…"   44 seconds ago      Up 42 seconds       0.0.0.0:5432->5432/tcp   payments-15years

But when I do so and then run 'psql' from CLI:但是当我这样做然后从 CLI 运行“psql”时:

docker exec -it payments-15years psql -U postgres

the database ('postgres-15year') is not listed.数据库 ('postgres-15year') 未列出。

Does anyone see what is wrong with my approach?有没有人看到我的方法有什么问题?

NOTE:笔记:

  1. I am not providing the db, however it is empty tables with schemas defined and all the above scripts and pictures should be sufficient to recreate the problem.我没有提供数据库,但是它是定义了架构的空表,并且上述所有脚本和图片应该足以重现问题。
  2. Closest stack answer I found was here but it didn't help.我找到的最接近的堆栈答案在这里,但没有帮助。

Actually when you ran the command with -v $(pwd)/postgres-15year/data:/var/lib/postgresql/data:delegated , According to the official documentation of the postgres-docker .其实,当你跑了命令-v $(pwd)/postgres-15year/data:/var/lib/postgresql/data:delegated ,按照官方文档postgres-docker

The -v /my/own/datadir:/var/lib/postgresql/data part of the command mounts the /my/own/datadir directory from the underlying host system as /var/lib/postgresql/data inside the container, where PostgreSQL by default will write its data files.命令的-v /my/own/datadir:/var/lib/postgresql/data部分将/my/own/datadir目录从底层主机系统挂载为容器内的/var/lib/postgresql/data ,其中PostgreSQL 默认会写入它的数据文件。

So you are just creating a data directory not a database.所以你只是在创建一个数据目录而不是一个数据库。 You can check it by using inspect keyword.您可以使用inspect关键字进行inspect

docker container inspect <container_name>

In your scenario payments-15years gives volume details of this,在您的方案 Payments-15years 中,提供了有关数量的详细信息,

"Mounts": [
            {
                "Type": "bind",
                "Source": "/Users/macair/postgres-15year/data",
                "Destination": "/var/lib/postgresql/data",
                "Mode": "delegated",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],

To create a database execute a interactive session as did before and create a db manually or try this.要创建数据库,请像以前一样执行交互式会话并手动创建数据库或尝试此操作。

docker run -it --rm --network some-network postgres psql -h some-postgres -U postgres

Reference to your comment first,先参考你的评论,

I was able to create the DB using interactive.我能够使用交互式创建数据库。 To populate the empty db with the proper schema I have a pg-dump file (.sql).要使用正确的模式填充空数据库,我有一个 pg-dump 文件 (.sql)。 I'm not sure how to make that file available to the container.我不确定如何使该文件可用于容器。 Thoughts?想法?

If you have dump file why one should bother to run the command once container up?如果您有转储文件,为什么要在容器启动后运行命令?

Better to make it part of Dockerfile and you will not need to and dump manually Docker image will take care of it.最好将其作为 Dockerfile 的一部分,您将不需要手动转储 Docker 映像将处理它。

FROM postgres
ADD mydb.sql /docker-entrypoint-initdb.d

Now if you up the container the DB will be populated automatically.现在,如果您启动容器,DB 将自动填充。

Initialization scripts初始化脚本

If you would like to do additional initialization in an image derived from this one, add one or more *.sql, *.sql.gz, or *.sh scripts under /docker-entrypoint-initdb.d (creating the directory if necessary).如果您想在从该镜像派生的镜像中进行额外的初始化,请在/docker-entrypoint-initdb.d下添加一个或多个 *.sql、*.sql.gz 或 *.sh 脚本(如有必要,创建目录)。 After the entrypoint calls initdb to create the default postgres user and database, it will run any *.sql files, run any executable *.sh scripts, and source any non-executable *.sh scripts found in that directory to do further initialization before starting the service.在入口点调用 initdb 创建默认的 postgres 用户和数据库后,它将运行任何 *.sql 文件,运行任何可执行的 *.sh 脚本,并在该目录中找到任何不可执行的 *.sh 脚本以在此之前进行进一步的初始化启动服务。

postgress init DB postgress 初始化数据库

Now come to your question, you can do that with Tarball, tar does not deal with volume while Postgres docker image come with volume .现在来回答你的问题,你可以用 Tarball 来做到这一点,tar 不处理 volume 而 Postgres docker image 带有volume so you need to follow the Dockerfile to import on Data on startup.所以你需要按照 Dockerfile 在启动时导入数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM