Le applicazioni PHP sono generalmente composte da un server web, un sistema di database relazionale e lo stesso interprete linguistico. In questo tutorial utilizzeremo uno stack completo di applicazioni PHP usando la finestra mobile. Questo è un tutorial approfondito in cui costruiremo e orchestreremo container per Nginx (il server web), MySQL (il sistema di database) e PHP.
Per il bene di questo tutorial, scriveremo una semplice applicazione che legge un elenco di città da un database e lo visualizza su una pagina Web, in questo modo dimostreremo un'applicazione PHP di base, ma funzionante.
In questa guida si presuppone che Docker-CE sia già installato e almeno una conoscenza minima della docker. Per questo motivo puoi consultare i seguenti tutorial:
Configurazione del nostro ambiente di lavoro
Un'applicazione basata su docker di vita reale sarà in genere composta da diversi contenitori. La gestione manuale di questi può facilmente diventare alquanto confusa e ingombrante. È qui che entra in gioco la composizione docker. Ti aiuta a gestire un numero di contenitori attraverso un semplice yaml
file di configurazione.
Installa docker-compose.
curl -L https://github.com/docker/compose/releases/download/1.19.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
Creare una cartella per contenere tutti i file necessari di questo esempio e quindi cd
al suo interno. D'ora in poi, questa è la nostra directory di lavoro e ogni comando verrà eseguito all'interno di questa cartella e ogni percorso verrà referenziato rispetto ad essa. Questa cartella può essere referenziata in seguito come WORKING_DIR
.
mkdir ~/docker
cd ~/docker
Ora crea altre tre cartelle.
mkdir php nginx app
La php
cartella è dove costruiremo la nostra immagine PHP personalizzata, la nginx
cartella conterrà i file necessari per la nostra immagine nginx personalizzata e la app
cartella è dove inseriremo il codice sorgente e la configurazione della nostra applicazione di esempio.
Configurazione del contenitore PHP
In questo esempio, useremo php-fpm
per connetterci al server web Nginx. Useremo l'immagine base PHP ufficiale. Tuttavia, dobbiamo anche installare e abilitare alcune estensioni in modo da poter accedere al database. All'interno della php
cartella creare un file denominato Dockerfile
e inserire il seguente contenuto in esso.
FROM php:7.1-fpm-alpine3.4
RUN apk update --no-cache \
&& apk add --no-cache $PHPIZE_DEPS \
&& apk add --no-cache mysql-dev \
&& docker-php-ext-install pdo pdo_mysql
Nota che stiamo usando la versione alpina dell'immagine PHP ufficiale. Alpine è una distribuzione molto piccola indirizzata verso i container fornendo impronte molto più piccole. Inoltre, nota l'uso del comando docker-php-ext-install
, l'immagine PHP ufficiale fornisce questo comando per facilitare il processo di installazione e configurazione delle estensioni PHP.
Ora costruiamo questa immagine Docker emettendo il seguente (all'interno del nostro WORKING_DIR
):
docker build -t vultr-php php/
Il docker-compose.yml
file
Come già accennato, docker-compose
consente di gestire un numero di contenitori tramite un semplice file di configurazione. Questo file di configurazione è in genere denominato docker-compose.yml
. Crea questo file all'interno della app
cartella.
touch app/docker-compose.yml
Ora inserisci i seguenti contenuti in questo file.
version: '2'
services:
php:
image: vultr-php
volumes:
- ./:/app
working_dir: /app
Spiegheremo questa sintassi. Innanzitutto, nota la prima riga.
version: '2'
Questo specifica la versione del docker-compose.yml
file di configurazione utilizzato. La riga successiva specifica i servizi o, in altre parole, i contenitori da sottoporre a provisioning.
services:
php:
image: vultr-php
volumes:
- ./:/app
working_dir: /app
Si noti che ogni servizio ha una chiave specifica all'interno del services
blocco. Il nome qui specificato verrà utilizzato per fare riferimento a questo specifico contenitore in un secondo momento. Si noti inoltre che all'interno della php
configurazione, definiamo l'immagine utilizzata per eseguire il contenitore (questa è l'immagine che abbiamo creato in precedenza). Definiamo anche una mappatura del volume.
volumes:
- ./:/app
Questo dice docker-compose
di mappare la directory corrente ( ./
) alla /app
directory all'interno del contenitore. L'ultima riga imposta la /app
cartella all'interno del contenitore come directory di lavoro, il che significa che questa è la cartella da cui vengono eseguiti per impostazione predefinita tutti i comandi futuri all'interno di un contenitore.
Ora possiamo orchestrare i nostri contenitori.
cd ~/docker/app
docker-compose up -d
È possibile eseguire il comando seguente per assicurarsi che il contenitore PHP sia stato eseguito:
docker ps
Come eseguire i comandi all'interno dei contenitori
Sempre all'interno della app
cartella, possiamo eseguire qualsiasi comando all'interno di un contenitore di servizi definito con l'aiuto del docker-compose
comando.
docker-compose exec [service] [command]
Il [service]
segnaposto si riferisce alla chiave di servizio. Nel nostro caso, questo è stato php
. Eseguiamo un comando all'interno del contenitore per verificare la nostra versione di PHP.
docker-compose exec php php -v
Vedrai il seguente output.
PHP 7.1.14 (cli) (built: Feb 7 2018 00:40:45) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2018 Zend Technologies
Configurazione del contenitore Nginx
Proprio come il contenitore PHP, dobbiamo creare un'immagine personalizzata per il server web. Ma in questo caso, dobbiamo solo fornire una configurazione per il nostro virtual host
. Assicurati di essere all'interno del nostro WORKING_DIR
e crea un Dockerfile
all'interno della nginx
cartella:
cd ~/docker
touch nginx/Dockerfile
Ora inserisci i seguenti contenuti in questo Dockerfile
:
FROM nginx:1.13.8-alpine
COPY ./default.conf /etc/nginx/conf.d/default.conf
Stiamo usando l'immagine Nginx predefinita basata su Alpine. Su questo file Docker copiamo semplicemente un file di configurazione nella nostra configurazione dell'applicazione. Prima di creare questa immagine, crea un file di configurazione.
touch nginx/default.conf
Ora popolarlo con questo contenuto.
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
root /app;
index index.php;
#server_name server_domain_or_IP;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
try_files $uri /index.php =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
Si noti che alla fastcgi_pass php:9000
riga stiamo facendo riferimento al contenitore PHP per nome all'interno del service
blocco del docker-compose.yml
file di configurazione. docker-compose
Crea internamente una rete e assegna il nome del servizio come nome host a ciascuno dei servizi definiti. Ora possiamo creare l'immagine Nginx.
docker build -t vultr-nginx nginx/
In aggiornamento docker-compose.yml
Ora aggiorna il app/docker-compose.yml
file.
version: '2'
services:
php:
image: vultr-php
volumes:
- ./:/app
working_dir: /app
web:
image: vultr-nginx
volumes:
- ./:/app
depends_on:
- php
ports:
- 80:80
Abbiamo solo aggiunto un nuovo servizio. La configurazione è quasi la stessa, tranne per quanto segue.
depends_on:
- php
ports:
- 80:80
Una volta che il contenitore Nginx richiede l'inizializzazione completa del servizio PHP, imponiamo questo requisito depends_on
nell'opzione. La ports
chiave di configurazione mappa una porta host su una porta contenitore, qui mappiamo la porta 80
nell'host alla porta 80
nel contenitore.
Ora crea un file chiamato index.php
all'interno della app
cartella e inserisci quanto segue.
<?php phpinfo();
Assicurarsi che la porta 80
sia accessibile tramite il firewall ed eseguire quanto segue.
cd ~/docker/app
docker-compose up -d
Ancora una volta, ricontrolla che il servizio sia attivo.
docker ps
Apri un browser e accedi [vultr-instance-ip]
. È possibile scoprire l'indirizzo IP dell'istanza Vultr eseguendo quanto segue.
hostname -I
Vedrai la pagina delle informazioni di PHP.
Configurazione del contenitore MySQL
L'immagine MySQL ufficiale consente di configurare il contenitore tramite semplici variabili di ambiente. Questo può essere fatto con environment
un'opzione all'interno della definizione del blocco di servizio. Aggiorna il ~/docker/app/docker-compose.yml
file al seguente.
version: '2'
services:
php:
image: vultr-php
volumes:
- ./:/app
working_dir: /app
web:
image: vultr-nginx
volumes:
- ./:/app
depends_on:
- php
ports:
- 80:80
mysql:
image: mysql:5.7.21
volumes:
- ./:/app
- dbdata:/var/lib/mysql
environment:
- MYSQL_DATABASE=world
- MYSQL_ROOT_PASSWORD=root
working_dir: /app
volumes:
dbdata:
Ora abbiamo definito un nuovo servizio per il database. Nota la linea dbdata:/var/lib/mysql
. Ciò monta il percorso sul contenitore /var/lib/mysql
su un volume persistente gestito da Docker, in questo modo i dati del database persistono dopo la rimozione del contenitore. Questo volume deve essere definito in un blocco di livello superiore, come puoi vedere alla fine del file.
Prima di orchestrare la nostra nuova configurazione, scarichiamo un database MySQL di esempio. La documentazione ufficiale di MySQL fornisce alcuni database di esempio. Useremo il noto database mondiale. Questo database fornisce un elenco di paesi e città. Per scaricare questo esempio, esegui quanto segue nella nostra cartella dell'app.
curl -L http://downloads.mysql.com/docs/world.sql.gz -o world.sql.gz
gunzip world.sql.gz
Ora consente di orchestrare i nostri contenitori.
docker-compose up -d
Come avrai già notato, il docker-compose up
comando avvia solo i contenitori che non sono già stati avviati. Verifica le differenze tra il docker-compose.yml
file e la configurazione corrente dei contenitori in esecuzione.
Ancora una volta, controlla che il contenitore MySQL sia stato avviato.
docker ps
Ora popola il database mondiale.
docker-compose exec -T mysql mysql -uroot -proot world < world.sql
È possibile verificare che il database sia stato popolato selezionando i dati direttamente dal database. Per prima cosa accedi al prompt di MySQL all'interno del contenitore.
docker-compose exec mysql mysql -uroot -proot world
Nel prompt di MySQL, eseguire quanto segue.
select * from city limit 10;
Vedrai un elenco di città. Ora esci dal prompt di MySQL.
mysql> exit
Costruire la nostra applicazione
Ora che tutti i contenitori necessari sono attivi e funzionanti, possiamo concentrarci sulla nostra applicazione di esempio. Aggiorna il app/index.php
file al seguente.
<?php
$pdo = new PDO('mysql:host=mysql;dbname=world;charset=utf8', 'root', 'root');
$stmt = $pdo->prepare("
select city.Name, city.District, country.Name as Country, city.Population
from city
left join country on city.CountryCode = country.Code
order by Population desc
limit 10
");
$stmt->execute();
$cities = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Vultr Rocks!</title>
</head>
<body>
<h2>Most Populous Cities In The World</h2>
<table>
<thead>
<tr>
<th>Name</th>
<th>Country</th>
<th>District</th>
<th>Population</th>
</tr>
</thead>
<tbody>
<?php foreach($cities as $city): ?>
<tr>
<td><?=$city['Name']?></td>
<td><?=$city['Country']?></td>
<td><?=$city['District']?></td>
<td><?=number_format($city['Population'], 0)?></td>
</tr>
<?php endforeach ?>
</tbody>
</table>
</body>
</html>
Se accedi [vultr-instance-ip]
in un browser web, vedrai un elenco delle città più popolose del mondo. Congratulazioni, hai implementato un'applicazione PHP perfettamente funzionante utilizzando la finestra mobile.
Conclusione
In questo tutorial, ho dimostrato passo dopo passo come configurare un'applicazione PHP pienamente funzionante. Abbiamo creato immagini personalizzate per PHP e Nginx e configurato docker-compose per orchestrare i nostri container. Nonostante sia molto semplice e di base, questa configurazione riflette uno scenario di vita reale.
In questa guida, abbiamo creato e taggato le nostre immagini localmente. Per una configurazione più flessibile, è possibile trasferire queste immagini in un registro docker . È possibile inviare al registro docker ufficiale o persino impostare il proprio registro docker. In ogni caso, questo ti permetterà di costruire le tue immagini su un host e usarle su un altro.
Per un uso più dettagliato di docker-compose
, è necessario fare riferimento alla documentazione ufficiale .
A seconda dei requisiti dell'applicazione e del framework PHP che usi, potresti voler aggiungere più estensioni. Questo può essere fatto facilmente modificando l' Dockerfile
usato per costruire la nostra immagine PHP personalizzata. Tuttavia, alcune estensioni richiedono l'installazione di dipendenze extra nel contenitore. È necessario fare riferimento all'elenco delle estensioni nella documentazione ufficiale di PHP per rivedere i requisiti di base di ciascuna estensione.