Как подключиться к Docker по SSH?

89

Я хочу создать следующий поток инфраструктуры:

Как этого добиться с помощью Docker?

Камиль Лелонек
источник

Ответы:

69

Во-первых, вам нужно установить SSH-сервер в образы, которые вы хотите использовать по ssh. Вы можете использовать базовый образ для всего вашего контейнера с установленным ssh-сервером. Затем вам нужно только запустить каждый контейнер, сопоставляющий порт ssh (по умолчанию 22) с портом хоста (удаленный сервер в вашем образе), используя -p <hostPort>:<containerPort>. то есть:

docker run -p 52022:22 container1 
docker run -p 53022:22 container2

Затем, если порты 52022 и 53022 хоста доступны извне, вы можете напрямую подключаться к контейнерам по ssh, используя IP-адрес хоста (удаленный сервер), указав порт в ssh с помощью -p <port>. Т.е.:

ssh -p 52022 myuser@RemoteServer -> SSH в контейнер1

ssh -p 53022 myuser@RemoteServer -> SSH в контейнер2

Хавьер Кортехосо
источник
А как эти порты выставить внешнему миру? Я имею в виду, есть ли возможность настроить без nginx?
Камил Лелонек
2
@squixy: это просто порты на вашем хосте; просто выставляйте их так же, как и для других приложений. Это может просто работать, или вам может потребоваться открыть порты в вашем брандмауэре.
Адриан Муат
Я понимаю, мне просто интересно, как лучше всего сопоставить доменные имена с портами, но я считаю, что NginX - это решение, которое я могу легко реализовать.
Камиль Лелонек
Что такое container1? Когда я выполняю «docker run <name>», <name> интерпретируется как имя изображения, поэтому docker ищет изображение в репозиториях. Мой идентификатор контейнера не работает с запуском докера. Я использую docker start <containerID> для запуска контейнера, но docker start не принимает параметр -p.
mvmn 04
1
Если пользователь Docker - «root», вам нужно будет дать пользователю root пароль через «passwd root». Также я обнаружил, что это работает: docker run -p 52022: 22 container1 service ssh start -D FOREGROUND
CMP
42

Примечание : этот ответ продвигает инструмент, который я написал.

Выбранный здесь ответ предлагает установить SSH-сервер в каждый образ. Концептуально это неправильный подход ( https://docs.docker.com/articles/dockerfile_best-practices/ ).

Я создал контейнерный SSH-сервер, который можно «привязать» к любому работающему контейнеру. Таким образом, вы можете создавать композиции из любого контейнера. Единственное требование - в контейнере должен быть bash.

В следующем примере запускается SSH-сервер, доступный на порту 2222 локального компьютера.

$ docker run -d -p 2222:22 \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e CONTAINER=my-container -e AUTH_MECHANISM=noAuth \
  jeroenpeeters/docker-ssh

$ ssh -p 2222 localhost

Для получения дополнительных указателей и документации см .: https://github.com/jeroenpeeters/docker-ssh

Это не только противоречит идее одного процесса на контейнер, но также является громоздким подходом при использовании образов из Docker Hub, поскольку они часто не содержат (и не должны) содержать SSH-сервер.

Йерун Петерс
источник
6
Это должен быть правильный ответ. Установка SSH-сервера в каждый образ, который вы хотите, идет вразрез с докером. У вас должен быть только один сервис на контейнер и вы должны составлять приложения из сервисов / контейнеров.
babbata 08
2
@JeroenPeeters Я предполагаю, что еще одним предварительным условием должно быть: «Сокет Docker отображается в контейнер, это позволяет контейнеру получить доступ к Docker Engine».
Nam G VU
1
Что такое jeroenpeeters в приведенной выше команде? Это имя пользователя на контейнере?
Практик Патил,
1
@PratikPatil его часть имени изображения. hub.docker.com/r/jeroenpeeters/docker-ssh
Питерс
13

Эти файлы успешно откроют sshd и запустят службу, чтобы вы могли использовать ssh локально. (вы используете Cyberduck, не так ли?)

Dockerfile

FROM swiftdocker/swift
MAINTAINER Nobody

RUN apt-get update && apt-get -y install openssh-server supervisor
RUN mkdir /var/run/sshd
RUN echo 'root:password' | chpasswd
RUN sed -i 's/PermitRootLogin without-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

COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf

EXPOSE 22
CMD ["/usr/bin/supervisord"]

supervisord.conf

[supervisord]
nodaemon=true

[program:sshd]
command=/usr/sbin/sshd -D

для сборки / запуска демона запуска / перехода в оболочку.

docker build -t swift3-ssh .  
docker run -p 2222:22 -i -t swift3-ssh
docker ps # find container id
docker exec -i -t <containerid> /bin/bash

введите описание изображения здесь

Джонпоп
источник
2
Привет, хороший ответ. Подходит мой контейнер, и он предлагает мне войти в систему, но являются ли учетные данные «root» и «password»? Мне кажется, это не работает, но мне нравится ваше решение, и я хочу его использовать.
Jabari Dash
не уверен - у меня возникли проблемы с подключением к порту 22 - убедитесь, что вы используете порт 2222, так как часто на локальном устройстве могут открываться какие-либо объекты, чтобы конфликтовать с этим портом.
johndpope
эта строка ('PermitRootLogin без пароля') в / etc / ssh / sshd_config по умолчанию закомментирована, поэтому используйте вместо нее 's / # PermitRootLogin без пароля / PermitRootLogin yes /'. Возможно, вам также придется использовать «запретить пароль» вместо «без пароля» для Ubuntu 16.04+. Вы можете убедиться, что exec в контейнере, чтобы проверить заранее.
ItsJack
10

Я думаю, это возможно. Вам просто нужно установить SSH-сервер в каждый контейнер и открыть порт на хосте. Основное раздражение будет заключаться в сохранении / запоминании сопоставления порта с контейнером.

Однако я должен задаться вопросом, зачем вам это нужно. SSH'ng в контейнеры должен быть достаточно редким, чтобы не было проблем с ssh для хоста, а затем использовать docker exec для входа в контейнер.

Адриан Муат
источник
Поэтому я хочу моделировать свою среду так, как я создаю контейнер для каждого проекта. Таким образом, у каждого проекта есть своя среда, пользователь, базы данных, версия python / ruby ​​и так далее. Я хочу изолировать проекты без создания нескольких серверов.
Камил Лелонек
1
@squixy; ОК. Обычно контейнеры докеров содержат только один процесс - идиоматически у вас должны быть отдельные контейнеры для mysql, php и apache. Я не уверен, насколько хорошо это сработает для вас.
Адриан Муат
Я знаю, вы знаете лучшее решение для моего случая?
Камил Лелонек
1
@squixy это зависит от многих вещей. Я бы рекомендовал разбить каждый контейнер на несколько контейнеров. Для чего вам нужен ssh? Если это просто обслуживание, почему вы не можете подключиться по ssh к хосту, а затем docker exec? Боюсь, это слишком сложный вопрос, чтобы отвечать в комментариях.
Адриан Муат,
Как пишет Адриан, как только вы освоите Docker, вы поймете, что контейнеры! = Виртуальные машины. Практически (каламбур) нет необходимости получать интерактивный доступ к работающим контейнерам.
mzedeler
8

Создайте образ докера с openssh-serverпредустановленными:

Dockerfile

FROM ubuntu:16.04

RUN apt-get update && apt-get install -y 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"]

Создайте образ, используя:

$ docker build -t eg_sshd .

Запускаем test_sshdконтейнер:

$ docker run -d -P --name test_sshd eg_sshd
$ docker port test_sshd 22

0.0.0.0:49154

Ssh в ваш контейнер:

$ ssh root@192.168.1.2 -p 49154
# The password is ``screencast``.
root@f38c87f2a42d:/#

Источник: https://docs.docker.com/engine/examples/running_ssh_service/#build-an-eg_sshd-image

имя пользователя
источник
Стоит отметить, что для Mac OS X вы можете попробовать ssh root@localhost -p <ssh_host_port>следовать инструкциям здесь
Клаудио Сантос