Как подключиться к контейнеру VSCode локально с помощью ssh?

#docker #visual-studio-code #ssh #dockerfile #vscode-remote

#докер #visual-studio-code #ssh #dockerfile #vscode-удаленный

Вопрос:

Используя контейнер VSCode Dev, я хотел бы иметь возможность ssh из моего контейнера входить внутрь моего контейнера (для целей тестирования).

 ssh root@localhost
 

Я прочитал много статей и подобных вопросов, но я не могу создать минимальный функциональный пример.

Мой Dockerfile следующий:

 FROM ubuntu:18.04

RUN apt-get update amp;amp; 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@sessions*requireds*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"
    ]
}
 

Я тестировал несколько комбинаций параметров ( forwardPorts appPort , EXPOSE , и т.д.), Но каждый раз либо:

  • в ssh подключении отказано
  • Я подключаюсь к своему хосту, а не к своему контейнеру

Знаете ли вы, как я могу изменить эти файлы, чтобы иметь возможность подключаться к ssh интерпретатору bash контейнера, пожалуйста?

Ответ №1:

Необходимо решить несколько проблем:

  1. Поскольку ваш хост использует порт 22, вы должны использовать другой порт. Вы можете сделать это с помощью appPort :
     "appPort": "2222:22",
 

Это обозначение сопоставляет порт 2222 хоста с портом 22 контейнера.

  1. runArgs и forwardPorts являются избыточными.
  2. Вам нужно добавить "overrideCommand": false , чтобы предотвратить переопределение VSCode CMD , объявленное в Dockerfile.
  3. Ваш sed in Dockerfile неверен, конфигурация по умолчанию не содержит строки 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 amp;amp; 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@sessions*requireds*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 в нем.

Комментарии:

1. Спасибо за вашу помощь и спасибо за то, что отредактировали ваш ответ с еще более ценной информацией! Я использовал devcontainer этот способ в качестве первого введения в Docker. Я обязательно рассмотрю подробнее docker-compose . Я также заметил, что вы удалили --net host вход "runArgs" . Действительно, если он присутствует, то VSCode сообщает об ошибке при сборке контейнера : Error response from daemon: Container xxx is not running . Не могли бы вы кратко объяснить мне проблему с этим аргументом, пожалуйста?

2. Я, вероятно, не объяснил бы это лучше, чем в документации: 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, а ваш контейнер не смог его привязать.