在 docker-compose v3 容器关闭并重新启动后,我很难保留 postgres 数据。这似乎是一个常见问题,但经过大量搜索后我无法找到有效的解决方案。
我的问题与这里类似:如何使用卷将数据保存在 dockerized postgres 数据库中 https://stackoverflow.com/questions/41637505/how-to-persist-data-in-a-dockerized-postgres-database-using-volumes,但该解决方案不起作用 - 所以请不要关闭。我将逐步完成以下所有步骤来重现该问题。
这是我的 docker-compose 文件:
version: "3"
services:
db:
image: postgres:latest
environment:
POSTGRES_DB: zennify
POSTGRES_USER: patientplatypus
POSTGRES_PASSWORD: SUPERSECRETPASSWORD
volumes:
- pgdata:/var/lib/postgresql/data:rw
ports:
- 5432:5432
app:
build: .
command: ["go", "run", "main.go"]
ports:
- 8081:8081
depends_on:
- db
links:
- db
volumes:
pgdata:
这是我启动并写入数据库后的终端输出:
patientplatypus:~/Documents/zennify.me/backend:08:54:03$docker-compose up
Starting backend_db_1 ... done
Starting backend_app_1 ... done
Attaching to backend_db_1, backend_app_1
db_1 | 2018-08-19 13:54:53.661 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
db_1 | 2018-08-19 13:54:53.661 UTC [1] LOG: listening on IPv6 address "::", port 5432
db_1 | 2018-08-19 13:54:53.664 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
db_1 | 2018-08-19 13:54:53.692 UTC [24] LOG: database system was shut down at 2018-08-19 13:54:03 UTC
db_1 | 2018-08-19 13:54:53.712 UTC [1] LOG: database system is ready to accept connections
app_1 | db init successful
app_1 | create_userinfo_table started
app_1 | create_userinfo_table finished
app_1 | inside RegisterUser in Golang
app_1 | here is the users email:
app_1 | %s [email protected] /cdn-cgi/l/email-protection
app_1 | here is the users password:
app_1 | %s ANOTHERSECRETPASSWORD
app_1 | value of randSeq, 7NLHzuVRuTSxYZyNP6MxPqdvS0qy1L6k
app_1 | search_userinfo_table started
app_1 | value of OKtoAdd, %t true
app_1 | last inserted id = 1 //I inserted in database!
app_1 | value of initUserRet, added
我还可以在另一个终端选项卡中连接到 postgres 并验证数据库是否已正确写入psql -h 0.0.0.0 -p 5432 -U patientplatypus zennify
。这是输出userinfo
table:
zennify=# TABLE userinfo
;
email | password | regstring | regbool | uid
-----------------------+--------------------------------------------------------------+----------------------------------+---------+-----
[email protected] /cdn-cgi/l/email-protection | $2a$14$u.mNBrITUJaVjly15BOV9.Q9XmELYRjYQbhEUi8i4vLWtOr9QnXJ6 | r33ik3Jtf0m9U3zBRelFoWyYzpQp7KzR | f | 1
(1 row)
所以写入数据库一次就可以了!
HOWEVER
现在让我们执行以下操作:
$docker-compose stop
backend_app_1 exited with code 2
db_1 | 2018-08-19 13:55:51.585 UTC [1] LOG: received smart shutdown request
db_1 | 2018-08-19 13:55:51.589 UTC [1] LOG: worker process: logical replication launcher (PID 30) exited with exit code 1
db_1 | 2018-08-19 13:55:51.589 UTC [25] LOG: shutting down
db_1 | 2018-08-19 13:55:51.609 UTC [1] LOG: database system is shut down
backend_db_1 exited with code 0
通过阅读有关该主题的其他线程,使用docker-compose stop
相对于docker-compose down
应该保留本地数据库。但是,如果我再次使用docker-compose up
然后,无需向数据库写入新值,只需查询 postgres 中的表,它是空的:
zennify=# TABLE userinfo;
email | password | regstring | regbool | uid
-------+----------+-----------+---------+-----
(0 rows)
我原以为我可能在初始化步骤中覆盖了代码中的表,但我只有(golang 片段):
_, err2 := db.Exec("CREATE TABLE IF NOT EXISTS userinfo(email varchar(40) NOT NULL, password varchar(240) NOT NULL, regString varchar(32) NOT NULL, regBool bool NOT NULL, uid serial NOT NULL);")
当然,如果之前没有创建过表,则应该只创建该表。
有人对出了什么问题有什么建议吗?据我所知,这一定是 docker-compose 的问题,而不是我的代码的问题。谢谢您的帮助!
EDIT:
我研究过使用 docker 版本 2 并遵循这篇文章中显示的格式(Docker compose 不持久化数据 https://stackoverflow.com/questions/47634042/docker-compose-not-persisting-data)通过使用以下组合:
version: "2"
services:
app:
build: .
command: ["go", "run", "main.go"]
ports:
- "8081:8081"
depends_on:
- db
links:
- db
db:
image: postgres:latest
environment:
POSTGRES_DB: zennify
POSTGRES_USER: patientplatypus
POSTGRES_PASSWORD: SUPERSECRETPASSWORD
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data/
volumes:
pgdata: {}
不幸的是,我再次遇到了同样的问题 - 数据可以写入,但在关闭之间不会保留。
编辑编辑:
只是快速说明一下,使用docker-compose up
实例化服务,然后依赖docker-compose stop
and docker-compose start
对数据的持久性没有实质性影响。重新启动后仍然不会持续。
编辑编辑编辑:
我还发现了更多事情。如果您想正确执行 docker 容器以查看数据库的值,您可以执行以下操作:
docker exec -it backend_db_1 psql -U patientplatypus -W zennify
where backend_db_1
是docker容器数据库的名称patientplatypus
是我的用户名和zennify
是数据库容器中数据库的名称。
我也尝试过将网桥添加到 docker-compose 文件,但没有成功,如下所示:
version: "3"
services:
db:
build: ./db
image: postgres:latest
environment:
POSTGRES_USER: patientplatypus
POSTGRES_PASSWORD: SUPERSECRET
POSTGRES_DB: zennify
ports:
- 5432:5432
volumes:
- ./db/pgdata:/var/lib/postgresql/data
networks:
- mynet
app:
build: ./
command: bash -c 'while !</dev/tcp/db/5432; do sleep 5; done; go run main.go'
ports:
- 8081:8081
depends_on:
- db
links:
- db
networks:
- mynet
networks:
mynet:
driver: "bridge"
我当前的工作理论是,无论出于何种原因,我的 golang 容器都将其具有的 postgres 值写入本地存储而不是共享卷,我不知道为什么。这是我对 golang open 命令应该是什么样子的最新想法:
data.InitDB("postgres://patientplatypus:SUPERSECRET@db:5432/zennify/?sslmode=disable")
...
func InitDB(dataSourceName string) {
db, _ := sql.Open(dataSourceName)
...
}
这同样有效,但它不会保留数据。