Docker PostgreSQL 将数据库编码更改为 UTF-8

Docker PostgreSQL 将数据库编码更改为 UTF-8

我想通过 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

相关内容