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

9gm1akwq  于 2023-08-03  发布在  Docker
关注(0)|答案(2)|浏览(124)

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

user: ${CURRENT_UID}

字符串
其中CURRENT_UID为:

export CURRENT_UID=$(id -u):$(id -g)


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

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


运行pg-admin容器时的情况相同,错误消息为:

PermissionError: [Errno 13] Permission denied: '/var/log/pgadmin'


当然,这些错误是有道理的,我不是root,但postgres需要root访问权限。
这是否意味着不可能以非root身份运行?

3b6akqbq

3b6akqbq1#

这是否意味着不可能以非root身份运行?
事实上,postgres服务 * 已经 * 以非root用户的身份运行。postgres容器的启动过程实际上是:
1.创建必要的目录并设置适当的所有权
1.切换到postgres用户
1.启动postgres
因此,如果您启动postgres映像,即使没有指定用户:

docker run -e POSTGRES_PASSWORD=secret postgres:14

字符串
你会发现它以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


也完全可以以非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:

bwitn5fc

bwitn5fc2#

在Kubernetes中如何做到这一点:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: db

spec:
  selector:
    matchLabels:
      app: db

  serviceName: "db"
  template:
    metadata:
      labels:
        app: db
    spec:

      initContainers:
        - name: db-init    # using root, change permissions to not use root in main container
          image: postgres
          command: 
            - 'sh'
            - '-c'
            - |
              chown -R 999:999 /var/lib/postgresql/data
              
          volumeMounts:
            - name:  db
              mountPath: /var/lib/postgresql/data

      containers:
      - name: db
        image: postgres
        securityContext:
          runAsUser: 999  # postgres user in container
          runAsGroup: 999

        envFrom:
          - secretRef:
             name: db-env

        ports:
        - containerPort: 5432
          name: db

        volumeMounts:
        - name: db
          mountPath: /var/lib/postgresql/data

        startupProbe:
          tcpSocket:
            port: db
          initialDelaySeconds: 5
          periodSeconds: 2
          failureThreshold: 15

        readinessProbe:
          exec:
            command:
              - bash 
              - '-c'
              - >
                psql -h localhost -U "${POSTGRES_USER}" -c 'select 1'

          initialDelaySeconds: 5
          periodSeconds: 5
          failureThreshold: 5

        livenessProbe:
          exec:
            command:
              - bash 
              - '-c'
              - >
                psql -h localhost -U "${POSTGRES_USER}" -c 'select 1'

          initialDelaySeconds: 5
          periodSeconds: 10

      volumes:
    
        - name: db
          persistentVolumeClaim:
            claimName: db

字符串

相关问题