非 root 用户运行 Docker 容器和同步主机和容器权限
非 root 用户运行 Docker 容器和同步主机和容器权限
简介
Docker 已成为开发者在可移植、一致的环境中创建、部署和运行应用程序的热门平台。
默认情况下,Docker 容器以 root 用户身份运行,如果容器受到攻击,这可能会带来安全风险。
此外,在主机和 Docker 容器之间共享文件夹时,以 root 用户身份运行可能会出现问题。
为了降低这些风险,我们将讨论如何使用自定义非 root 用户身份运行 Docker 容器,该用户身份与主机 Linux 用户的用户 ID (UID) 和组 ID (GID) 匹配,以确保已挂载文件夹的无缝权限处理。
我们将用ComfyUI代码仓库做案例,演示制作过程。
Dockerfile 添加普通用户
修改dockerfile文件,在构建镜像过程中使用普通用户,假设
- 用户名是 aigc,用户组名 aigc
- UID=1001, GID=1001
注意系统识别判别用户的机制是通过UID和GID,这点记住就好了。 OKAY,继续往下。
添加普通用户aigc
在宿主机和容器内同时创建aigc用户
在Dockerfile文件中添加:
ARG UID=1001
ARG GID=1001
ENV USERNAME=aigc
RUN groupadd -g ${GID} ${USERNAME} && \
useradd -l -u ${UID} -g ${GID} -m -s /bin/bash -N ${USERNAME}
这样操作的目的是:
- 容器内用户和宿主机用户一致(适合挂载卷操作);
- 避免默认 root 用户的安全隐患;
- 默认进入用户 home 目录。
设置目录
在Dockerfile文件中添加:
ENV HOME_DIR=/home/${USERNAME}
ENV APP_DIR=${HOME_DIR}/app
ENV PIP_CACHE_DIR=${HOME_DIR}/.cache/pip
# 创建目录 + 修正权限
RUN mkdir -p ${HOME_DIR} ${PIP_CACHE_DIR} ${APP_DIR} && \
chown -R ${USERNAME}:${USERNAME} ${HOME_DIR} ${APP_DIR}
创建你想要的目录,同时设置权限。
拷贝文件+设置权限
构建镜像时,免不了要拷贝文件
COPY --link --chown=${USERNAME}:${USERNAME} . ${APP_DIR}
RUN chmod -R 755 ${APP_DIR}
COPY 文件时,用 --chown=aigc:aigc 来设置属主
同样要注意,不管是目录还是文件,都要设置权限。
COPY --link 是 Dockerfile 的 BuildKit 扩展功能,它的作用是:
📌 尽可能保留原始文件的硬链接关系(hard link),而不是创建一个新的复制文件。
✅ 简单解释:
通常,COPY 会复制文件的内容,新建一个文件副本。但使用 --link,Docker 会尝试让目标文件 和源文件共用 inode(即硬链接),从而:
- 减少镜像大小;
- 加快构建速度;
- 避免多余复制。
挂在目录
注意权限, 确保在宿主机里面,要挂在的目录权限是在aigc下。
示例 docker-compose.yml 片段:
services:
comfyui:
build: .
image: comfyui:latest
volumes:
- ./data:/data # 映射本地 data 文件夹
user: "aigc:aigc" # 容器进程以 aigc 用户身份运行
关于挂在目录权限问题,有很多方式处理,重点是权限要限制好
把宿主机的权限,锁死在aigc下
sudo chown -R aigc:aigc ./data
整版Dockerfile
FROM python:3.10-slim
# 设置无交互模式,避免 apt 安装过程中的提示卡住;
# 优先安装 wheel 格式的二进制包,加快 pip 安装速度。
ENV DEBIAN_FRONTEND=noninteractive
ENV PIP_PREFER_BINARY=1
ARG UID=1001
ARG GID=1001
ENV USERNAME=aigc
RUN groupadd -g ${GID} ${USERNAME} && \
useradd -l -u ${UID} -g ${GID} -m -s /bin/bash -N ${USERNAME}
ENV HOME_DIR=/home/${USERNAME}
ENV APP_DIR=${HOME_DIR}/app
ENV PIP_CACHE_DIR=${HOME_DIR}/.cache/pip
# 创建目录 + 修正权限
RUN mkdir -p ${HOME_DIR} ${PIP_CACHE_DIR} ${APP_DIR} && \
chown -R ${USERNAME}:${USERNAME} ${HOME_DIR} ${APP_DIR}
# 安装依赖
RUN apt-get update && apt-get install -y \
build-essential \
libpq-dev \
git \
curl \
&& rm -rf /var/lib/apt/lists/*
USER aigc
WORKDIR ${APP_DIR}
# pip 镜像(可选)
RUN pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/
# 克隆代码
RUN --mount=type=cache,target=${PIP_CACHE_DIR} \
git clone https://github.com/comfyanonymous/ComfyUI.git . && \
git checkout master && \
git reset --hard 2f7d8159c32de22c15fbeea7ff9063f2231586bb && \
# 安装依赖
RUN pip install --no-cache-dir -r requirements.txt
# 拷贝脚本并授权
COPY --chown=aigc:aigc ./entrypoint.sh /home/aigc/entrypoint.sh
RUN chmod +x /home/aigc/*.sh
ENV NVIDIA_VISIBLE_DEVICES=all \
PYTHONPATH="${PYTHONPATH}:${PWD}" \
CLI_ARGS=""
# 容器入口定义
ENTRYPOINT ["/home/aigc/entrypoint.sh"]
CMD ["python", "-u", "main.py", "--listen", "--port", "7860" ${CLI_ARGS} ]
entrypoint.sh
#!/bin/sh
#!/bin/bash
set -Eeuo pipefail
# mkdir -vp /data/custom_nodes
declare -A MOUNTS
MOUNTS["${APP_DIR}/.cache"]="/data/.cache"
MOUNTS["${APP_DIR}/input"]="/data/input"
MOUNTS["${APP_DIR}/output"]="/data/output"
MOUNTS["${APP_DIR}/temp"]="/data/temp"
MOUNTS["${APP_DIR}/custom_nodes"]="/data/custom_nodes"
MOUNTS["${APP_DIR}/models"]="/data/models"
MOUNTS["${APP_DIR}/user/default/workflows"]="/data/user/default/workflows"
for to_path in "${!MOUNTS[@]}"; do
set -Eeuo pipefail
from_path="${MOUNTS[${to_path}]}"
rm -rf "${to_path}"
if [ ! -f "$from_path" ]; then
mkdir -vp "$from_path"
fi
mkdir -vp "$(dirname "${to_path}")"
ln -sT "${from_path}" "${to_path}"
echo Mounted $(basename "${from_path}")
done
if [ -f "/data/config/comfy/startup.sh" ]; then
pushd ${APP_DIR}
. /data/config/comfy/startup.sh
popd
fi
exec "$@"
docker-compose.yml
version: '3.8'
services:
comfyui:
build: .
image: comfyui:latest
container_name: comfyui
ports:
- "${WEBUI_PORT:-8188}:7860"
volumes:
- ./data:/data
user: "aigc:aigc" # 容器进程以 aigc 用户身份运行
stop_signal: SIGKILL
tty: true
deploy:
resources:
reservations:
devices:
- driver: nvidia
device_ids: [ '0' ]
capabilities: [ compute, utility ]
environment:
- CLI_ARGS=--port 7860 --disable-cuda-malloc
extra_hosts:
- "raw.githubusercontent.com:185.199.108.133"
宿主机,将aigc添加到docker组
为了让没有sudo权限的aigc执行docker命令,将将aigc添加到docker组
- 添加用户到 docker 组
sudo usermod -aG docker aigc
groups aigc
-aG 表示追加用户到组而不是替换原有组。
- 验证权限是否生效
docker run hello-world
END