Como usar SSH no Docker?

90

Eu gostaria de criar o seguinte fluxo de infraestrutura:

Como isso pode ser feito usando o Docker?

Kamil Lelonek
fonte

Respostas:

70

Primeiramente você precisa instalar um servidor SSH nas imagens que deseja fazer o ssh. Você pode usar uma imagem de base para todo o seu contêiner com o servidor ssh instalado. Então você só precisa executar cada container mapeando a porta ssh (padrão 22) para uma das portas do host (servidor remoto em sua imagem), usando -p <hostPort>:<containerPort>. ie:

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

Então, se as portas 52022 e 53022 do host são acessíveis de fora, você pode fazer ssh diretamente para os contêineres usando o ip do host (servidor remoto) especificando a porta em ssh com -p <port>. Ie:

ssh -p 52022 myuser@RemoteServer -> SSH para o container1

ssh -p 53022 myuser@RemoteServer -> SSH para o container2

Javier Cortejoso
fonte
E como expor essas portas para o mundo exterior? Quer dizer, se houver a possibilidade de configurá-lo sem nginx?
Kamil Lelonek
2
@squixy: eles são apenas portas em seu host; apenas exponha-os da mesma maneira que para outros aplicativos. Pode funcionar ou pode ser necessário abrir portas no firewall.
Adrian Mouat
Eu entendo, só me pergunto qual é a melhor maneira de mapear nomes de domínio para portas, mas acredito que NginX é a solução que posso implementar facilmente.
Kamil Lelonek
O que é container1? Quando eu faço "docker run <name>", o <name> é interpretado como nome de imagem, então o docker procura uma imagem nos repositórios. Meu ID de contêiner não funciona com docker run. Eu uso "docker start <containerID>" para iniciar o contêiner, mas o docker start não aceita o parâmetro -p.
mvmn
1
Se o usuário do Docker for "root", você precisará fornecer ao usuário root uma senha por meio de "passwd root". Também descobri que isso funciona: docker run -p 52022: 22 container1 service ssh start -D FOREGROUND
CMP
42

Aviso : esta resposta promove uma ferramenta que escrevi.

A resposta selecionada aqui sugere instalar um servidor SSH em cada imagem. Conceitualmente, essa não é a abordagem certa ( https://docs.docker.com/articles/dockerfile_best-practices/ ).

Eu criei um servidor SSH em contêiner que você pode "colar" em qualquer contêiner em execução. Desta forma, você pode criar composições com todos os contêineres. O único requisito é que o contêiner tenha bash.

O exemplo a seguir iniciaria um servidor SSH exposto na porta 2222 da 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 obter mais dicas e documentação, consulte: https://github.com/jeroenpeeters/docker-ssh

Isso não apenas derrota a ideia de um processo por contêiner, mas também é uma abordagem complicada ao usar imagens do Docker Hub, pois muitas vezes não (e não deveriam) conter um servidor SSH.

Jeroen Peeters
fonte
6
Esta deve ser a resposta correta. Instalar o servidor SSH em todas as imagens que você deseja vai contra a tendência do docker. Você deve ter apenas um serviço por contêiner e deve compor aplicativos de serviços / contêineres.
babbata,
2
@JeroenPeeters Acho que outro pré-requisito é "O soquete do Docker está mapeado no contêiner, isso permite que o contêiner acesse o mecanismo do Docker."
Nam G VU
1
O que é 'jeroenpeeters' no comando acima? É um nome de usuário no contêiner?
Pratik Patil de
1
@PratikPatil faz parte do nome da imagem. hub.docker.com/r/jeroenpeeters/docker-ssh
Jeroen Peeters de
13

Esses arquivos abrirão o sshd com sucesso e executarão o serviço para que você possa ssh localmente. (você está usando o cyberduck, não está?)

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 / executar iniciar daemon / saltar para o 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

insira a descrição da imagem aqui

johndpope
fonte
2
Ei, boa resposta. Meu contêiner aparece e me pede para fazer login, mas as credenciais são "root" e "senha"? Isso não parece funcionar para mim, mas gosto da sua solução e quero usá-la.
Jabari Dash,
não tenho certeza - tive problemas para acessar a porta 22 - certifique-se de usar a porta 2222, pois muitas vezes as coisas podem ser abertas no dispositivo local para entrar em conflito com essa porta.
johndpope
esta linha ('PermitRootLogin sem senha') em / etc / ssh / sshd_config é comentada por padrão, então use 's / # PermitRootLogin sem senha / PermitRootLogin yes /' ao invés. Você também pode ter que usar 'proibir senha' em vez de 'sem senha' para Ubuntu 16.04+. Você pode garantir que o exec no contêiner seja verificado com antecedência.
ItsJack
10

Eu acho que é possível. Você só precisa instalar um servidor SSH em cada contêiner e expor uma porta no host. O principal incômodo seria manter / lembrar o mapeamento do porto ao contêiner.

No entanto, tenho que questionar por que você deseja fazer isso. O SSH'ng em contêineres deve ser raro o suficiente para que não seja um incômodo fazer o ssh para o host e depois usar o docker exec para entrar no contêiner.

Adrian Mouat
fonte
Portanto, quero modelar meu ambiente da maneira como crio um contêiner por projeto. Portanto, cada projeto tem seu próprio ambiente, usuário, bancos de dados, versão python / ruby ​​e assim por diante. Quero isolar projetos sem criar vários servidores.
Kamil Lelonek
1
@squixy; Está bem. Normalmente os contêineres do docker mantêm apenas um único processo - linguisticamente, você deve ter contêineres separados para mysql, php e apache. Não tenho certeza de como isso vai funcionar para você.
Adrian Mouat
Eu sei, você conhece melhor solução para o meu caso?
Kamil Lelonek
1
@squixy depende de muitas coisas. Eu recomendaria quebrar cada recipiente em vários recipientes. Para que você precisa do ssh? Se for apenas manutenção, por que você não pode fazer SSH no host e no docker exec? É uma pergunta muito grande para responder em um comentário que receio.
Adrian Mouat
Como Adrian escreve, quando você pega o jeito de usar o Docker, percebe que contêineres! = Máquinas virtuais. Não há virtualmente (trocadilho intencional) necessidade de obter acesso interativo aos contêineres em execução.
mzedeler
8

Crie uma imagem docker com openssh-serverpré-instalado:

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

Construa a imagem usando:

$ docker build -t eg_sshd .

Execute um test_sshdcontêiner:

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

0.0.0.0:49154

Ssh para seu contêiner:

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

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

nome do usuário
fonte
Vale ressaltar que para mac os x você pode tentar ssh root@localhost -p <ssh_host_port>seguir as instruções aqui
Claudio Santos