Il mio blog

Simone Foschi

Frontend Developer

‹ Back to Blog index


Come creare un Reverse Proxy Nginx con configurazione automatizzata dei siti web con docker

Simo 2020/2/13

updated 2020/2/23


Come ho iniziato a pensarci

Era un pezzetto che seguivo delle guide su docker, se ne parla molto in giro per il web e nell'associazione RiminiLUG che frequento.

Siccome Docker è un ottimo tool per eseguire vari servizi su una singola macchina, ho pensato che mi sarebbe tornato utile per il mio server.

Docker ha il pregio di sporcare minimamente la macchina sul quale si eseguono i suoi container, è facilmente trasportabile da una macchina ad un'altra ed estendibile tramite altri tool, per distribuire il carico del server su più macchine quando il carico di lavoro aumenta.

Dopo una riflessione e qualche ricerca sul come creare il server con docker ho scoperto che mi sarebbe servito un reverse proxy nginx e quindi, cercando su internet, ho trovato questo articolo dove si parla di come eseguire un reverse proxy con docker e caricare automaticamente la configurazione di nginx.

Inizialmente, per via di un errore nella configurazione del file docker-compose.yml, non sono riuscito a metterlo in piedi, finché insieme a Matteo dell'associazione non ho trovato una guida che mi facesse vedere l'installazione sotto un altro punto di vista in questa guida sul wiki ufficiale.

Chiara chiara, pulita ed ha funzionato subito.

Alla fine chiedendo su stackoverflow, ho scoperto che il mio sbaglio consisteva nell'aver editato il codice originale di pattonwebz e stavo eseguendo due istanze di docker-gen. Una era dentro il container nginx-proxy ed un'altra la istanziavo direttamente come container. Quindi in un'installazione con tre container (nginx, docker-gen e docker-letsencrypt-nginx-proxy-companion), non va istanziato un container nginx-proxy.

Eseguendo i servizi in test su un'istanza di digitalocean da 1 GB di RAM, ho scoperto che questo tipo di sistema, eseguendo un'istanza di mariadb per ogni wordpress installato, richiedeva una quantità di risorse maggiore e che mi sarebbe costato troppo l'hosting presso di loro per due sitarelli come i miei.

Matteo mi ha ricordato contabo.com, che mi aveva consigliato precedentemente anche Giuseppe, un altro socio dell'associazione, ma al tempo, a causa di runcloud.io che funziona solo su determinati hosting, non avevo considerato l'opzione di spostare il mio server.

Quindi, comprato un VPS su contabo ed ora ho 4 Gb di RAM e 300 Gb di hard disk SSD boosted per una cifra ridicola confronto a prima.

Questa la parte decisionale e ragioneristica, ora passiamo alla parte pratica.


Come configurare il server per e installare docker

Come sistema operativo ho deciso di usare Ubuntu 18.04 LTS e come sistema di protezione per ssh un classico fail2ban. Il firewall non ho dovuto installarlo in quanto ho trovato che sull'immagine di Ubuntu 18.04 di Contabo è impostato un firewall che apre solamente le porte 22, 80 e 443. Quindi è una situazione perfetta a livello di sicurezza per una installazione basica come la mia.

Quindi ho configurato il server da root così:

1adduser TUO-USERNAME
2usermod -aG sudo TUO-USERNAME
3rsync --archive --chown=TUO-USERNAME:TUO-USERNAME ~/.ssh /home/TUO-USERNAME
4apt update && apt upgrade && apt dist-upgrade && apt autoremove && apt autoclean
5apt install --install-recommends linux-generic-hwe-18.04
6apt install fail2ban
7apt update && apt upgrade && apt dist-upgrade && apt autoremove && apt autoclean
8curl -fsSL https://get.docker.com -o get-docker.sh
9sh get-docker.sh
10usermod -aG docker TUO-USERNAME
11apt install docker-compose -y
12

Quindi mi sono loggato col nome utente appena creato.

Per quanto riguarda il login ssh avevo già generato sul mio computer con ssh-keygen di lavoro le chiavi private e quindi con filezilla non ho fatto altro che caricarle nella cartella ~/.ssh con i permessi corretti.

Quindi mi sono creato dei domini di test su duckdns ed li ho configurati tutti per puntare al mio server. Per ogni dominio di test ho fatto così:

1mkdir duckdns
2cd duckdns
3nano TUO-DOMINIO.sh
4# ci ho incollato dentro questa stringa
5echo url="https://www.duckdns.org/update?domains=TUO-DOMINIO&token=xxxx-xxxx-xxxx-xxxx&ip=" | curl -k -o ~/duckdns/TUO-DOMINIO.log -K -
6# CTRL-X INVIO
7chmod 700 TUO-DOMINIO.sh
8crontab -e
9# ci ho incollato dentro questa stringa
10*/5 * * * * ~/duckdns/TUO-DOMINIO.sh >/dev/null 2>&1
11# CTRL-X INVIO
12./TUO-DOMINIO.sh
13

Per il server di produzione bisogna puntare i dns dei domini all'IP della macchina di produzione, infatti la configurazione sopra serve per la macchina in test e il dns dei siti di test, con la procedura sopra è già apposto.


Configurare la network, i container ed i volumi Docker

Per creare il docker network sotto il quale gireranno i container, bisogna dare questo comando:

1docker network create nginx-proxy

Da ora in poi assegneremo i container alla rete nginx-proxy appena creata.

Successivamente bisogna creare un po' di cartelle, qui sotto l'albero delle directory:

1- /home/TUO-USERNAME/
2  - nginx-proxy/
3    - wordpress1/
4      - wp-content/
5    - wordpress2/
6      - wp-content/
7

Questo per creare una struttura ordinata nella quale compilare i docker-compose.yml, per i files della cartella wp-content di wordpress e per la cartella dei certificati ssl.

In questa maniera, qualora si volesse cambiare hosting VPS, basterà procedere ad una configurazione standard di Ubuntu esattamente come sopra, basterà caricare le cartelle e i files che creeremo e lanciare il comando "docker-compose up -d" su ogni cartella ove ci sia un docker-compose.yml e girare i dns verso il nuovo server per avere i siti funzionanti come sul vecchio VPS.


Creare i files docker-compose.yml

Seguendo il wiki di nginx-proxy-letsencrypt-companion, ho creato il three-container setup incollando dentro il docker-compose.yml creato nella directory radice (nginx-proxy):

1version: '2'
2services:
3nginx-proxy:
4    image: nginx:alpine
5    container_name: nginx-proxy
6    ports:
7      - "80:80"
8      - "443:443"
9    volumes:
10      - conf:/etc/nginx/conf.d
11      - vhost:/etc/nginx/vhost.d
12      - html:/usr/share/nginx/html
13      - certs:/etc/nginx/certs:ro
14    network_mode: bridge
15  docker-gen:
16    image: jwilder/docker-gen
17    container_name: nginx-proxy-gen
18    command: -notify-sighup nginx-proxy -watch /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
19    volumes_from:
20      - nginx-proxy
21    volumes:
22      - /path/to/nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl:ro
23      - /var/run/docker.sock:/tmp/docker.sock:ro
24    labels:
25      - "com.github.jrcs.letsencrypt_nginx_proxy_companion.docker_gen"
26    network_mode: bridge
27  letsencrypt:
28    image: jrcs/letsencrypt-nginx-proxy-companion
29    container_name: nginx-proxy-le
30    volumes_from:
31      - nginx-proxy
32    volumes:
33      - certs:/etc/nginx/certs:rw
34      - /var/run/docker.sock:/var/run/docker.sock:ro
35    network_mode: bridge
36volumes:
37  conf:
38  vhost:
39  html:
40  certs:

A questo punto dentro le cartelle wordpress1 e wordpress2 ho creato la cartella wp-content

e un docker-compose.yml in ogni cartella con questo contenuto:

1version: "3"
2services:
3  db_node_domain:
4    image: mariadb:10.4
5    volumes:
6      - db_data:/var/lib/mysql
7    restart: always
8    environment:
9      MYSQL_ROOT_PASSWORD: MY-SECRET-PASSWORD
10      MYSQL_DATABASE: wordpress
11      MYSQL_USER: wordpress
12      MYSQL_PASSWORD: MY-SECRET-PASSWORD
13    container_name: example_db
14  example:
15    depends_on:
16      - db_node_domain
17    image: wordpress:latest
18    expose:
19      - 443
20    restart: always
21    environment:
22      VIRTUAL_HOST: www.example.com,example.com
23      WORDPRESS_DB_HOST: db_node_domain:3306
24      WORDPRESS_DB_USER: wordpress
25      WORDPRESS_DB_PASSWORD: MY-SECRET-PASSWORD
26      LETSENCRYPT_HOST: www.example.com,example.com
27      LETSENCRYPT_EMAIL: myemail@example.com
28    container_name: example
29    volumes:
30      - data_volume:/var/www/html
31      - ./home/wp:/home/wp
32      - ./wp-content:/var/www/html/wp-content
33volumes:
34  db_data:
35  data_volume:
36networks:
37  default:
38    external:
39      name: nginx-proxy

Cambiando rispettivamente "example" con il nome del mio sito, "MY-SECRET-PASSWOWRD" con due password sicure, una per root e una per l'utente di mariadb associato al sito e l'email per richiedere il certificato https.

Si salvano le due configurazioni e rispettivamente in ogni cartella ove abbiamo creato i file docker-compose.yml si esegue:

1docker-compose up

aggiungendo il parametro -d si indicherà a docker-compose di eseguire i container come demoni, quindi in fase di produzione bisognerà dare quel paramentro.


Il lieto fine

Dopo aver messo in produzione il tutto ho dovuto fare alcune sistemazioni, tutte correttamente riportate negli snippet di questo articolo.

Le macchine vanno che è una meraviglia ma ho notato che ad ogni aggiornamento dell'engine di docker, bisogna riavviare i container con un:

1docker-compose stop
2docker-compose up -d

nelle rispettive cartelle dei file docker-compose.yml

Finito tutto per il meglio dopo qualche mese di standby sul vecchio sistema, domande nelle chat, nei forum e di sbattimenti di testa. Morale, so anche fare il sistemista quando mi impegno. :-)

-- Buona vita --

Commenti ->

‹ prevnext ›

‹ Back to Blog index