我知道以 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 无法运行?
这是否意味着非 root 无法运行?
事实上,postgres 服务已经以非 root 用户身份运行。
postgres
容器的启动过程有效:
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
也完全可以以非根用户身份启动映像,但在这种情况下,您必须确保必要的目录存在并且具有适当的所有权。在像 Kubernetes/OpenShift 这样的环境中,容器编排系统会在安装卷时为您处理这个问题,但是当使用普通 Docker(或 docker-compose)时,您必须自己处理它。
这是一种方法:
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:
我如何在 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