我知道可以将 Docker 的--user
选项以特定用户的身份运行容器,但就我而言,我的 Docker 映像内部有一个用户,让我们称该用户为manager
。现在是否可以将该用户映射到主机上的用户?例如,如果主机上有用户john
,我们可以将john
映射到manager
吗?
是的,您可以从主机设置用户,但您应该稍微修改一下 Dockerfile 以处理运行时用户。
FROM alpine:latest
# Override user name at build. If build-arg is not passed, will create user named `default_user`
ARG DOCKER_USER=default_user
# Create a group and user
RUN addgroup -S $DOCKER_USER && adduser -S $DOCKER_USER -G $DOCKER_USER
# Tell docker that all future commands should run as this user
USER $DOCKER_USER
现在,构建 Docker 映像:
docker build --build-arg DOCKER_USER=$(whoami) -t docker_user .
Docker 中的新用户将是主机用户。
docker run --rm docker_user ash -c "whoami"
另一种方法是传递主机用户 ID 和组 ID,而无需在 Dockerfile 中创建用户。
export UID=$(id -u)
export GID=$(id -g)
docker run -it
--user $UID:$GID
--workdir="/home/$USER"
--volume="/etc/group:/etc/group:ro"
--volume="/etc/passwd:/etc/passwd:ro"
--volume="/etc/shadow:/etc/shadow:ro"
alpine ash -c "whoami"
您可以在此处和此处进一步阅读有关 docker 中用户的更多信息。
另一种方法是通过入口点。
Example
这个例子依赖于gosu,gosu存在于最近的Debian衍生产品中,还没有在Alpine 3.13中(但处于边缘(。
您可以按如下方式运行此映像:
docker run --rm -it
--env UID=$(id -u)
--env GID=$(id -g)
-v "$(pwd):$(pwd)" -w "$(pwd)"
imagename
tree
.
├── Dockerfile
└── files/
└── entrypoint
Dockerfile
FROM ...
# [...]
ARG DOCKER_USER=default_user
RUN addgroup "$DOCKER_USER"
&& adduser "$DOCKER_USER" -G "$DOCKER_USER"
RUN wget -O- https://github.com/tianon/gosu/releases/download/1.12/gosu-amd64 |
install /dev/stdin /usr/local/bin/gosu
COPY files /
RUN chmod 0755 /entrypoint
&& sed "s/$DOCKER_USER/$DOCKER_USER/g" -i /entrypoint
ENTRYPOINT ["/entrypoint"]
files/entrypoint
#!/bin/sh
set -e
set -u
: "${UID:=0}"
: "${GID:=${UID}}"
if [ "$#" = 0 ]
then set -- "$(command -v bash 2>/dev/null || command -v sh)" -l
fi
if [ "$UID" != 0 ]
then
usermod -u "$UID" "$DOCKER_USER" 2>/dev/null && {
groupmod -g "$GID" "$DOCKER_USER" 2>/dev/null ||
usermod -a -G "$GID" "$DOCKER_USER"
}
set -- gosu "${UID}:${GID}" "${@}"
fi
exec "$@"
Notes
UID
通常是 bash 中的只读变量,但如果由 docker--env
标志设置,它将按预期工作- 我选择
gosu
因为它很简单,但你可以让它与su
或sudo
一起使用;但是它需要更多的配置 - 如果你不想指定两个
--env
开关,你可以执行以下操作:--env user="$(id -u):$(id -g)"
并在entrypoint
:uid=${user%:*} gid=${user#*:}
; 注意此时UID
变量在 bash 中将是只读的,这就是我切换到小写的原因......改编的其余部分留给读者
没有简单的解决方案可以处理所有用例。解决这些问题是持续的工作,是容器化世界生活的一部分。
没有神奇的参数可以添加到docker exec
或docker run
调用中,并可靠地导致容器化软件在对主机映射卷进行操作期间不再遇到权限问题。除非您的映射目录是 chmod-0777-and-come-what-may (DON'T(,否则您将遇到权限问题,并且您将随时解决它们,这是您应该尝试提高效率的任务,而不是试图找到一个永远不会存在的奇迹般的解决方案。