我想通过 docker-compose 运行一个具有 COLLATE 和 CTYPE 'C' 以及数据库编码 'UTF-8' 的 postgres 容器。但这似乎是不可能的。
这是 docker-compose.yml 上的部分:
database:
image: postgres:latest
volumes:
- db:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: test
LC_COLLATE: C
LC_CTYPE: C
LANG: C.UTF-8
这是日志输出:
The database cluster will be initialized with locales.
The default text search configuration will be set to "english".
COLLATE: C
CTYPE: C
MESSAGES: C.UTF-8
MONETARY: C.UTF-8
NUMERIC: C.UTF-8
TIME: C.UTF-8
The default database encoding has accordingly been set to "SQL_ASCII".
我必须使用 UTF-8 格式的数据库编码,并使用 'C' 格式的 COLLATE 和 CTYPE 格式,并且不是'C.UTF-8',否则依赖的应用程序无法连接。
我在任何文档或其他任何地方都没有找到任何东西。
答案1
你需要将这两部分拼图拼凑在一起:
https://www.postgresql.org/docs/9.5/app-initdb.html
initdb,教您如何将编码信息传递给数据库创建函数。
postgres 官方 Docker 镜像指出你可以将选项传递给 initdb:
https://hub.docker.com/_/postgres
因此,答案可能是这样的:
database:
image: postgres:latest
volumes:
- db:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: test
POSTGRES_INITDB_ARGS: '--encoding=UTF-8 --lc-collate=C --lc-ctype=C'
或者类似的参数。我忽略了 lang 选项,因为这不是手册页(我包含的第一个链接)上的官方“将此标志传递给 postgres”选项。
我的测试没有使用 docker compose 运行它,而是在命令行上使用 -e 选项。然而,这是完全相同的概念;docker compose 中的“环境”在命令行上是 -e。即:
https://docs.docker.com/engine/reference/commandline/run/
--env,-e 设置环境变量
仅设置密码环境的测试#1:
docker run -e POSTGRES_PASSWORD=test postgres:latest
这是默认运行的输出:
postgres@cbf23636dabc:~$ psql
psql (13.4 (Debian 13.4-1.pgdg100+1))
Type "help" for help.
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+----------+------------+------------+-----------------------
postgres | postgres | UTF8 | en_US.utf8 | en_US.utf8 |
template0 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres +
| | | | | postgres=CTc/postgres
测试#2,仅在 CLI 上建议的 docker compose 中设置环境变量如上所示:
docker run -e POSTGRES_PASSWORD=test -e POSTGRES_INITDB_ARGS='--encoding=UTF-8 --lc-collate=C --lc-ctype=C' postgres:latest
然后输出:
postgres@b6b80c876f3e:~$ psql
psql (13.4 (Debian 13.4-1.pgdg100+1))
Type "help" for help.
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+----------+---------+-------+-----------------------
postgres | postgres | UTF8 | C | C |
template0 | postgres | UTF8 | C | C | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | C | C | =c/postgres +
| | | | | postgres=CTc/postgres
还请注意,官方 Postgresql Docker 镜像页面上的部分描述了初始化脚本。您也可以查看这一点。
答案2
我尝试了上述方法,但遇到的另一个问题是,官方 Postgres Docker 映像附带的默认 Debian 基础没有安装任何其他语言。
# locale -a
C
C.UTF-8
en_US.utf8
POSIX
要设置其他语言,例如中文,则需要运行例如localedef -i zh_CN -c -f UTF-8 -A /usr/share/locale/locale.alias zh_CN.UTF-8
。
然后设置环境变量就成功了。
由于这种需要,似乎默认的 Postgres 镜像不能满足所有需求,最好构建一个自定义镜像,如文档中所述在这篇文章中。
FROM postgres
RUN localedef -i zh_CN -c -f UTF-8 -A /usr/share/locale/locale.alias zh_CN.UTF-8
ENV LANG zh_CN.utf8
然后docker build -t your-custom-image-name .
然后,您就可以使用自定义映像来docker-compose.yml
代替官方 postgres 映像,而无需另外设置任何环境变量。
答案3
您实际上可以将构建合并到 docker compose 中:
services:
postgres:
container_name: postgres
image: postgres-de
build: ./pg-docker-config # a Dockerfile must reside in this directory
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PW}
- POSTGRES_DB=${POSTGRES_DB} #optional (specify default database instead of $POSTGRES_DB)
- PGDATA=/var/lib/postgresql/data/pgdata
- POSTGRES_INITDB_ARGS='--locale=de_DE.UTF8'
ports:
- "5432:5432"
# volumes:
# - /postgres/dev:/var/lib/postgresql/data
restart: unless-stopped
Dockerfile./pg-docker-config
如下所示
FROM postgres:latest
RUN localedef -i de_DE -c -f UTF-8 -A /usr/share/locale/locale.alias de_DE.UTF-8
ENV LANG de_DE.utf8
再次运行之前,请确保删除现有的数据库卷...
docker compose down --volumes
...否则您将看到此消息,并且数据库将不是初始化区域设置
PostgreSQL Database directory appears to contain a database; Skipping initialization
现在您只需一个命令即可启动容器:)
docker compose up -d