docker - vscode devcontainers - 为什么构建两个图像?

标签 docker visual-studio-code docker-compose vscode-devcontainer devcontainer

我使用远程容器作为我的开发环境。所以本质上在我的项目中我有一个 Dockerfile、docker-compose.yml 和我的 devcontainer.json,vscode 使用它们来构建、启动和启动到安装了我的代码的容器中。到目前为止效果很好。
问题是,在 Linux 主机上,如果执行 docker ps,我会看到我的单个容器,但如果查看 docker 镜像,会创建两个容器,最后一个是启动的容器。

我的 docker-compose 看起来像这样:


  app:
    container_name: my_app 
    build:
      context: ..
      dockerfile: .devcontainer/Dockerfile
    volumes:
      - ../..:/workspaces:cached

我的 .devcontainer.json 看起来像这样:

    "name": "my_app_service",
    "dockerComposeFile": "docker-compose.yml",
    "service": "app",
    "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
    "customizations": { 
        "vscode": {
            "extensions": ["ms-python.python"]
        },
        "settings": {
            "terminal.integrated.shell.*": "/bin/bash"
        }
    }     

docker ps 显示单个容器正在运行:

container name: my_app
image: vsc-my_proj-64ad9a6809f39eaa523af6a319f22b90b2d1358fe3a8aebc93ac1dfaebf5f22a-uid 

docker images 显示了创建的两个镜像,其名称为:

REPOSITORY: my_app_devcontainer-app 
REPOSITORY: vsc-my_proj-64ad9a6809f39eaa523af6a319f22b90b2d1358fe3a8aebc93ac1dfaebf5f22a-uid

(请注意,上面的“my_proj”部分图像名称来 self 的 vscode 项目文件夹名称。) 我可以删除第一张图片。但我想了解为什么会发生这种情况?看起来不应该——它几乎就像构建发生了两次。 另外,有没有办法使用 docker-compose 指定图像名称,或者在 vscode 中使用 devcontainer.json (我知道如何从 docker-build 命令行参数执行此操作)。

感谢您帮助解决这个问题

最佳答案

我也想知道同样的事情,所以我做了以下事情:

步骤

  1. 我打印了图像历史记录,只打印了显示实际 docker 文件语句的列。请参阅https://docs.docker.com/config/formatting/https://docs.docker.com/engine/reference/commandline/history/
docker image history PUTIMAGE_HASH_HERE_FOR_IMAGE_NOT_ENDING_IN_UID --no-trunc --format "table {{.CreatedBy}}" > image_wo_uid.txt

docker image history PUTIMAGE_HASH_HERE_FOR_IMAGE_WITH_UID_AT_END --no-trunc --format "table {{.CreatedBy}}" > image_uid.txt
  • 然后比较两者: diff image_wo_uid.txt image_uid.txt

  • 这会给你类似的东西(注意:按时间顺序倒序):

  • 1a2,9
    > USER vscode
    > ARG IMAGE_USER
    > RUN |3 REMOTE_USER=vscode NEW_UID=1000 NEW_GID=1000 /bin/sh -c eval $(sed -n "s/${REMOTE_USER}:[^:]*:\([^:]*\):\([^:]*\):[^:]*:\([^:]*\).*/OLD_UID=\1;OLD_GID=\2;HOME_FOLDER=\3/p" /etc/passwd);  eval $(sed -n "s/\([^:]*\):[^:]*:${NEW_UID}:.*/EXISTING_USER=\1/p" /etc/passwd);  eval $(sed -n "s/\([^:]*\):[^:]*:${NEW_GID}:.*/EXISTING_GROUP=\1/p" /etc/group);  if [ -z "$OLD_UID" ]; then   echo "Remote user not found in /etc/passwd ($REMOTE_USER).";  elif [ "$OLD_UID" = "$NEW_UID" -a "$OLD_GID" = "$NEW_GID" ]; then   echo "UIDs and GIDs are the same ($NEW_UID:$NEW_GID).";  elif [ "$OLD_UID" != "$NEW_UID" -a -n "$EXISTING_USER" ]; then   echo "User with UID exists ($EXISTING_USER=$NEW_UID).";  elif [ "$OLD_GID" != "$NEW_GID" -a -n "$EXISTING_GROUP" ]; then   echo "Group with GID exists ($EXISTING_GROUP=$NEW_GID).";  else   echo "Updating UID:GID from $OLD_UID:$OLD_GID to $NEW_UID:$NEW_GID.";   sed -i -e "s/\(${REMOTE_USER}:[^:]*:\)[^:]*:[^:]*/\1${NEW_UID}:${NEW_GID}/" /etc/passwd;   if [ "$OLD_GID" != "$NEW_GID" ]; then    sed -i -e "s/\([^:]*:[^:]*:\)${OLD_GID}:/\1${NEW_GID}:/" /etc/group;   fi;   chown -R $NEW_UID:$NEW_GID $HOME_FOLDER;  fi; # buildkit
    > SHELL [/bin/sh -c]
    > ARG NEW_GID
    > ARG NEW_UID
    > ARG REMOTE_USER
    > USER root
    

    结论

    • 以 uid 结尾的镜像正在采取额外措施来保证 uid 和 guid 均为 1000(请参阅长 RUN 语句)。如果 1000 处已存在另一个用户/组,它有一堆错误处理来输出错误。
    • 我猜测 devcontainer 程序员这样做是因为他们无法确定正在使用什么基本镜像,因此 USER vscode 的 uid/guid 可能不是 1000/1000。

    注释

    • 详细信息可能因 Linux 发行版而异(我认为),但基本上,如果您保证您的用户 ID/组 ID 为 1000 或以上,那么您就处于“非系统用户”(=常规用户)uid 空间。讨论示例:https://ubuntuforums.org/showthread.php?t=1740376
    • 有些人建议改为 10000,而不是 1000,这样可以降低在 1000 范围内遇到现有用户的可能性,这种情况很有可能发生,因为第一个非系统用户将会 如果不采取其他步骤,则为 1000。讨论示例:https://news.ycombinator.com/item?id=25621610
    • 我不确定为什么额外的代码不首先确定 1000 以上的第一个可用 uids/guid 并使用它们而不是 1000,以防万一 1000 已被占用。

    关于docker - vscode devcontainers - 为什么构建两个图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75915194/

    相关文章:

    linux - 为什么一个 linux 命令在容器内运行但在 entrpoint.sh 中不起作用

    docker - 使用 docker 获得 websphere 自由有什么好处?

    docker compose 命令 down 和 up 不会创建新的图像和容器

    visual-studio-code - vscode 总是在启动时打开欢迎屏幕而不是上次打开的文件夹

    spring-boot - 错误 :docker Spring boot container : java. lang.IllegalArgumentException:无法解析值 'CASSANDRA_HOST' 中的占位符 "${CASSANDRA_HOST}"

    hadoop - CoreOS & HDFS - 在 Linux 容器/Docker 中运行分布式文件系统

    c# - 列出 Visual Studio Code (C#) 中的可重写方法

    java - 在基于 Visual Studio Code Maven 的 Java 项目中设置类路径

    windows - docker-compose run 在 Windows 中不起作用

    docker-compose - Docker 组合,重试拉取镜像