Как вы используете SSH для входа в контейнер Docker? Традиционный подход состоит из двух шагов:
Шаг 1 : подключитесь по SSH к удаленному серверу Linux (если вы запускаете контейнер в удаленной системе).
ssh user_name@server_ip_address
Шаг 2 : Затем вы входите в оболочку вашего запущенного контейнера Docker в интерактивном режиме следующим образом:
docker exec -it container_ID_or_name /bin/bash
При этом вы можете запустить команду Linux или выполнить некоторое обслуживание службы, работающей внутри контейнера.
В описанном выше методе нет ничего плохого. Это традиционный и рекомендуемый способ без труда загружать контейнеры.
Однако, приложив некоторые усилия, вы можете напрямую подключиться к работающему контейнеру по SSH, без предварительного входа в хост-систему.
SSH в контейнер Docker: но почему?
Это немного странно, не правда ли? Вход в контейнер через SSH. Хотя это звучит нетрадиционно, в зависимости от ваших сценариев использования оно может быть вам полезно.
Вот несколько вещей, которых вы можете достичь с помощью SSH в контейнере:
- Вы можете настроить поддельный хост для любого потенциального злоумышленника. Используя нестандартный порт для демона SSH вашего хоста и обслуживая SSH-соединение на порту 22 для злоумышленников.
- Абсолютно отдельный уровень авторизации, то есть пароли для входа или разные ключи ssh – все зависит от вас и отдельно от того, что ваш хост в настоящее время использует.
- Запуск любого автоматизированного удаленного процесса без использования тех же ключей ssh, которые используются для входа в систему сотрудниками вашей команды.
Прежде чем мы покажем вам, как делать все вышеперечисленное, расскажем, как это на самом деле работает.
Настройка доступа SSH для контейнеров Docker [от среднего до эксперта]
Если вас не интересует, как это работает, вы можете игнорировать этот раздел. Мы собираемся показать вам контейнер-пустышку. Вы можете следовать инструкциям на практике.
Запустить контейнер
Во-первых, вам нужно запустить контейнер Docker. В alpine:latest пока будем использовать очень маленькое изображение. Запустите контейнер с помощью этой команды:
docker run --rm --name ssh-test -it -p 22:7655 alpine:latest ash
Некоторые заметные моменты, касающиеся параметров командной строки, следующие:
- С опцией –rm вам не нужно впоследствии явно удалять контейнер.
- Здесь есть параметры -it, позволяющие получить рабочую интерактивную оболочку контейнера.
- Наконец, вы привязываете порт 22 контейнера к номеру порта хоста 7655 (или любому другому номеру порта, который еще не используется демоном SSH в вашей хост-системе). Помните, какой порт вы используете.
Настройте демон SSH в контейнере
Теперь вам нужно установить ssh-сервер внутри контейнера. В Alpine Linux вы можете использовать следующие команды:
apk update; apk add openssh-server
Затем вам нужно быстро изменить параметр конфигурации, чтобы разрешить вход в систему с правами root. Вы можете сделать это вручную, отредактировав файл /etc/ssh/sshd_config или используя эту команду:
sed -E 's/^#(PermitRootLogin )no/\1yes/' /etc/ssh/sshd_config -i
Сгенерируйте ключи хоста с помощью:
ssh-keygen -A
Наконец, запустите ssh-сервер, запустите /usr/sbin/sshd &. Проверьте, не пробегает ли он ps aux.
Установите пароль для учетной записи root вашего контейнера
По умолчанию у корневой учетной записи вашего контейнера нет пароля. Если вы открываете к нему SSH-доступ, вы должны установить пароль для учетной записи root.
Вы можете использовать команду passwd без каких-либо параметров и следовать инструкциям на экране:
passwd
Войдите в контейнер через SSH
С другого хоста попробуйте войти в контейнер сейчас.
ssh root@IP_address_of_host_server -p port_number
Вам не нужна опция -p, если вы ранее были привязаны к порту 22. В качестве IP используйте IP-адрес хост-сервера (а не контейнера).
Когда вы запустите команду, вы должны увидеть результат, подобный этому:
debdut@shinchan:/mnt/data/documents/AndreyEx/container-ssh$ ssh root@domain.com root@domain.com's password: Welcome to Alpine! The Alpine Wiki contains a large amount of how-to guides and general information about administrating Alpine systems. See <http://wiki.alpinelinux.org/>. You can setup the system with the command: setup-alpine You may change this message by editing /etc/motd. c4585d951883:~#
Как это работает?
Это можно лучше понять визуально. Взгляните на следующую диаграмму:
Думайте о контейнерах как о виртуальной машине, порт 22 которой склеен с портом хоста 7655 (или тем, который вы выбрали). Это позволяет вам иметь два разных процесса ssh, запущенных на одном компьютере, привязанных к разным портам.
Допустим, вы используете какой-то другой порт для SSH в хост-системе и склеиваете порт 22 с портом контейнера. Теперь, если кто-то попытается подключиться к хост-серверу, используя SSH-порт по умолчанию 22, окажется в корневой файловой системе контейнера.
Настройка SSH для контейнеров с помощью Docker Compose [экспертные настройки]
Было бы несправедливо, если бы мы оставили вас на этом месте, не предоставив какой-нибудь надежный вариант для контейнера SSH-сервера.
Если вы хотите воспользоваться преимуществом наличия другого изолированного ssh-сервера с отдельной корневой файловой системой, работающей в вашей удаленной системе, это можно было бы сделать, но не следуя предыдущему пошаговому руководству, т.е. установив и настроив sshd на работающей базе контейнера.
Просто потому, что его нелегко воспроизвести, все изменения, которые вы делаете в работающем контейнере, не являются постоянными, перезапуск контейнера и все исчезает.
Итак, здесь мы предлагаем вам гораздо более простой, легко воспроизводимый, настраиваемый способ развертывания контейнера SSH-сервера на вашем удаленном хосте.
Предпосылки
Очевидно, вам необходимо установить docker compose. Здесь необходимы базовые знания о компоновке докеров.
Поскольку вы будете получать доступ к серверу через ключи SSH, вам необходимо добавить открытый ключ SSH вашей локальной системы в каталог вашего хост-сервера Linux, где находится файл docker-compose, и на всякий случай сохранить имя «id_rsa.pub».
Подготовьте файл создания
Предлагаем использовать изображение linuxserver/openssh-server. Это очень легкий образ с достаточно хорошими параметрами конфигурации с помощью переменных среды.
Здесь будет вставлен весь файл композиции. Скопируйте это в какое-нибудь место на вашем сервере и назовите файл docker-compose.yaml.
version: "3.7" services: ssh: image: "linuxserver/openssh-server" ports: - "22:2222" volumes: - "./id_rsa.pub:/pubkey:ro" environment: PUID: ${ID} PGID: ${ID} TZ: ${TZ} PUBLIC_KEY_FILE: "/pubkey" SUDO_ACCESS: "false" PASSWORD_ACCESS: "false" USER_NAME: ${USER_NAME} restart: "always"
Довольно маленький файл для создания текста, не так ли? Позвольте нам объяснить различные части этого файла набора.
Том: у вас есть только одна привязка, которая монтирует открытый ключ в контейнере как pubkey. Он также доступен только для чтения.
Порты: процесс sshd внутри контейнера работает на порту 2222. Вот почему мы привязали этот порт к порту 22 нашего хоста. Измените 22 в соответствии с вашими потребностями, но помните, что он понадобится вам для входа в контейнер через SSH позже.
Переменные среды:
- USER_NAME: пользователь в контейнере, вы будете входить в систему со своего локального компьютера.
- PUID & PGID: UID и GID пользователя USER_NAME. Это необязательно, контейнер автоматически назначит пару идентификаторов без полномочий root, если переменные среды не установлены.
- TZ: Ваш текущий часовой пояс. Вы можете это пройти cat /etc/timezone.
- PUBLIC_KEY_FILE: расположение файла открытого ключа
- SUDO_ACCESS & PASSWORD_ACCESS: Не требует пояснений.
Политика перезапуска: мы установили политику перезапуска «always», которая будет перезапускать контейнер, даже если демон будет перезагружен.
Разверните сервис
Чтобы упростить вам задачу, мы создали сценарий Bash, который задаст вам несколько вопросов и на основе ответа развернет службу.
#! /usr/bin/env bash vars=("ID" "USER_NAME") defaults=("991" "dummy") questions=("Каков был бы ваш предпочтительный UID & GID для имени пользователя по вашему выбору? [default] " "Ваше желаемое имя пользователя для контейнера? [dummy] ") put() { echo "$1" >> .env } for i in {1..0}; do read -p "${questions[$i]}" ans case $ans in ""|"default") put "${vars[$i]}=${defaults[$i]}" ;; *) put "${vars[$i]}=$ans" ;; esac done put "TZ=$(cat /etc/timezone)" docker-compose up -d
Мы сохранили сценарий bash как deploy.sh в том же каталоге, где находился файл docker-compose.
Теперь, если вы запустите этот скрипт, он задаст вам несколько вопросов, а затем запустит контейнер docker:
bash deploy.sh
Как только это будет сделано, попробуйте войти на сервер:
ssh user@ip -p port