Docker SSH on the fly

Docker SSH on the fly

purpose

Create an image, a script and a bit of local configuration to pop SSH container on the …. fly.

prerequisite

Have docker installed.

Create a folder to start the project and add configFiles/

Create configFiles/bashrc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples

# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac

# don't put duplicate lines or lines starting with space in the history.
# See bash(1) for more options
HISTCONTROL=ignoreboth

# append to the history file, don't overwrite it
shopt -s histappend

# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTSIZE=1000
HISTFILESIZE=2000

# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize

# If set, the pattern "**" used in a pathname expansion context will
# match all files and zero or more directories and subdirectories.
#shopt -s globstar

# make less more friendly for non-text input files, see lesspipe(1)
[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"

# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
debian_chroot=$(cat /etc/debian_chroot)
fi

# set a fancy prompt (non-color, unless we know we "want" color)
case "$TERM" in
xterm-color|*-256color) color_prompt=yes;;
esac

# uncomment for a colored prompt, if the terminal has the capability; turned
# off by default to not distract the user: the focus in a terminal window
# should be on the output of commands, not on the prompt
#force_color_prompt=yes

if [ -n "$force_color_prompt" ]; then
if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
# We have color support; assume it's compliant with Ecma-48
# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
# a case would tend to support setf rather than setaf.)
color_prompt=yes
else
color_prompt=
fi
fi

# custom
IP=$(tac /etc/hosts | head -n 1 | awk '{print $1}')
if [ ! -f .colorc ]; then
COLOR=$((1 + $RANDOM % 256))
echo -ne $COLOR > .colorc
else
COLOR=$(cat .colorc)
fi

if [ "$color_prompt" = yes ]; then
PS1='${debian_chroot:+($debian_chroot)}\[\033[48;5;${COLOR}m\](Docker)\[\033[00m\]\[\033[01;95m\] \u@${IP}\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi
unset color_prompt force_color_prompt

# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
;;
*)
;;
esac

# enable color support of ls and also add handy aliases
if [ -x /usr/bin/dircolors ]; then
test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
alias ls='ls --color=auto'
#alias dir='dir --color=auto'
#alias vdir='vdir --color=auto'

alias grep='grep --color=auto'
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'
fi

# colored GCC warnings and errors
#export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'

# some more ls aliases
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'

# You may want to put all your additions into a separate file like
# ~/.bash_aliases, instead of adding them here directly.
# See /usr/share/doc/bash-doc/examples in the bash-doc package.

if [ -f ~/.bash_aliases ]; then
. ~/.bash_aliases
fi

# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc).
if ! shopt -oq posix; then
if [ -f /usr/share/bash-completion/bash_completion ]; then
. /usr/share/bash-completion/bash_completion
elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
fi

Create a configFiles/sudoers

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#
# This file MUST be edited with the 'visudo' command as root.
#
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
#
# See the man page for details on how to write a sudoers file.
#
Defaults env_reset
Defaults mail_badpass
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"

# Host alias specification

# User alias specification

# Cmnd alias specification

# User privilege specification
root ALL=(ALL:ALL) ALL

# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL

# Allow members of group sudo to execute any command
%sudo ALL=(ALL) NOPASSWD: ALL

# See sudoers(5) for more information on "#include" directives:

#includedir /etc/sudoers.d

Add your SSH public key and paste it to configFiles/id_rsa.pub

Finally :

1
2
3
4
configFiles/
├── bashrc
├── id_rsa.pub
└── sudoers

Image

first create a Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
FROM ubuntu

# Update and install component
RUN apt-get update
RUN apt-get -y install openssh-server sudo

# add sudoers right
ADD configFiles/sudoers /etc/sudoers
RUN mkdir /var/run/sshd; chmod 755 /var/run/sshd

# create a local user
RUN groupadd local
RUN useradd -m -s /bin/bash -g local -G sudo -u 1000 local
RUN mkdir /home/local/.ssh; chmod 700 /home/local/.ssh

# add bashrc with cool prompt
ADD configFiles/bashrc /home/local/.bashrc
ADD configFiles/bashrc /root/.bashrc

# add your public SSH key
ADD configFiles/id_rsa.pub /home/local/.ssh/authorized_keys
RUN chmod 600 /home/local/.ssh/authorized_keys
RUN chown -R local:local home/local

# remove some file to get a clean start
RUN rm /etc/update-motd.d/*
RUN rm /etc/legal
RUN touch /home/local/.sudo_as_admin_successful

# start SSH
EXPOSE 22
CMD ["/usr/sbin/sshd","-D"]

Now to create the image run :

1
docker build -t docker_ssh --label latest --pull .

This will create the image : docker_ssh:latest

SSH config

Configure your .ssh/config file (create or modify), and add

1
2
3
4
5
Host 172.17.*.*
User local
StrictHostKeyChecking no
IdentityFile ~/.ssh/id_rsa.pkey
LogLevel QUIET

for the IP 172.17.0.0/16 (default docker range)
use user “local”
don’t check the key (on local env only)
use your private key (change if needed)
no log

Bash script to start SSH container on the fly

startDocker_ssh.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#!/bin/bash

docker_name="ssh"
docker_image='docker_ssh'

# help
usage(){
echo "-n [name] for the docker name prefix, default : ${docker_name}"
echo "-l for the number of docker, default : 1"
echo "-i for the docker image name , default : ${docker_image}"
echo "-h for the help"
exit 1
}

random_id(){
echo $(cat /dev/random | tr -dc 'a-zA-Z0-9' | fold -w 4 | head -n 1)
}
loop=1

while getopts ":n:i:l:h" options; do

case "${options}" in
h)
usage
exit
;;
n)
docker_name=${OPTARG}
;;
i)
docker_image=${OPTARG}
;;
l)
loop=${OPTARG}
re_isanum='^[0-9]+$'
if ! [[ $loop =~ $re_isanum ]]; then

echo "Error: i must be a num"
usage
exit 2
elif [ $loop -eq "0" ]; then

echo "Error: i must be > 0"
usage
exit 3
fi
;;
:)
echo "Error: -${OPTARG} requires an argument."
usage
exit 4
;;
*)
echo "Error: fail option..."
usage
;;
esac
done

ips=()

for (( c=1; c<=$loop; c++ )); do

id=$(random_id)
name="${docker_name}_${id}"
#echo "Create docker : [$name]"
uuid=$(docker run -d --name $name $docker_image)
#echo "$uuid"
ips+=($(docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $uuid))
echo -ne "."
done

echo ""

for ip in "${ips[@]}"; do
echo "ssh $ip"
done

The script start x ssh local server \o/

stopDocker_ssh.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#!/bin/bash

name='ssh_'

function usage(){

echo "-n [name] filter prefix to delete, default value: $name"
echo "-h show help"
}


while getopts ":n:h" options; do

case "${options}" in
h)
usage
exit
;;
n)
name=${OPTARG}
;;
:)
echo "Error: -${OPTARG} requires an argument."
usage
exit 4
;;
*)
echo "Error: fail option..."
usage
;;
esac
done


# docker stop all containers
docker stop $(docker ps -a -q -f name=$name) >/dev/null

# Docker rm all
docker rm $(docker ps -a -q -f name=$name) >/dev/null

This script stop and remove all docker how match “ssh_”

docker ssh gif

Now you can put this Bash script into your PATH ;)