【问题标题】:Pass multiple arguments to ENTRYPOINT in Dockerfile将多个参数传递给 Dockerfile 中的 ENTRYPOINT
【发布时间】:2021-07-06 08:24:53
【问题描述】:

这是我的 Dockerfile 中定义的入口点:

ENTRYPOINT ["/bin/bash", "-c" , "useradd -r user_test -u 2001 -g 100 && chown -R 2001:100 /home/user_test && su - user_test && mkdir -p /home/user_test/external_user_id"]

我需要将其参数化如下:

ENTRYPOINT ["/bin/bash", "-c" , "useradd -r user_test -u <user_id> -g 100 && chown -R <user_id>:100 /home/user_test && su - user_test && mkdir -p /home/user_test/<external_user_id>"]

其中user_idexternal_user_id 是通过DockerSpawner 配置设置的:

c.DockerSpawner.extra_host_config = {"user_id": "2001", "external_user_id": "id_1234567890"}

如何编辑 Dockerfile 中的入口点?

谢谢

【问题讨论】:

    标签: docker dockerfile docker-entrypoint


    【解决方案1】:

    我建议在这里更改的第一件事是将其拆分为单独的脚本。像这样在单个命令中内联编写的大量代码很难阅读和更新。相反,根据脚本的作用,它可能更容易编辑,如果您需要进行此类更改,甚至可以在 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
    

    如果您查看容器环境(尝试将 idls -l 附加到该 docker run 命令以查看其中一些详细信息),您会看到您以主机用户 ID 身份运行,并且您应该拥有对结果目录的读/写权限,无需在容器启动时进行设置。

    【讨论】:

    • 由于我没有要运行的特定命令,我可以跳过 Dockerfile 中的最后一行 (CMD ???) 吗?
    • 技术上没有要求...但是容器在运行时会做什么?
    • 基本上是 Docker Spawner 所指示的,即启动笔记本服务器。以及 jupuyterhub 配置文件中定义的绑定挂载
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-19
    • 1970-01-01
    • 2018-11-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多