Postgresql Docker卷不保留数据

Postgresql Docker卷不保留数据,postgresql,docker,dockerfile,Postgresql,Docker,Dockerfile,这是我的docker文件: FROM ubuntu:14.04 RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8 RUN echo "deb http://apt.postgresql.org/pub/repos/apt/ precise-pgdg main" > /etc/apt/sources.list.d/pgdg.list R

这是我的docker文件:

FROM ubuntu:14.04

RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8
RUN echo "deb http://apt.postgresql.org/pub/repos/apt/ precise-pgdg main" > /etc/apt/sources.list.d/pgdg.list

RUN apt-get update && apt-get -y -q install python-software-properties software-properties-common \
    && apt-get -y -q install postgresql-9.3 postgresql-client-9.3 postgresql-contrib-9.3

USER postgres
RUN /etc/init.d/postgresql start \
    && psql --command "CREATE USER pguser WITH SUPERUSER PASSWORD 'pguser';" \
    && createdb -O pguser pgdb
USER root
RUN echo "host all  all    0.0.0.0/0  md5" >> /etc/postgresql/9.3/main/pg_hba.conf
RUN echo "listen_addresses='*'" >> /etc/postgresql/9.3/main/postgresql.conf
EXPOSE 5432

RUN mkdir -p /var/run/postgresql && chown -R postgres /var/run/postgresql
VOLUME  ["/etc/postgresql", "/var/log/postgresql", "/var/lib/postgresql"]
USER postgres

CMD ["/usr/lib/postgresql/9.3/bin/postgres", "-D", "/var/lib/postgresql/9.3/main", "-c", "config_file=/etc/postgresql/9.3/main/postgresql.conf"]
这就是我所做的

  • 我创建docker映像:

    docker build --rm=true -t my_image/postgresql:9.3
    
  • 然后,我在当前目录中创建一个名为
    data
    的新目录,并运行以下命令:

    docker run -i -t -v="data:/data" -p 5432:5432 my_image/postgresql:9.3
    
  • 我打开另一个终端,通过运行以下命令进入postgres外壳:

    psql -h my_docker_ip -p 5432 -U pguser -W pgdb
    
    我创建了一个表:

    pgdb=# create table test (test_id bigserial primary key);
    
  • 我使用
    \dt
    验证表是否存在,并退出postgres shell

  • 我终止docker进程并重新运行以下操作:

    docker run -i -t -v="data:/data" -p 5432:5432 my_image/postgresql:9.3
    
  • 我再次进入posgrest shell并运行
    \dt

  • 我注意到
    • 没有桌子
    • 数据
      目录中没有文件
  • 我一定是做错了什么,因为我假设我创建的表将继续存在。有人能指出我的错误吗?

    根据你的评论:

    数据已持久化,但我仍然无法在主机/data目录中找到持久化数据

    并运行此命令:

    docker run -i -t -v="data:/data" -p 5432:5432 my_image/postgresql:9.3
    
    您似乎混淆了命名卷和主机卷。当您为卷指定一个没有路径的名称时,将使用命名卷,如
    data
    。命名卷使用docker驱动程序(通常为本地)以您可以重用的给定名称存储数据。它的优点是列在docker volume ls中,并在安装位置初始化为映像的内容

    如果包含完整路径,如
    /home/username/data
    ,它将从docker主机而不是使用命名卷装载目录。最大的缺点是您无法使用映像中的内容初始化目录,并且可能会遇到权限问题,其中容器进程的uid与您在主机上使用的uid不匹配

    有关更多详细信息,请参见您的评论:

    数据已持久化,但我仍然无法在主机/data目录中找到持久化数据

    并运行此命令:

    docker run -i -t -v="data:/data" -p 5432:5432 my_image/postgresql:9.3
    
    您似乎混淆了命名卷和主机卷。当您为卷指定一个没有路径的名称时,将使用命名卷,如
    data
    。命名卷使用docker驱动程序(通常为本地)以您可以重用的给定名称存储数据。它的优点是列在docker volume ls中,并在安装位置初始化为映像的内容

    如果包含完整路径,如
    /home/username/data
    ,它将从docker主机而不是使用命名卷装载目录。最大的缺点是您无法使用映像中的内容初始化目录,并且可能会遇到权限问题,其中容器进程的uid与您在主机上使用的uid不匹配


    有关更多详细信息,请参见

    有一些东西让我感到困惑,对我来说,在官方文档中并不十分清楚

    据我所知,可以通过三种方式创建持久卷

    • 在容器调用时,包括完整路径(
      -v~/database:/data
      ):使来自主机的外部文件夹在docker容器内可用。两者都可以修改它
    • 在容器调用时使用卷名(
      -v datamysql:/data
      ):使容器内的卷保持可用。如果它不存在,则创建它。您可以使用
      docker volume ls
      按名称列出它们。在内部,它将存储在
      /var/lib/docker/volumes/ae4445f7c9317a22fe84726fb894c47754f38a7fd150c00fd877024889968750/_data
      等位置
    • 在容器构建时(Dockerfile中的卷[“/database/data”])。每次调用
      docker run
      都将创建一个新卷,即使您删除了该容器,该卷也将保持不变。这可能会造成混淆,因为后续调用将导致创建不同的卷,而这些卷不会被重用
    您可以使用列出命名(第二种情况)卷和未命名(第三种情况)卷

    $ docker volume ls                                                             
    DRIVER              VOLUME NAME                                                             
    local               064593b3e65977097d4d0c8402a6c633f1af69be2937bf118678ab8f97ee9a7e               
    local               4753ad0437d13e54c76d9c34a30a1843396a1866a0cf9237d500fdcca0d78c5f           
    local               8d7a35354f666b2e8a26866a35bbae36bb9601701d4c6b505ab8ce6629f69415               
    local               db48eefe8f189b36107ca9c4eebb792690590ab0ba055e7e4e2c9adfd1765b7e                    
    local               datamysql
    
    通过使用
    docker inspect mycontainer

    {
                    "Type": "volume",
                    "Name": "8d7a35354f666b2e8a26866a35bbae36bb9601701d4c6b505ab8ce6629f69415",
                    "Source": "/media/USBdrive/docker/volumes/8d7a35354f666b2e8a26866a35bbae36bb9601701d4c6b505ab8ce6629f69415/_data",
                    "Destination": "/var/lib/mysql",
                    "Driver": "local",
                    "Mode": "",
                    "RW": true,
                    "Propagation": ""
                },
    
    删除未使用的卷可能很方便(特别是对于第三种情况)


    由于您在Dockerfile中使用了
    VOLUME
    指令,因此属于第三种情况。检查您的容器以查找文件,如果希望重复会话来保存数据,请从命令行指定卷。

    有一点让我感到困惑,对我来说,在官方文档中不是很清楚

    据我所知,可以通过三种方式创建持久卷

    • 在容器调用时,包括完整路径(
      -v~/database:/data
      ):使来自主机的外部文件夹在docker容器内可用。两者都可以修改它
    • 在容器调用时使用卷名(
      -v datamysql:/data
      ):使容器内的卷保持可用。如果它不存在,则创建它。您可以使用
      docker volume ls
      按名称列出它们。在内部,它将存储在
      /var/lib/docker/volumes/ae4445f7c9317a22fe84726fb894c47754f38a7fd150c00fd877024889968750/_data
      等位置
    • 在容器构建时(Dockerfile中的卷[“/database/data”])。每次调用
      docker run
      都将创建一个新卷,即使您删除了该容器,该卷也将保持不变。这可能会造成混淆,因为后续调用将导致创建不同的卷,而这些卷不会被重用
    您可以使用列出命名(第二种情况)卷和未命名(第三种情况)卷

    $ docker volume ls                                                             
    DRIVER              VOLUME NAME                                                             
    local               064593b3e65977097d4d0c8402a6c633f1af69be2937bf118678ab8f97ee9a7e               
    local               4753ad0437d13e54c76d9c34a30a1843396a1866a0cf9237d500fdcca0d78c5f           
    local               8d7a35354f666b2e8a26866a35bbae36bb9601701d4c6b505ab8ce6629f69415               
    local               db48eefe8f189b36107ca9c4eebb792690590ab0ba055e7e4e2c9adfd1765b7e                    
    local               datamysql
    
    通过使用
    docker inspect mycontainer

    {
                    "Type": "volume",
                    "Name": "8d7a35354f666b2e8a26866a35bbae36bb9601701d4c6b505ab8ce6629f69415",
                    "Source": "/media/USBdrive/docker/volumes/8d7a35354f666b2e8a26866a35bbae36bb9601701d4c6b505ab8ce6629f69415/_data",
                    "Destination": "/var/lib/mysql",
                    "Driver": "local",
                    "Mode": "",
                    "RW": true,
                    "Propagation": ""
                },
    
    删除未使用的卷可能很方便(特别是对于第三种情况)