如何以非root用户身份在docker中运行postgres?

sco*_*t_m 7 postgresql docker

我知道以 root 身份运行 docker 容器并不安全,所以我想改变它们的运行方式。我有一个运行 postgres 的容器,到目前为止它是以 root 身份运行的(默认)。但是,当我将这一行添加到我的docker-compose文件中时:

user: ${CURRENT_UID}
Run Code Online (Sandbox Code Playgroud)

哪里CURRENT_UID

export CURRENT_UID=$(id -u):$(id -g)
Run Code Online (Sandbox Code Playgroud)

我在容器日志中收到以下错误:

initdb: error: could not change permissions of directory "/var/lib/postgresql/data": Operation not permitted

fixing permissions on existing directory /var/lib/postgresql/data ... chmod: changing permissions of '/var/lib/postgresql/data': Operation not permitted

chmod: changing permissions of '/var/run/postgresql': Operation not permitted
Run Code Online (Sandbox Code Playgroud)

运行容器时情况也是一样pg-admin,报错信息:

PermissionError: [Errno 13] Permission denied: '/var/log/pgadmin'
Run Code Online (Sandbox Code Playgroud)

这些错误当然是有道理的,我不是 root,但 postgres 需要 root 访问权限。

这是否意味着无法以非 root 身份运行?

lar*_*sks 9

这是否意味着无法以非 root 身份运行?

事实上,postgres 服务已经以非 root 用户身份运行。容器的启动过程postgres实际上是:

  1. 创建必要的目录并设置适当的所有权
  2. 切换到postgres用户
  3. 启动postgres

因此,如果您启动postgres图像,即使没有指定用户:

docker run -e POSTGRES_PASSWORD=secret postgres:14
Run Code Online (Sandbox Code Playgroud)

你会发现它正在以postgres用户身份运行:

# ps -fe
UID          PID    PPID  C STIME TTY          TIME CMD
postgres       1       0  0 16:11 ?        00:00:00 postgres
postgres      56       1  0 16:11 ?        00:00:00 postgres: checkpointer
postgres      57       1  0 16:11 ?        00:00:00 postgres: background writer
postgres      58       1  0 16:11 ?        00:00:00 postgres: walwriter
postgres      59       1  0 16:11 ?        00:00:00 postgres: autovacuum launcher
postgres      60       1  0 16:11 ?        00:00:00 postgres: stats collector
postgres      61       1  0 16:11 ?        00:00:00 postgres: logical replication launcher
Run Code Online (Sandbox Code Playgroud)

也完全可以以非 root 用户身份启动映像,但在这种情况下,您必须确保必要的目录存在具有适当的所有权。在像 Kubernetes/OpenShift 这样的环境中,容器编排系统会在安装卷时为您处理这个问题,但是当使用普通 Docker(或 docker-compose)时,您必须自己处理它。

这是一种方法:

  • 让“初始化容器”负责设置卷权限
  • 仅在初始化容器完成后启动 postgres
version: "3.9"

services:
  postgres-init:
    image: postgres:14
    volumes:
      - "postgres_data:/data"
    entrypoint:
      - sh
      - -c
      - |
        chown -R 2000:2000 /data

  postgres:
    depends_on:
      postgres-init:
        condition: service_completed_successfully

    image: postgres:14
    environment:
      POSTGRES_PASSWORD: "secret"
      PGDATA: /pgdata
    volumes:
      - "postgres_data:/pgdata"
    user: "2000"

volumes:
  postgres_data:
Run Code Online (Sandbox Code Playgroud)