本文重点探索怎么在 docker 中使用 postgresql,同时体会 volume 的用法。

运行 PostgreSQL 容器

安装 PostgreSQL 镜像:

  1. $ docker pull postgres:alpine

然后新建并运行一个 PostgreSQL 的容器:

  1. $ docker run -d -p 5432:5432 -v postgres-data:/var/lib/postgresql/data `
  2. --name postgres1 postgres:alpine

查看运行状态:

  1. $ docker ps -l

查看日志输出:

  1. $ docker logs postgres1

创建数据库

使用 docker exec 命令在 postgres1 容器中启动一个交互式 Shell:

  1. $ docker exec -it postgres1 sh

在这个 Shell 中,我们使用命令创建一个新的数据库 testdb

  1. $ createdb -U postgres testdb

然后启动 psql ,连接到我们的 testdb 数据库:

  1. $ psql -U postgres testdb

浏览数据库

现在,在 psql 中的让我们运行一些基本命令:

  1. testdb=# \l
  2. testdb=# select version();
  3. testdb=# select current_date;

接下来,让我们来做一些更有趣的事情。我们将创建一个表:

testdb=# CREATE TABLE users (id int, name varchar(80));
CREATE TABLE

查看创建的表:

testdb=# \d
         List of relations
 Schema | Name  | Type  |  Owner
--------+-------+-------+----------
 public | users | table | postgres
(1 row)

testdb=# \d users
                      Table "public.users"
 Column |         Type          | Collation | Nullable | Default
--------+-----------------------+-----------+----------+---------
 id     | integer               |           |          |
 name   | character varying(80) |           |          |

然后我们将在表中插入一行:

testdb=# INSERT INTO users (id, name) VALUES (1, 'Mark');
INSERT 0 1

最后,检查一下:

testdb=# SELECT * FROM users;
 id | name
----+------
  1 | Mark
(1 row)

现在我们可以使用 \q 退出 psql 以及我们的 Shell:

testdb=# \q
$ exit

此时,我们的 postgres1 容器仍然在运行。

卷(volume)数据

下面我们分几种情况看其操作对 volume 数据的影响:

重启(restart)

让我们验证一下,如果我们r重启(或停止 stop 再启用 start )容器,我们将不会丢失数据。

$ docker restart postgres1
$ docker exec -it postgres1 sh

进入 psql 查看数据:

$ psql -U postgres testdb
testdb=# select * from users;
 id | name
----+------
  1 | Mark
(1 row)

可以看到,容器关闭重新启动,卷中数据未丢失。

连接(link)

下面我们换一种方式,从另一个连接的容器进行测试:

$ docker run -it --rm --link postgres1:pg --name client1 postgres:alpine sh

启动 psql ,但连接到另一个容器 postgres1 中:

# psql -U postgres -h pg testdb

现在我们可以在 client1 容器中访问 postgres1 容器中的数据库数据:

testdb=# select * from users;
 id | name
----+------
  1 | Mark
(1 row)

丢弃容器

下面我们停止并删除容器 postgres1 ,看是否影响的存储在 volume 中的数据:

# -f: 强制它删除正在运行的容器
$ docker rm -f postgres1

然后我们查看卷 postgres-data 是否还存在:

$ docker volume inspect postgres-data
[
    {
        "CreatedAt": "2019-09-06T17:28:17Z",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/postgres-data/_data",
        "Name": "postgres-data",
        "Options": null,
        "Scope": "local"
    }
]

现在我们将 postgres-data 重新附加到新容器,看能否正常访问:

$ docker run -d -p 5432:5432 -v postgres-data:/var/lib/postgresql/data --name postgres2 postgres:alpine

然后同上,进入 sh,运行 psql 会话,检查数据库、表和数据:

$ docker exec -it postgres2 sh
# psql -U postgres testdb
testdb=# select * from users;
 id | name
----+------
  1 | Mark
(1 row)

可以看到,volume 中数据存在,并不随容器的变动而改变,可以随时在其他容器中正常使用。若要删除 volumedh 使用 rm 命令,删除前需要对其依赖的容器,或使用 -f 参数:

docker rm -f postgres2
docker volume rm postgres-data

总结

如您所件,Docker 不仅可以让您轻松使用 PostgreSQL,还可以轻松配置 volume,从而可以独立于容器的生命周期管理数据的生命周期。如果愿意,我们还可以直接连接到 5432 端口上的这个 PostgreSQL 容器,并将其用于一些本地开发。

参考