我建议在这里更改的第一件事是将其拆分为单独的脚本。像这样在单个命令中内联编写的大量代码很难阅读和更新。相反,根据脚本的作用,它可能更容易编辑,如果您需要进行此类更改,甚至可以在 Docker 之外运行它。
COPY entrypoint.sh . # should be executable on the host
# For this standard use, ENTRYPOINT _must_ be JSON-array form.
# Do not use an explicit "bash" invocation generally.
ENTRYPOINT ["./entrypoint.sh"]
# Specify the actual command to run
CMD ???
当脚本运行时,it gets passed the CMD as additional arguments,因此您可以在此处使用您喜欢的任何配置机制。调用 getopt(1) 是可能的,如果有点不寻常的话;使用环境变量进行这样的简单配置更为常见。
#!/bin/sh
# Do the setup things from the original ENTRYPOINT line:
# Create the user, using the uid from the environment variable, or
# the default from the first line
useradd -r user_test -u "${USER_ID:-2001}" -g 100
# Change directory ownership, using the newly created user name
chown -R user_test:100 /home/user_test
# Do nothing, but proceed to the next line continuing to run as root
su - user_test
# Create another directory
mkdir -p "/home/user_test/${EXTERNAL_USER_ID:-external_user_id}"
# Run the main container CMD
exec "$@"
您还需要在启动容器时传入环境变量:
c.DockerSpawner.extra_host_config = {"user_id": "2001", "external_user_id": "id_1234567890"}
c.DockerSpawner.environment = {"USER_ID": "2001", "EXTERNAL_USER_ID": "id_1234567890"}
我实际上要做的是删除所有这些代码。传递 user_id 设置应该会导致 Docker 使用该数字用户 ID 运行。用户没有特别需要“存在”;在大多数情况下,如果用户 2001 未在容器的 /etc/passwd 文件中列出,则不会发生任何不良情况。当您尝试按原样运行此程序时,您可能还会发现权限问题,因为在入口点脚本开始运行时您已经不是 root。
如果您像在此处所做的那样配置用户 ID,并将主机目录绑定到具有适当权限的容器中,则容器将能够读取和写入目录而无需任何特殊设置。从上下文来看,我猜您希望该目录是从主机绑定挂载的(否则特定的 uid 根本不重要),在这种情况下,您可以提前创建输出目录。
我会用简单的docker run 语法写:
docker run \
--rm \ # clean up container when done
-u $(id -u) \ # with the current host uid
-v "$PWD/id_1234567890:/result" \ # mounting the result directory
-w /result \ # working in that directory
image-name:tag
如果您查看容器环境(尝试将 id 或 ls -l 附加到该 docker run 命令以查看其中一些详细信息),您会看到您以主机用户 ID 身份运行,并且您应该拥有对结果目录的读/写权限,无需在容器启动时进行设置。