【问题标题】:How to connect to VSCode container locally using ssh?如何使用 ssh 在本地连接到 VSCode 容器?
【发布时间】:2020-12-08 04:45:59
【问题描述】:

使用VSCode Dev Container,我希望能够ssh 从我的容器内到我的容器内(用于测试目的)。

ssh root@localhost

我已经阅读了很多文章和类似的问题,但我无法创建一个最小的功能示例。

我的Dockerfile如下:

FROM ubuntu:18.04

RUN apt-get update && apt-get install -y --no-install-recommends net-tools iputils-ping openssh-client openssh-server 


RUN mkdir /var/run/sshd
RUN echo 'root:screencast' | chpasswd
RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config

# SSH login fix. Otherwise user is kicked off after login
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd

ENV NOTVISIBLE "in users profile"
RUN echo "export VISIBLE=now" >> /etc/profile

EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]

我的devcontainer.json如下:

{
    "name": "Ubuntu",
    "build": {
        "dockerfile": "Dockerfile",
    },
    "settings": {
        "terminal.integrated.shell.linux": "/bin/bash"
    },
    "extensions": [],
    "forwardPorts": [
        22
    ],
    "appPort": 22,
    "runArgs": [
        "--net",
        "host",
        "-p",
        "22:22"
    ]
}

我测试了多种参数组合(forwardPortsappPortEXPOSE 等),但每次都是:

  • ssh 连接被拒绝
  • 我连接到我的主机而不是我的容器

您知道我该如何修改这些文件以便能够从容器的 bash 解释器连接到 ssh 吗?

【问题讨论】:

    标签: docker visual-studio-code ssh dockerfile vscode-remote


    【解决方案1】:

    有几个问题需要解决:

    1. 由于您的主机使用端口 22,您必须使用另一个端口。你可以通过appPort做到这一点:
        "appPort": "2222:22",
    

    此表示法将主机的端口 2222 映射到容器的 22。

    1. runArgsforwardPorts 是多余的。

    2. 您需要添加 "overrideCommand": false 以防止 VSCode 覆盖 Dockerfile 中声明的 CMD

    3. 您在 Dockerfile 中的 sed 不正确,默认配置不包含行 PermitRootLogin prohibit-password 但包含 #PermitRootLogin <some-other-value。将sed 命令更改为:

    RUN sed -i 's/.*PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config
    

    为了方便,这里是修改过的文件:

    Dockerfile

    FROM ubuntu:18.04
    
    RUN apt-get update && apt-get install -y --no-install-recommends net-tools iputils-ping openssh-client openssh-server 
    
    
    RUN mkdir /var/run/sshd
    RUN echo 'root:test' | chpasswd
    RUN sed -i 's/.*PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config
    
    # SSH login fix. Otherwise user is kicked off after login
    RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
    
    ENV NOTVISIBLE "in users profile"
    RUN echo "export VISIBLE=now" >> /etc/profile
    
    EXPOSE 22
    CMD ["/usr/sbin/sshd", "-D"]
    

    devcontainer.json

    {
        "name": "Ubuntu",
        "build": {
            "dockerfile": "Dockerfile",
        },
        "settings": {
            "terminal.integrated.shell.linux": "/bin/bash"
        },
        "extensions": [],
        "appPort": "2222:22",
        "overrideCommand": false
    }
    

    当您运行容器时,您可以使用ssh root@localhost -p 2222 和密码“test”连接到它。

    另外,我不知道您为什么决定使用 VSCode 特定的方式来使用 Docker,也许这样做有充分的理由,但有更好的方法。您可以使用docker-compose 创建测试环境。它是:

    • 有更好的记录;
    • 广泛使用;
    • 受许多 IDE(包括 VSCode)支持。

    看看这个docker-compose.yml

    # Check out this reference https://docs.docker.com/compose/compose-file/
    # for list of available versions, their differences, and the file format in general.
    version: "3.0"
    
    # This is where you declare containers you want to run.
    services:
    
      # This is the name of the service. One cool thing about it is that is will be a DNS name
      # in the networks where this service will be present. So when you need to connect this
      # service from another container you can simply do 'ssh username@ssh-server'.
      ssh-server:
    
        # This is the name of the image to use. In this case I intentionally used a nonexistent name.
        # Because of that when Docker will build the image from the Dockerfile, it will assign this
        # name to the image. This is not required since I've added 'build' property but giving the
        # right name could come handy.
        image: myssh
    
        # This is equivalent to 'build an image from the Dockerfile in current working directory' or
        # 'docker build .'
        build:
          context: .
          dockerfile: Dockerfile
    
        # This maps host's port 2222 to container's 22. This isn't necessary unless you want to connect
        # to this container from outside (e.g. from host or another machine). Containers do not
        # require 'exposure' or any other step to reach one another within one network - they have all
        # ports open. That is why it is called port forwarding or mapping.
        ports:
          - "2222:22"
    
      # Same image as the server but with a different command to execute.
      ssh-client:
        image: myssh
        build:
          context: .
        # Just a loop to run a command every second. Won't work with password, you need a key or some hacks.
        command: bash -c 'while sleep 1; do ssh root@ssh-server ls /; done'
    

    如果将其保存到上面带有Dockerfile 的目录中,则可以使用docker-compose up 运行它。或者你可以将它与VSCode集成:当没有.devcontainer目录并且你点击Reopen in container,你可以选择From 'docker-compose.yml',然后选择你想要的服务之一,它会构建并启动一个容器。它还将创建.devcontainer 目录,其中包含devcontainer.json

    【讨论】:

    • 感谢您的帮助,感谢您使用更有价值的信息编辑您的答案!我以这种方式使用devcontainer 作为对 Docker 的第一次介绍。我一定会仔细看看docker-compose。我还注意到您删除了"runArgs" 中的--net host。事实上,如果它存在,那么 VSCode 在构建容器时会报告错误:Error response from daemon: Container xxx is not running。请您简要解释一下这个论点的问题吗?
    • 我可能不会比文档更好地解释它:If you use the host network mode for a container, that container’s network stack is not isolated from the Docker host (the container shares the host’s networking namespace), and the container does not get its own IP-address allocated. For instance, if you run a container which binds to port 80 and you use host networking, the container’s application is available on port 80 on the host’s IP address. 所以你有冲突,因为你的主机使用端口 22 而你的容器无法绑定它。
    猜你喜欢
    • 1970-01-01
    • 2019-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-30
    • 2021-03-05
    • 2020-11-22
    相关资源
    最近更新 更多