Simone Foschi
Frontend Developer
Come creare un Reverse Proxy Nginx con configurazione automatizzata dei siti web con docker
Simo 2020/2/13
updated 2021/6/12
UPDATE 12/6/2021: inizialmente questa guida era stata basata su Ubuntu 18.04, ora l'ho aggiornata includendo le istruzioni anche per la 20.04
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
8
9## IN CASO CURL NON SIA PRESENTE
10## -->
11apt install curl
12## <--
13
14curl -fsSL https://get.docker.com -o get-docker.sh
15sh get-docker.sh
16usermod -aG docker TUO-USERNAME
17## riavviare il computer
18apt install docker-compose -y
Nota: forse avrete bisogno di usare sudo prima dei comandi
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
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, girare i dns verso il nuovo server per avere i siti funzionanti.
Infine bisognerà caricare i backup delle vostre installazioni WordPress creato precedentemente tramite un plugin di backup. Io uso Updraft Plus
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.
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. :-)
Commenti ->
In questo post su twitter