95

I'd like to create the following infrastructure flow:

How can that be achieved using Docker?

Kamil Lelonek
  • 13,631
  • 10
  • 60
  • 87

6 Answers6

73

Firstly you need to install a SSH server in the images you wish to ssh-into. You can use a base image for all your container with the ssh server installed. Then you only have to run each container mapping the ssh port (default 22) to one to the host's ports (Remote Server in your image), using -p <hostPort>:<containerPort>. i.e:

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

Then, if ports 52022 and 53022 of host's are accessible from outside, you can directly ssh to the containers using the ip of the host (Remote Server) specifying the port in ssh with -p <port>. I.e.:

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

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

Javier Cortejoso
  • 8,068
  • 3
  • 24
  • 27
  • And how to expose these ports to the outside world? I mean if there's a possibility to configure it without nginx? – Kamil Lelonek Jan 25 '15 at 11:45
  • 2
    @squixy: they are just ports on your host; just expose them in the same way as for other applications. It may just work, or you might need to open ports in your firewall. – Adrian Mouat Jan 25 '15 at 13:33
  • I get that, I just wonder what is the best way to map domain names to ports, but I believe that NginX is the solution I can easily implement. – Kamil Lelonek Jan 25 '15 at 16:37
  • What is container1? When I do "docker run " the is being interpreted as image name, so docker looks for an image in repos. My container ID doesn't work with docker run. I use "docker start " to start container, but docker start does not accept -p parameter. – mvmn Nov 04 '16 at 12:01
  • @JavierCortejoso Is it possible to SSH connect to the container via normal way i.e. its local IP and port 22? – Nam G VU Jul 03 '17 at 04:24
  • then what is the user and password? are they the same as host machine? – aaron Mar 07 '18 at 07:38
  • Same question about "myuser". In case of ubuntu is it a user created in process? What if IP is dynamic? Can I connect by host name? – Eugene May 03 '18 at 06:07
  • 1
    If the Docker user is "root" then you will need to give user root a password via "passwd root". Also I found this works: docker run -p 52022:22 container1 service ssh start -D FOREGROUND – CMP May 29 '18 at 20:23
  • Successfully created docker. But when I set password in container using `passwd`. I cannot log using ssh – Elbek Jan 31 '20 at 08:26
44

Notice: this answer promotes a tool I've written.

The selected answer here suggests to install an SSH server into every image. Conceptually this is not the right approach (https://docs.docker.com/articles/dockerfile_best-practices/).

I've created a containerized SSH server that you can 'stick' to any running container. This way you can create compositions with every container. The only requirement is that the container has bash.

The following example would start an SSH server exposed on port 2222 of the local machine.

$ 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

For more pointers and documentation see: https://github.com/jeroenpeeters/docker-ssh

Not only does this defeat the idea of one process per container, it is also a cumbersome approach when using images from the Docker Hub since they often don't (and shouldn't) contain an SSH server.

Mark Kahn
  • 81,115
  • 25
  • 161
  • 212
Jeroen Peeters
  • 1,854
  • 1
  • 20
  • 23
  • 7
    This should be the correct answer. Installing SSH server into every image you want goes against the grain of docker. You should have only one service per container and should be composing applications from services/containers. – babbata Oct 08 '15 at 08:02
  • 2
    @JeroenPeeters I guess another prerequisite to be "The Docker socket is mapped into the container, this lets the container access the Docker Engine." – Nam G VU Jul 04 '17 at 01:39
  • 1
    What is 'jeroenpeeters' in the above command? Is it a username on the container? – Pratik Patil Aug 14 '18 at 12:00
  • 1
    @PratikPatil its part of the image name. https://hub.docker.com/r/jeroenpeeters/docker-ssh/ – Jeroen Peeters Aug 15 '18 at 19:13
13

These files will successfully open sshd and run service so you can ssh in locally. (you are using cyberduck aren't you?)

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

to build / run start daemon / jump into 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

enter image description here

johndpope
  • 4,223
  • 2
  • 33
  • 37
  • 2
    Hey, nice answer. My container comes up and it prompts me to log in, but are the credentials "root" and "password" ? That doesn't seem to work for me, but I like your solution, and I want to use it. – Jabari Dash Apr 06 '18 at 02:40
  • not sure - I ran into trouble hitting port 22 - make sure you use port 2222 as often things could be open on local device to conflict with that port. – johndpope May 07 '18 at 19:25
  • this line('PermitRootLogin without-password') in /etc/ssh/sshd_config is comment out by default, so use 's/#PermitRootLogin without-password/PermitRootLogin yes/' instead. You may also have to use 'prohibit-password' instead of 'without-password' for Ubuntu 16.04+. You can sure exec into container to check in advance. – ItsJack Oct 29 '19 at 04:59
10

I guess it is possible. You just need to install a SSH server in each container and expose a port on the host. The main annoyance would be maintaining/remembering the mapping of port to container.

However, I have to question why you'd want to do this. SSH'ng into containers should be rare enough that it's not a hassle to ssh to the host then use docker exec to get into the container.

Adrian Mouat
  • 38,986
  • 15
  • 98
  • 99
  • So I want to model my environment in the way I create container per project. So each project has it own environment, user, databases, python/ruby version and so on. I want to isolate projects without creating multiple server. – Kamil Lelonek Jan 25 '15 at 11:41
  • 1
    @squixy; ok. Normally docker containers only hold a single process - idiomatically you should have separate containers for mysql, php and apache. I'm not sure how well this is going to work out for you. – Adrian Mouat Jan 25 '15 at 13:34
  • I know, do you know better solution for my case? – Kamil Lelonek Jan 25 '15 at 16:36
  • 1
    @squixy it depends on a lot of things. I would recommend breaking each container into multiple containers. What do you need ssh for? If it's just maintenance, why can't you ssh into the host then docker exec? It's too big a question to answer in a comment I'm afraid. – Adrian Mouat Jan 25 '15 at 21:21
  • As Adrian writes, once you get the hang of using Docker, you realize that containers != virtual machines. There is virtually (pun intended) no need to get interactive access to running containers. – mzedeler Jan 25 '15 at 21:28
  • I see. I'm not sure if I really need docker here, but regular VMs in my case. – Kamil Lelonek Jan 25 '15 at 21:39
  • A typical (and legit) use case of ssh in a docker container: remote debugging. Also this post might worth reading: [If you run SSHD in your Docker containers, you're doing it wrong!](http://jpetazzo.github.io/2014/06/23/docker-ssh-considered-evil/) – Anto Feb 24 '15 at 12:28
8

Create docker image with openssh-server preinstalled:

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

Build the image using:

$ docker build -t eg_sshd .

Run a test_sshd container:

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

0.0.0.0:49154

Ssh to your container:

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

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

username
  • 419
  • 5
  • 6
  • It's worth to mention that for mac os x you can try `ssh root@localhost -p ` follow instructions [here](https://superuser.com/a/1080211/436362) – Claudio Santos Jun 01 '20 at 04:45
0

It is a short way but not permanent

first create a container

docker run  ..... -p 22022:2222 .....

port 22022 on your host machine will map on 2222, we change the ssh port on container later , then on your container executing the following commands

apt update && apt install  openssh-server # install ssh server
passwd #change root password

in file /etc/ssh/sshd_config change these : uncomment Port and change it to 2222

Port 2222

uncomment PermitRootLogin to

PermitRootLogin yes

and finally restart ssh server

/etc/init.d/ssh start

you can login to your container now

ssh -p 2022 root@HostIP

Remember : if you restart the container you need to restart ssh server again