Docker: Connessione Client-Server

Introduzione agli Esercizi

Questo primo esempio introduce l'utilizzo degli strument Docker e Docker Compose nel realizzare una rete semplice.

Come primo esempio è prolisso e vengono descritti tutti i componenti della rete e come generarli.

Per quanto sia possibile seguire passo passo le istruzioni e preparare manualmente ogni componente (copiando il codice dalla documentazione e incollandolo nel proprio personale ambiente di esercizio), questo non è necessario.

Ogni esercizio è corredato di un file in formato TAR, che si può scaricare e scompattare.

Installazione di un Esercizio

Per esempio a questo esercizio è collegato il file 01net1-ccli-cssh.tar.

Scaricarlo in una directory che conterrà tutti gli esercizi e che deve venire creata:

mkdir -p ~/ex
cd ~/ex

Scompattarlo:

tar xvf 01net1-ccli-cssh.tar

Andare nella directory creata:

cd 01net1-ccli-cssh.tar

Creare fli oggetti dell'esercizio, o progetto specifico, col comando.

Se si usa il Docker Compose come plugin interno di Docker:

docker compose up -d

Se si usa l'utility Docker Compose scritta in Python:

docker-compose up -d

I dettagli di esecuzione dell'esercizio sono poi specifici all'esercizio stesso.

Pulizia dell'Esercizio

Al termine rimuovere tutti i contenitori di processo, di rete e di dati coinvolti nell'esercizio.

Se si usa il Docker Compose come plugin interno di Docker:

docker compose down

Se si usa l'utility Docker Compose scritta in Python:

docker-compose down

Una rete: 01net1-ccli-cssh

Descrizione concisa: Una rete, client e server SSH.

E' importante preparare un diagramma del progetto.

Non esiste uno specifico linguaggio di diagrammazione, ciascuno può scegliersi il suo. L'importante è rimanere consistemti in diagrammi di più progetti.

Il diagramma deve specificare tutti i componenti del progetto. Lo scopo è di passarlo ad un programmatore, che deve comprendere subito quello che deve preparare.

01net

La rete si chiamerà net1 e il suo indirizzo CIDR sarà 192.160.100.0/24.

Sulla rete vi saranno due container: one e two, con indirizzi di host 11 e 12.

Il container one sarà generato dall'immagine ccli e sarà un client SSH, two dall'immagine cssh, un server SSH.

Il container two avrà un utente pippo, con password pluto.

Scaffolding

E' importante avere un nome distintivo del progetto, che suggerisca la struttura e le intenzioni di ciò che si vuole compiere.

Creare la directory di progetto:

mkdir -p ~/ex
cd ~/ex
mkdir 01net1-ccli-cssh
cd 01net1-ccli-cssh

L'albero dei files che comporranno il progetto è preparato prima, con i files vuoti. Questo è lo scaffolding (impalcatura) del progetto.

L'approccio è top-down.

Preparare lo scaffolding:

mkdir ccli cssh
touch ccli/Dockerfile cssh/Dockerfile
touch docker-compose.yml

Ogni immagine da generare ha una sottodirectory col nome dell'immagine, e contiene il suo Dockerfile, più ogni altro eventuale file necessario nal build.

A livello progetto vi è il file docker-compose.yml.

Il risultato è:

tree .
.
├── ccli
│   └── Dockerfile
├── cssh
│   └── Dockerfile
└── docker-compose.yml

Files del Progetto

ccli/Dockerfile

vim ccli/Dockerfile
FROM alpine:3.7
MAINTAINER John Smith <john@stormforce.ac>

RUN apk --update add --no-cache openssh tcpdump curl

CMD ["/bin/sleep","1000000"]

cssh/Dockerfile

vim cssh/Dockerfile
FROM alpine:3.7
MAINTAINER John Smith <john@stormforce.ac>

# Installazione del software
RUN apk --update add --no-cache openssh tcpdump \
openssh bash && rm -rf /var/cache/apk/*

# ‘root’ può fare login
RUN sed -i s/#PermitRootLogin.*/PermitRootLogin\ yes/ /etc/ssh/sshd_config \
  && echo "root:root" | chpasswd 
# Abilitare la porta 22
RUN sed -ie 's/#Port 22/Port 22/g' /etc/ssh/sshd_config

# Abilitare le chiavi crittografiche
RUN sed -ri 's/#HostKey \/etc\/ssh\/ssh_host_key/HostKey \/etc\/ssh\/ssh_host_key/g' /etc/ssh/sshd_config
RUN sed -ir 's/#HostKey \/etc\/ssh\/ssh_host_rsa_key/HostKey \/etc\/ssh\/ssh_host_rsa_key/g' /etc/ssh/sshd_config
RUN sed -ir 's/#HostKey \/etc\/ssh\/ssh_host_dsa_key/HostKey \/etc\/ssh\/ssh_host_dsa_key/g' /etc/ssh/sshd_config
RUN sed -ir 's/#HostKey \/etc\/ssh\/ssh_host_ecdsa_key/HostKey \/etc\/ssh\/ssh_host_ecdsa_key/g' /etc/ssh/sshd_config
RUN sed -ir 's/#HostKey \/etc\/ssh\/ssh_host_ed25519_key/HostKey \/etc\/ssh\/ssh_host_ed25519_key/g' /etc/ssh/sshd_config


# Generare le chiavi crittografiche
RUN /usr/bin/ssh-keygen -A
RUN ssh-keygen -t rsa -b 4096 -f  /etc/ssh/ssh_host_key

# Generazione dell’utente ‘pippo’ con password ‘pluto’
RUN adduser -D pippo && echo "pippo:pluto" | chpasswd

# Porta da esporre al port mapping
EXPOSE 22

# Comando da lanciare
CMD ["/usr/sbin/sshd","-D"]

docker-compose.yml

vim docker-compose.yml
version: '3.6'

services:
  one:
    build: ccli
    image: ccli
    container_name: one
    hostname: one
    cap_add:
      - ALL
    networks:
      net1:
        ipv4_address: 192.168.101.11
  two:
    build: cssh
    image: cssh
    container_name: two
    hostname: two
    cap_add:
      - ALL
    networks:
      net1:
        ipv4_address: 192.168.101.12
networks:
  net1:
    name: net1
    ipam:
      driver: default
      config:
        - subnet: 192.168.101.0/24

Esecuzione

Lancio del progetto:

docker compose up -d

Vengono create le immagini ccli e cssh.

Vengono attivate la rete net1 e i containers one e two.

Test

Collegarsi a one:

docker exec -ti one sh

Aprire una sessione SSH a two:

ssh pippo@two
  • Accettare la chiave pubblica
  • La password è pluto

Chiudere il collegamento ssh con exit.

Uscire da one con exit.

Pulizia

Da host, directory di progetto:

docker compose down

Vengono fermati i contenitori, poi rimossi i contenitori e la rete.


Esercizio 1A

Accedere ad un contenitore di processo con il comando, p.es. docker exec -ti one sh è fattibile ma pesante, e occupa una finestra di terminale.

Un'alternativa per chi dispone di un Linux con grafica è di configurare una finestra di terminale per l'accesso ad uno specifico contenitore di processo.

Questo lo faremo creando, nelle Preferenze di terminale, un nuovo profilo. In questo esercizio chiameremo il profilo one.

Dato che i vari contenitori di processo nei vari esercizi si chiamano one, two, three, ecc., possiamo creare un numero di profili di terminale con gli stessi nomi, ciascuno che accede al corrispondente contenitore di processo.

01anet

Nuovo Profilo di terminale

Nuovo profilo: one.

Term1

  1. Cliccare sul menù di terminale
  2. Selezionare Preferences
  3. Aggiungere un profilo, cliccando il simbolo + accanto a Profiles
  4. Dare al profilo il nome one

Custom Command

Term2

  1. Nella nuova configurazione del profilo one, selezionare il tab Command
  2. Spuntare "Run a custom command instead of my shell"
  3. Nella finestra "Custom command" digitare:
bash -c "docker exec -ti one sh -c \"export PS1='\h:\W\# ' && sh -\""

Viene eseguito sul terminale one

  • una prima shell che cambia il pronto primario PS1
  • una shell figlia sh - e il simbolo - fa si che sia una shell di login, che quindi esegue il file .profile

Personalizzazione Colori

Term3

Per renderlo distintivo, cambiamo i colori del terminale.

  1. Selezioniamo il tab "Colors"
  2. Togliamo la spunta a "Use transparency"
  3. Togliamo la spunta a "Use colors from system theme"
  4. Nel menù a tendina di "Built in schemes" selezioniamo lo schema di colori, p.es. "Black on light yellow"
  5. Chiudiamo la finestra di configurazione del profilo

Uso del Terminale

Term4

  1. Menà "New Terminal" o "New Window"
  2. Scegliere il profilo one

Nota - Occorre che il nostro esercizio sia attivo, cioè che sia stato dato in precedenza il comando docker compose up -d.

Profilo per two

Ripetere per un nuovo profilo two.

Il comando custom è naturalmente:

bash -c "docker exec -ti two sh -c \"export PS1='\h:\W\# ' && sh -\""

Schema di colori, per esempio, : Green on black.

Term5