我正在尝试在Alpine Linux Docker容器中创建一个具有UID
1340816314
的新用户,以便使具有与主机上的特定用户匹配UID
的用户。
问题是,即使我按照 adduser 手册页重新定义UID_MAX
/etc/login.defs
的值,我也面临着adduser: number 1340816314 is not in 0..256000 range
。顺便说一下,我认为它没有任何影响,因为 Alpine 中的adduser
命令来自 BusyBox。
这是我尝试做的日志:
$ docker run -it --rm alpine:3.4 sh
/ # adduser -D -g '' -u 1340816314 user
adduser: number 1340816314 is not in 0..256000 range
/ # echo "UID_MAX 1340816314" > /etc/login.defs
/ # adduser -D -g '' -u 1340816314 user
adduser: number 1340816314 is not in 0..256000 range
/ # echo "UID_MAX 1340816315" > /etc/login.defs
/ # adduser -D -g '' -u 1340816314 user
adduser: number 1340816314 is not in 0..256000 range
您知道如何在 Docker 容器中添加具有 Alpine Linux 中具有大UID
的用户吗?
对于阿尔卑斯山的高 UID/GID,有一个更优雅的解决方案。
包shadow
包含useradd
和groupadd
实用程序,这些实用程序反过来支持更高的值。不确定这些实用程序的上限是什么,以及是否支持整个 2^32 空间,但我已经测试了超过 6 亿的值并且它可以工作。
例如,实现此目的的命令如下所示:
UID=666000666
GID=999000999
apk add shadow
/usr/sbin/groupadd -g ${GID} my_group
/usr/sbin/useradd -s /bin/sh -g ${GID} -u ${UID} my_user
请注意,我将 shell 变量传递给useradd
因为默认情况下它会尝试使用未安装的/bin/bash
。
这是一个有效但肮脏的解决方法,通过手动创建用户,使用 $UID_TO_SET
作为包含要设置的高UID
的 bash 变量:
# Create user
echo "user:x:$UID_TO_SET:$UID_TO_SET::/home/user:" >> /etc/passwd
## thanks for http://stackoverflow.com/a/1094354/535203 to compute the creation date
echo "user:!:$(($(date +%s) / 60 / 60 / 24)):0:99999:7:::" >> /etc/shadow
echo "user:x:$UID_TO_SET:" >> /etc/group
mkdir /home/user && chown user: /home/user
虽然上面的"肮脏"方法确实有效,但它们很丑陋,对某些人来说不容易使用。复制和粘贴很容易出错。
因此,鉴于这与 Docker 有关,我有更好的方法来使用多阶段构建。
## Busybox adduser doesn't allow UIDs over 60000
## So we'll use a debian image to make the user
## And then copy the files and grep out the new user into the busybox container
FROM debian as base
RUN useradd -D -g '' -u 1340816314 user
FROM alpine as image
COPY --from=base /etc/passwd /root/passwd
RUN grep user /root/passwd >> /etc/passwd && rm -f /root/passwd
USER user
虽然此示例使用 debian,但您可以在第一阶段使用任何您想要的容器映像而不是 Debian。只要容器不会因为您使用的命令中的任意低 UID 限制而出错,它应该没问题,所以我鼓励您使用不同的容器作为基础映像,并检查 useradd
和adduser
命令是否可用,以及哪一个可能支持您需要的 UID 编号。
这个问题实际上启发了我以某种方式解决它,对于获取长 ID 以在基于 Alpine 和 BusyBox 的 Docker 映像上工作的特定用例来说,这既方便又易于使用。
https://github.com/theAkito/userdef
示例用法:
## Get the binary.
## The default Docker Tag provides the Alpine (musl) based binary.
FROM akito13/userdef AS base
## Pull the image you want to modify the executing user of.
FROM gitea/gitea:1.16.5-linux-amd64-rootless
## We temporarily need to use the root user,
## as we are doing administrative tasks, like e.g. modifying an OS user.
USER root:root
COPY --from=base /userdef /userdef
## 1. Change the existing user.
## 2. Use that user to `chown` relevant folders.
## 3. Remove the binary, because the user has been changed,
## i.e. our job is done here.
RUN /userdef -h=/var/lib/gitea/git -n=git -u=9234 -g=9234 &&
chown git:git -R /var/lib/gitea /etc/gitea &&
rm -f /userdef
## Switch to the now relevant executing user.
USER 9234:9234
## Taken from https://github.com/go-gitea/gitea/blob/66f2210feca0b50d305a46a203c2b3d2f4d3790b/Dockerfile.rootless#L71-L72
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
CMD []
阐述 @anthony-o 的唯一工作答案
# FOR UID higher than 60000, users need to be added like this!
RUN export GUID_TO_SET=100 &&
export UID_TO_SET=66666 &&
export USER=youruser &&
echo "${USER}:x:${UID_TO_SET}:${GUID_TO_SET}:Linux User,,,:/home/${USER}:/bin/sh" >> /etc/passwd &&
echo "${USER}:!:$(($(date +%s) / 60 / 60 / 24)):0:99999:7:::" >> /etc/shadow &&
mkdir /home/${USER} &&
chown ${USER}:${GUID_TO_SET} /home/${USER}