LUCA FAVENZI

Una breve introduzione

Prima di iniziare, dovrebbe essere noto che questo articolo non è un tutorial completo su Docker o una spiegazione sulla complessità del set di strumenti. È più una procedura semplificata per ottenere un ambiente di sviluppo locale configurato rapidamente utilizzando Docker e docker-compose, invece di installare uno stack LAMP direttamente sulla tua macchina. Ci sono alcuni avvertimenti che ne derivano, ma il metodo seguente è quello che ho trovato che funziona meglio per me durante lo sviluppo di app Laravel.

Per coloro che non sanno cosa sia Docker, godiamoci una breve panoramica. Secondo opensource.com:

Docker è uno strumento progettato per semplificare la creazione, la distribuzione e l’esecuzione di applicazioni utilizzando i contenitori. I contenitori consentono a uno sviluppatore di creare un pacchetto di un’applicazione con tutte le parti di cui ha bisogno, come le librerie e altre dipendenze, e spedire tutto come un unico pacchetto.

Puoi pensare a Docker come a una VM annacquata.

Perché è utile o utile? Bene, se hai più server di produzione che eseguono versioni diverse di Linux, PHP o qualsiasi altro software web, quelle variabili possono essere replicate nel tuo contenitore e puoi essere certo che l’applicazione verrà eseguita esattamente come previsto sulla macchina di produzione.

Adattandosi maggiormente al tono di questo post, se hai più progetti Laravel che abbracciano versioni diverse sulla tua macchina locale, puoi avere una configurazione Docker specifica per ogni app senza dover implementare qualcosa come uno switcher di versione PHP e modificare la configurazione della tua macchina effettiva . Puoi persino accedere a entrambi i progetti contemporaneamente, con ogni contenitore in esecuzione isolato dall’altro.

Ti sembra eccitante? Immergiamoci!

Installazione di Docker

Per la durata di questo articolo, screenshot e riferimenti saranno relativi agli utenti di MacOS. Tuttavia, le istruzioni di installazione e utilizzo dovrebbero essere molto simili (se non quasi esatte) su Windows.

Innanzitutto, prendi il programma di installazione: https://docs.docker.com/docker-for-mac/install/ .

Esegui il tipico processo di installazione dell’applicazione, aprendo l’app una volta completata. Ti verrà chiesto di autorizzare Docker tramite la tua password di sistema la prima volta che lo apri, dopodiché vedrai l’icona della piccola balena apparire nella barra di stato in alto.

Struttura del progetto

Quella che segue è una struttura che ho utilizzato per i miei progetti Laravel + Docker. Non devi seguirlo esplicitamente, anche se il resto di questo articolo presumerà che il tuo progetto sia impostato con lo stesso layout.

my-project.com/
├── nginx/
│   └── default.conf
├── src/
│   └── (Laravel app files)
├── docker-compose.yml
└── Dockerfile

Nelle prossime due parti esaminerò cosa fanno ciascuno di questi file, ma per ora crearli semplicemente come segnaposto vuoti usando il layout sopra. Inoltre, aggiungi (o crea) i file dell’intera app Laravel nella directory src / .

Creare il nostro stack

Un’ottima regola pratica quando si utilizza Docker è che ogni contenitore dovrebbe fornire un singolo servizio. Dato che stiamo creando un tipico stack LEMP, significa che ne avremo bisogno per il nostro server web ( Nginx ), PHP e MySQL . Sebbene in teoria potremmo creare singoli contenitori per ciascuno di questi servizi e quindi tentare di collegarli insieme, Docker ha un bellissimo strumento integrato per questo chiamato docker-compose .

Quello che facciamo è definire i servizi che verranno utilizzati e in fase di runtime Docker provvede a fornire ciascuno di essi come un contenitore e li avvolge tutti in una rete virtuale. Ciò significa che ogni servizio sarà accessibile da ogni contenitore.

Per iniziare, apri il file docker-compose.yml e aggiungi quanto segue all’inizio:

inizio dello screenshot docker-compose.yml

Alcune rapide spiegazioni per ciò che abbiamo appena aggiunto:

  • Versione: 3 , la versione più recente e più consigliata del motore docker-compose
  • Reti: stiamo usando solo una rete, laravel , a cui non stiamo aggiungendo alcuna opzione oltre al nome
  • Servizi: dove specificheremo le immagini che costituiranno il nostro stack

Aggiunta di Nginx

Direttamente sotto l’intestazione dei servizi che abbiamo specificato nella parte inferiore del file docker-compose.yml sopra, aggiungerai quanto segue:

screenshot docker-compose.yml del servizio nginx

Quello che stiamo facendo in quanto sopra è dire a Docker che vogliamo un contenitore chiamato nginx , costruito dall’immagine nginx: stable-alpine (la cui fonte completa puoi vedere qui ). Stiamo usando alpine linux come sistema operativo di base a causa della sua impronta leggera e reattiva.

Successivamente nominiamo il contenitore nginx ed esponiamo la sua :80porta come :8080sulla nostra macchina locale. Questo numero di porta è quello che alla fine useremo per accedere al nostro sito e puoi adattarlo a qualsiasi numero di porta non riservato che ti piace.

Per i volumi del server web, stiamo aggiungendo i due seguenti:

  • La nostra cartella / src locale è associata al percorso / var / www del contenitore . Non diversamente da un collegamento simbolico, tutto ciò che modifichiamo in / src sarà immediatamente disponibile per il server in / var / www.
  • Il file /nginx/default.conf che abbiamo creato è collegato al file contenitore /etc/nginx/conf.d/default.conf e ci darà la possibilità di modificare il server web nginx sulla nostra macchina locale.

È possibile specificare un numero qualsiasi di directory o file sotto questa intestazione per collegarli simbolicamente dalla macchina locale al contenitore nginx.

Aggiungendo sia php che mysql (i servizi che creeremo in seguito) sotto l’ elemento depend_on , stiamo dicendo a Docker che durante l’inizializzazione i contenitori php e mysql devono essere in esecuzione prima di nginx. Inoltre, se provassimo a far girare solo il contenitore nginx, avvierebbe anche entrambi i contenitori dipendenti.

Infine, stiamo specificando che questo contenitore è esplicitamente sotto la rete laravel che abbiamo creato all’inizio del nostro file docker-compose.yml.

Aggiunta di MySQL

Il prossimo servizio che aggiungeremo al nostro file docker-compose.yml è MySQL. Questo è relativamente semplice.

screenshot docker-compose.yml che aggiunge il servizio mysql

Inizialmente stiamo specificando l’immagine e il nome del contenitore, oltre a impostare alcune impostazioni varie che ritengo abbiano aiutato a mantenere la stabilità di MySQL nel contenitore.

La porta MySQL predefinita di :3306è quella che stiamo esponendo alla nostra macchina locale, quindi utilizzando l’ oggetto ambiente possiamo impostare alcune variabili utilizzate durante l’inizializzazione per modificare il database creato. Poiché stiamo configurando Docker per un’app Laravel, sto utilizzando il nome / nome utente / password del database predefinito che si trova nel tipico file Laravel .env.

Proprio come con nginx, stiamo collegando questo servizio alla rete Laravel.

Aggiunta di PHP

A differenza di Nginx e MySQL, l’aggiunta del nostro contenitore PHP richiederà un percorso diverso e leggermente più complicato. Con i due servizi precedenti siamo stati in grado di fare riferimento direttamente a un’immagine da cui costruire il nostro contenitore, tuttavia a causa di una dipendenza richiesta da Laravel stiamo effettivamente costruendo la nostra immagine da un Dockerfile locale.

Prima di arrivare a quella parte, aggiungi quanto segue come prossimo (e ultimo) servizio al nostro file docker-compose.yml .

Docker-compose.yml screenshot dell'aggiunta del servizio php

Puoi già notare la differenza, stiamo sostituendo l’ intestazione dell’immagine che abbiamo usato prima con una build . Sotto di esso, stiamo specificando il contesto come la directory del progetto corrente e il dockerfile come Dockerfile (che abbiamo già creato in precedenza).

Come con il nostro contenitore nginx, stiamo specificando lo stesso volume per la directory root, quindi esponiamo la porta :9000per il contenitore e impostiamo la rete su laravel .

Ora che abbiamo aggiunto quel servizio, è il momento di aggiungere quanto segue al nostro Dockerfile :

Screenshot Dockerfile per la creazione dell'immagine PHP

Sì, è così.

Tutto ciò che stiamo facendo qui è:

  • Specificare che vogliamo che il nostro contenitore php sia costruito 7.2-fpm-alpinedall’immagine PHP.
  • Installazione delle estensioni pdopdo_mysqlPHP che l’ORM di Laravel utilizza con i suoi metodi di database.

Il docker-php-ext-installcomando è integrato (e non ben documentato ) in Docker. Puoi passare attraverso qualsiasi estensione PHP e gestirà l’installazione e la configurazione all’interno del nostro contenitore appena creato.

Configurazione di nginx

Ricordi il nostro file /nginx/default.conf che abbiamo creato? Aprilo e aggiungi quanto segue:

Screenshot della configurazione predefinita di nginx

Onestamente non c’è molto da discutere qui, poiché è principalmente una configurazione nginx boilerplate utilizzata con la maggior parte delle app Laravel di base. Nota che il percorso di root è stato impostato sulla cartella pubblica della nostra directory / var / www nginx a cui abbiamo collegato la nostra app Laravel.

Avvio di Docker

Abbiamo tutti i nostri singoli pezzi in ordine, ora è finalmente il momento di assemblare la nostra rete Docker! Apri una finestra di terminale e vai alla directory principale di questo progetto. Poiché uno dei nostri contenitori ( php ) utilizza un Dockerfile come immagine, ed è la prima volta che facciamo girare questi contenitori, la prima cosa che dobbiamo fare è eseguire il comando build per generare i dati dell’immagine:

docker-compose build

Questo richiederà un po ‘di tempo per finire e potrebbe sembrare che non stia succedendo nulla per un po’. Dagli circa 1–2 minuti e dovresti aver visto i messaggi creati con successo e contrassegnati con successo nel tuo terminale. È quindi possibile procedere con l’avvio effettivo dei contenitori utilizzando:

docker-compose up -d

Docker creerà la nostra rete laravel e quindi creerà i tre contenitori che abbiamo specificato nella sezione servizi del nostro file docker-compose.yml. Se sei curioso del flag -d , sta per disconnesso e mantiene i contenitori in esecuzione dopo che tutti i loro comandi sono stati elaborati. Altrimenti, Docker li interromperà non appena avranno terminato l’inizializzazione. Piuttosto inutile per un server web!

Configurazione di Laravel

Prima di accedere alla nostra app per la prima volta, dobbiamo apportare alcune piccole modifiche al nostro file Laravel .env. In particolare per quanto riguarda la connessione al database e il dominio dell’app. Apri il .envfile del tuo progetto nella directory src e modifica le seguenti righe:

  • DB_HOST=mysql – Questo nome deriva dal servizio MySQL che abbiamo creato nel file docker-compose.yml e viene utilizzato nella rete Docker per fare riferimento al servizio da altri contenitori.
  • APP_URL=http://localhost:8080 – Aggiungi il numero di porta che hai esposto nel nostro contenitore nginx per mantenerlo puntato a un indirizzo risolvibile.

Accesso alla tua app

Supponendo che tutto nel passaggio precedente sia iniziato con successo, ora possiamo visitare il nostro container con la porta esposta e vedere la pagina di destinazione della nostra app!

Nel tuo browser, vai a http: // localhost: 8080 dove 8080 è la prima porta che hai specificato nel servizio nginx nel tuo file docker-compose.yml.

Screenshot di un browser che mostra la schermata di destinazione di Laravel

💥 Boom! Abbiamo la nostra app Laravel in esecuzione su una rete Docker!

Ovviamente se probabilmente vorrai anche accedere al tuo database MySQL usando uno strumento come TablePlus , e connettersi a quello è altrettanto semplice. Tutto quello che devi fare è utilizzare 127.0.0.1come host, insieme alla porta che hai esposto nel servizio MySQL nel nostro file docker-compose.yml (che per questo esempio abbiamo mantenuto come predefinito 3306 ).

Il nostro nome utente e la password che abbiamo specificato nelle variabili di ambiente rispettivamente come MYSQL_USERMYSQL_PASSWORDhomestead e secret .

Screenshot della configurazione di TablePlus

Nota: se hai intenzione di eseguire più reti contemporaneamente per progetti diversi, dovrai specificare porte diverse da esporre sulla tua macchina locale (ad esempio 8080 per una, 8081 per un’altra). In caso contrario, verrai accolto con un port is already allocatederrore durante l’inizializzazione del contenitore.

Comandi in esecuzione

Laravel utilizza la riga di comando abbastanza spesso per cose come migrazioni, code e test. Eseguirli sulla nostra rete Docker è semplicissimo utilizzando il execcomando docker-compose .

Invece di una VM in cui esegui ssh nel sistema ed esegui comandi direttamente sul sistema operativo, Docker preferisce che tu passi i comandi ai contenitori e quindi l’output di quei comandi viene rispedito al tuo terminale. Ad esempio, eseguiamo le migrazioni predefinite fornite da Laravel eseguendo il seguente comando nel nostro terminale nella radice del progetto:

docker-compose exec php php /var/www/artisan migrate

Analizziamo un po ‘questo:

  • docker-compose exec dice a Docker che vogliamo eseguire un comando sulla nostra rete di container.
  • php il nome del contenitore su cui vogliamo eseguire il comando. Dato che stiamo per eseguire un comando PHP, deve essere sul contenitore in cui è in esecuzione PHP.
  • php / var / www / artisan migrano il nome effettivo del comando che stiamo eseguendo. Stiamo usando un percorso assoluto per l’artisan che è collegato tramite link simbolico attraverso il nostro volume locale su ./src ed esegue una migrazione Laravel standard.

Screenshot di un terminale dopo aver eseguito un comando docker-compose migrate

Dovresti essere presentato con l’output della migrazione dopo aver eseguito il nostro comando e il tuo database verrà ora popolato con due tabelle!

Qualsiasi numero di comandi può essere eseguito dal nostro terminale locale nei contenitori Docker di nostra scelta. Basta essere consapevoli dei servizi installati e disponibili nel contenitore su cui si desidera eseguire il comando.

Suggerimento: se sei irremovibile nel voler eseguire ssh direttamente in un contenitore per eseguire i comandi, c’è una soluzione piuttosto semplice. L’esecuzione
docker-compose exec {container_name} /bin/shaprirà una connessione persistente al contenitore specificato nell’argomento {container_name}.

Fine della linea

Bene, ce l’abbiamo! Abbiamo installato Docker, impostato e configurato un file docker-compose per creare uno stack LEMP di tre contenitori avvolti in una singola rete, abbiamo porte esposte su quella rete che ci consentono di accedere alla nostra app e al nostro database e abbiamo persino eseguito comandi cli tramite il metodo exec di docker-compose.

Andando avanti, se vuoi abbattere i contenitori e la rete, è semplice come navigare nella cartella principale del tuo progetto ed eseguire
docker-compose down. In questo modo verranno disattivati ​​e distrutti i contenitori e tutti i dati non di volume associati archiviati in essi.

Docker mi ha aperto un intero mondo di possibilità di sviluppo quando sto manipolando più progetti su diverse versioni di Laravel. Posso facilmente avere un progetto in esecuzione su una rete Docker con un contenitore PHP utilizzando 7.1, e se volessi vedere come il mio progetto corrente si sarebbe comportato in PHP 7.3è semplice come cambiare un singolo carattere nel mio Dockerfile, ricostruire il contenitore e ripristinare la rete docker-compose.

Non lo nego, non otterrai prestazioni di sviluppo locale migliori rispetto all’esecuzione del tuo stack direttamente sull’hardware della tua macchina. Ma il compromesso tra prestazioni e versatilità, facilità d’uso, ambienti paralleli e personalizzazione supera di gran lunga quello per me.