Comment SSH dans Docker?

89

Je souhaite créer le flux d'infrastructure suivant:

Comment cela peut-il être réalisé avec Docker?

Kamil Lelonek
la source

Réponses:

69

Tout d'abord, vous devez installer un serveur SSH dans les images dans lesquelles vous souhaitez ssh-into. Vous pouvez utiliser une image de base pour tous vos conteneurs avec le serveur ssh installé. Ensuite, il vous suffit d'exécuter chaque conteneur mappant le port ssh (par défaut 22) à l'un des ports de l'hôte (serveur distant dans votre image), en utilisant -p <hostPort>:<containerPort>. c'est à dire:

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

Ensuite, si les ports 52022 et 53022 de l'hôte sont accessibles de l'extérieur, vous pouvez directement ssh vers les conteneurs en utilisant l'adresse IP de l'hôte (serveur distant) en spécifiant le port dans ssh avec -p <port>. C'est à dire:

ssh -p 52022 myuser@RemoteServer -> SSH vers container1

ssh -p 53022 myuser@RemoteServer -> SSH vers container2

Javier Cortejoso
la source
Et comment exposer ces ports au monde extérieur? Je veux dire s'il y a une possibilité de le configurer sans nginx?
Kamil Lelonek
2
@squixy: ce ne sont que des ports sur votre hôte; exposez-les simplement de la même manière que pour les autres applications. Cela peut simplement fonctionner ou vous devrez peut-être ouvrir des ports dans votre pare-feu.
Adrian Mouat
Je comprends cela, je me demande simplement quelle est la meilleure façon de mapper les noms de domaine aux ports, mais je crois que NginX est la solution que je peux facilement mettre en œuvre.
Kamil Lelonek
Qu'est-ce que container1? Quand je fais "docker run <nom>", le <nom> est interprété comme un nom d'image, donc docker recherche une image dans les dépôts. Mon ID de conteneur ne fonctionne pas avec docker run. J'utilise "docker start <containerID>" pour démarrer le conteneur, mais docker start n'accepte pas le paramètre -p.
mvmn
1
Si l'utilisateur Docker est "root", vous devrez donner un mot de passe à l'utilisateur root via "passwd root". J'ai aussi trouvé que cela fonctionne: docker run -p 52022: 22 container1 service ssh start -D FOREGROUND
CMP
42

Remarque : cette réponse fait la promotion d'un outil que j'ai écrit.

La réponse sélectionnée ici suggère d'installer un serveur SSH dans chaque image. Conceptuellement, ce n'est pas la bonne approche ( https://docs.docker.com/articles/dockerfile_best-practices/ ).

J'ai créé un serveur SSH conteneurisé que vous pouvez «coller» à n'importe quel conteneur en cours d'exécution. De cette façon, vous pouvez créer des compositions avec chaque conteneur. La seule exigence est que le conteneur ait bash.

L'exemple suivant démarrerait un serveur SSH exposé sur le port 2222 de la machine locale.

$ 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

Pour plus de pointeurs et de documentation, voir: https://github.com/jeroenpeeters/docker-ssh

Non seulement cela va à l'encontre de l'idée d'un processus par conteneur, mais c'est également une approche lourde lors de l'utilisation d'images du Docker Hub car elles ne contiennent souvent pas (et ne devraient pas) contenir de serveur SSH.

Jeroen Peeters
la source
6
Cela devrait être la bonne réponse. L'installation du serveur SSH dans chaque image que vous voulez va à l'encontre du grain de docker. Vous ne devez avoir qu'un seul service par conteneur et vous devez composer des applications à partir de services / conteneurs.
babbata
2
@JeroenPeeters Je suppose qu'une autre condition préalable est "Le socket Docker est mappé dans le conteneur, cela permet au conteneur d'accéder au moteur Docker."
Nam G VU
1
Qu'est-ce que «jeroenpeeters» dans la commande ci-dessus? S'agit-il d'un nom d'utilisateur sur le conteneur?
Pratik Patil
1
@PratikPatil fait partie du nom de l'image. hub.docker.com/r/jeroenpeeters/docker-ssh
Jeroen Peeters
13

Ces fichiers ouvriront avec succès sshd et exécuteront le service afin que vous puissiez ssh localement. (vous utilisez cyberduck n'est-ce pas?)

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

pour construire / exécuter le démon de démarrage / sauter dans le 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

entrez la description de l'image ici

johndpope
la source
2
Hé, belle réponse. Mon conteneur apparaît et il m'invite à me connecter, mais les informations d'identification sont-elles "root" et "password"? Cela ne semble pas fonctionner pour moi, mais j'aime votre solution et je veux l'utiliser.
Jabari Dash
pas sûr - j'ai rencontré des problèmes pour atteindre le port 22 - assurez-vous d'utiliser le port 2222 car souvent des choses pourraient être ouvertes sur un périphérique local pour entrer en conflit avec ce port.
johndpope
cette ligne ('PermitRootLogin sans-mot de passe') dans / etc / ssh / sshd_config est commentée par défaut, alors utilisez à la place 's / # PermitRootLogin sans-mot de passe / PermitRootLogin yes /'. Vous devrez peut-être également utiliser «interdit-mot de passe» au lieu de «sans mot de passe» pour Ubuntu 16.04+. Vous pouvez vous assurer de l'exécuter dans le conteneur pour vérifier à l'avance.
ItsJack
10

Je suppose que c'est possible. Il vous suffit d'installer un serveur SSH dans chaque conteneur et d'exposer un port sur l'hôte. Le principal inconvénient serait de maintenir / se souvenir de la cartographie du port au conteneur.

Cependant, je dois me demander pourquoi vous voudriez faire cela. SSH'ng dans les conteneurs devrait être suffisamment rare pour que ce ne soit pas un problème de ssh vers l'hôte, puis d'utiliser docker exec pour entrer dans le conteneur.

Adrian Mouat
la source
Je souhaite donc modéliser mon environnement comme je crée un conteneur par projet. Ainsi, chaque projet a son propre environnement, son utilisateur, ses bases de données, sa version python / ruby ​​et ainsi de suite. Je souhaite isoler des projets sans créer plusieurs serveurs.
Kamil Lelonek
1
@squixy; D'accord. Normalement, les conteneurs docker ne contiennent qu'un seul processus - idiomatiquement, vous devriez avoir des conteneurs séparés pour mysql, php et apache. Je ne sais pas si cela va fonctionner pour vous.
Adrian Mouat
Je sais, connaissez-vous une meilleure solution pour mon cas?
Kamil Lelonek
1
@squixy cela dépend de beaucoup de choses. Je recommanderais de diviser chaque conteneur en plusieurs conteneurs. Pourquoi avez-vous besoin de ssh? S'il ne s'agit que de maintenance, pourquoi ne pouvez-vous pas ssh dans l'hôte puis docker exec? C'est une question trop grande pour répondre dans un commentaire, j'en ai peur.
Adrian Mouat
Comme l'écrit Adrian, une fois que vous maîtrisez l'utilisation de Docker, vous réalisez que les conteneurs! = Machines virtuelles. Il n'y a pratiquement pas (jeu de mots) nécessaire pour obtenir un accès interactif aux conteneurs en cours d'exécution.
mzedeler
8

Créer une image docker avec openssh-server préinstallé:

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

Construisez l'image en utilisant:

$ docker build -t eg_sshd .

Exécutez un test_sshdconteneur:

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

0.0.0.0:49154

Ssh dans votre conteneur:

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

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

Nom d'utilisateur
la source
Il vaut la peine de mentionner que pour mac os x, vous pouvez essayer de ssh root@localhost -p <ssh_host_port>suivre les instructions ici
Claudio Santos