我是 PostgreSQL 新手,但我想在 Docker 中运行 PostgreSQL 实例以及与其通信的程序。 我的 dockerfile 看起来像这样:
FROM archlinux:latest
RUN pacman --sync -yu --noconfirm --needed base-devel curl postgresql postgresql-libs jansson
WORKDIR /srv
COPY main3.c /srv/
RUN gcc main3.c -lpq -ljansson -std=c99 -I/usr/include/postgresql
RUN su postgres -c 'initdb --locale=C.UTF-8 --encoding=UTF8 -D /var/lib/postgres/data --data-checksums'
RUN mkdir /run/postgresql
RUN chown postgres: /run/postgresql
RUN su postgres -c 'postgres -D /var/lib/postgres/data' &
EXPOSE 5432
EXPOSE 8000
EXPOSE 45510
CMD ["./a.out"]
然后我用
docker build -t myexample .
构建它并用 docker run -p 127.0.0.1:8000:8000 -e DATABASE_HOST=127.0.0.1 -e DATABASE_PORT=5432 -e DATABASE_NAME=mydb -e DATABASE_USER=ene -e DATABASE_PASSWORD=as_shrimple_as_that myexample
运行它。这些变量必须从外部传递,因为它们对于运行 docker 映像的其他人来说是不同的。
但是,我的输出出现错误:
connection to database failed: connection to server at "127.0.0.1", port 5432 failed: Connection refused
Is the server running on that host and accepting TCP/IP connections?
这是我的一段代码,用于检查数据库连接。
...
char* db_host = getenv("DATABASE_HOST");
char* db_port = getenv("DATABASE_PORT");
char* db_name = getenv("DATABASE_NAME");
char* db_user = getenv("DATABASE_USER");
char* db_password = getenv("DATABASE_PASSWORD");
char conninfo[256];
sprintf(conninfo, "host=%s port=%s dbname=%s user=%s password=%s", db_host, db_port, db_name, db_user, db_password);
PGconn *conn = PQconnectdb(conninfo);
if (PQstatus(conn) != CONNECTION_OK) {
fprintf(stderr, "connection to database failed: %s\n", PQerrorMessage(conn));
PQfinish(conn);
return 1;
}
...
我是否未正确启动 PostgreSQL 服务器,或者 Docker 的某些原因导致它在我的程序启动之前就消失了?
到目前为止我不需要修改数据库 - 我只是希望它能够连接。然后我的程序将提供数据库中的版本数据。
在 Docker 中运行 postgres 的正确方法是使用官方上游镜像在单独的容器中运行它,而不是尝试在与应用程序相同的容器中运行它。
docker compose
文件来管理此操作,尽管这并不是绝对必要的(docker compose
实际上只是 docker run
的包装器,因此您可以使用多个 docker run
命令完成相同的操作 - - 只是不太方便)。
可能看起来像下面这样。您可以将此内容放置在与您的
compose.yaml
相邻的名为 Dockerfile
的文件中:
volumes:
pg_data:
services:
postgres:
image: docker.io/postgres:15
volumes:
- "pg_data:/var/lib/postgresql"
environment:
POSTGRES_USER: ene
POSTGRES_PASSWORD: as_shrimple_as_that
app:
build:
context: .
environment:
DATABASE_HOST: postgres
DATABASE_PORT: 5432
DATABASE_NAME: my_db
DATABASE_USER: ene
DATABASE_PASSWORD: as_shrimple_as_that
您可能会使用
.env
文件来管理环境变量,而不是像我在此处所示的那样将它们包含在撰写文件中。
查看您的 Dockerfile,请注意,这并不符合您的想法:
RUN su postgres -c 'postgres -D /var/lib/postgres/data' &
RUN
命令仅在映像构建过程中运行。由 RUN
启动的进程在隔离环境中运行,并在 RUN
命令完成时终止。从映像启动容器时,这些命令不会执行。