¿Cómo SSH en Docker?

89

Me gustaría crear el siguiente flujo de infraestructura:

¿Cómo se puede lograr eso usando Docker?

Kamil Lelonek
fuente

Respuestas:

69

En primer lugar, debe instalar un servidor SSH en las imágenes en las que desea ssh-into. Puede usar una imagen base para todo su contenedor con el servidor ssh instalado. Entonces solo tiene que ejecutar cada contenedor mapeando el puerto ssh (predeterminado 22) a uno de los puertos del host (servidor remoto en su imagen), usando -p <hostPort>:<containerPort>. es decir:

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

Luego, si se puede acceder a los puertos 52022 y 53022 de los hosts desde el exterior, puede enviar directamente ssh a los contenedores utilizando la ip del host (servidor remoto) especificando el puerto en ssh con -p <port>. Es decir:

ssh -p 52022 myuser@RemoteServer -> SSH al contenedor1

ssh -p 53022 myuser@RemoteServer -> SSH al contenedor2

Javier Cortejoso
fuente
¿Y cómo exponer estos puertos al mundo exterior? Quiero decir, ¿existe la posibilidad de configurarlo sin nginx?
Kamil Lelonek
2
@squixy: son solo puertos en su host; simplemente expóngalos de la misma manera que para otras aplicaciones. Es posible que simplemente funcione o que necesite abrir puertos en su firewall.
Adrian Mouat
Entiendo, me pregunto cuál es la mejor manera de asignar nombres de dominio a puertos, pero creo que NginX es la solución que puedo implementar fácilmente.
Kamil Lelonek
¿Qué es container1? Cuando hago "Docker run <name>", el <name> se interpreta como el nombre de la imagen, por lo que Docker busca una imagen en repositorios. Mi ID de contenedor no funciona con Docker Run. Utilizo "docker start <containerID>" para iniciar el contenedor, pero docker start no acepta el parámetro -p.
mvmn
1
Si el usuario de Docker es "root", entonces deberá darle al usuario root una contraseña a través de "passwd root". También encontré que esto funciona: docker run -p 52022: 22 container1 service ssh start -D FOREGROUND
CMP
42

Aviso : esta respuesta promueve una herramienta que he escrito.

La respuesta seleccionada aquí sugiere instalar un servidor SSH en cada imagen. Conceptualmente, este no es el enfoque correcto ( https://docs.docker.com/articles/dockerfile_best-practices/ ).

He creado un servidor SSH en contenedor que puede 'pegar' a cualquier contenedor en ejecución. De esta forma puedes crear composiciones con cada contenedor. El único requisito es que el contenedor tenga bash.

El siguiente ejemplo iniciaría un servidor SSH expuesto en el puerto 2222 de la máquina local.

$ 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

Para obtener más sugerencias y documentación, consulte: https://github.com/jeroenpeeters/docker-ssh

Esto no solo anula la idea de un proceso por contenedor, sino que también es un enfoque engorroso cuando se utilizan imágenes de Docker Hub, ya que a menudo no contienen (y no deberían) contener un servidor SSH.

Jeroen Peeters
fuente
6
Esta debería ser la respuesta correcta. La instalación del servidor SSH en cada imagen que desee va en contra de la línea de Docker. Debe tener solo un servicio por contenedor y debe componer aplicaciones a partir de servicios / contenedores.
babbata
2
@JeroenPeeters Supongo que otro requisito previo es "El socket de Docker está asignado al contenedor, esto permite que el contenedor acceda al motor de Docker".
Nam G VU
1
¿Qué es 'jeroenpeeters' en el comando anterior? ¿Es un nombre de usuario en el contenedor?
Pratik Patil
1
@PratikPatil es parte del nombre de la imagen. hub.docker.com/r/jeroenpeeters/docker-ssh
Jeroen Peeters
13

Estos archivos abrirán sshd con éxito y ejecutarán el servicio para que pueda ssh in localmente. (estás usando cyberduck ¿no?)

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

para construir / ejecutar start daemon / saltar al shell.

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

ingrese la descripción de la imagen aquí

johndpope
fuente
2
Hola, buena respuesta. Mi contenedor aparece y me pide que inicie sesión, pero ¿las credenciales son "root" y "contraseña"? Eso no parece funcionar para mí, pero me gusta tu solución y quiero usarla.
Jabari Dash
No estoy seguro, tuve problemas para acceder al puerto 22, asegúrese de usar el puerto 2222, ya que a menudo las cosas pueden estar abiertas en el dispositivo local para entrar en conflicto con ese puerto.
johndpope
esta línea ('PermitRootLogin sin contraseña') en / etc / ssh / sshd_config está comentada por defecto, así que use 's / # PermitRootLogin sin contraseña / PermitRootLogin yes /' en su lugar. También puede tener que usar 'prohibir-contraseña' en lugar de 'sin contraseña' para Ubuntu 16.04+. Puede asegurarse de que el ejecutivo ingrese al contenedor para verificar con anticipación.
ItsJack
10

Supongo que es posible. Solo necesita instalar un servidor SSH en cada contenedor y exponer un puerto en el host. La principal molestia sería mantener / recordar el mapeo de puerto a contenedor.

Sin embargo, tengo que preguntarme por qué querrías hacer esto. SSH'ng en contenedores debería ser lo suficientemente raro como para que no sea una molestia enviar ssh al host y luego usar docker exec para ingresar al contenedor.

Adrian Mouat
fuente
Así que quiero modelar mi entorno de la forma en que creo un contenedor por proyecto. Entonces, cada proyecto tiene su propio entorno, usuario, bases de datos, versión de python / ruby, etc. Quiero aislar proyectos sin crear múltiples servidores.
Kamil Lelonek
1
@squixy; Okay. Normalmente, los contenedores de Docker solo contienen un único proceso; idiomáticamente, debería tener contenedores separados para mysql, php y apache. No estoy seguro de qué tan bien te va a funcionar esto.
Adrian Mouat
Lo sé, ¿conoces una mejor solución para mi caso?
Kamil Lelonek
1
@squixy depende de muchas cosas. Recomendaría dividir cada contenedor en varios contenedores. ¿Para qué necesitas ssh? Si es solo mantenimiento, ¿por qué no puede ingresar al host y luego al Docker Exec? Me temo que es una pregunta demasiado grande para responder en un comentario.
Adrian Mouat
Como escribe Adrian, una vez que aprendes a usar Docker, te das cuenta de que los contenedores! = Máquinas virtuales. Prácticamente (juego de palabras) no es necesario obtener acceso interactivo a los contenedores en ejecución.
mzedeler
8

Crea una imagen de Docker con openssh-server preinstalado:

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"]

Construye la imagen usando:

$ docker build -t eg_sshd .

Ejecutar un test_sshdcontenedor:

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

0.0.0.0:49154

Ssh a su contenedor:

$ ssh [email protected] -p 49154
# The password is ``screencast``.
root@f38c87f2a42d:/#

Fuente: https://docs.docker.com/engine/examples/running_ssh_service/#build-an-eg_sshd-image

nombre de usuario
fuente
Vale la pena mencionar que para mac os x puedes intentar ssh root@localhost -p <ssh_host_port>seguir las instrucciones aquí
Claudio Santos