Docker & Laravel: l’ambiente di sviluppo

Docker

In questo articolo mosterò come ulizzare Docker per creare un ambiente di sviluppo portabile e isolato per Laravel.

I container, ovvero come ti impacchetto l’applicazione

Prima di passare al concreto, trovo sia necessaria fare una piccola premessa su cosa sono i container e come stanno rivoluzionando l’industria.

Per molti versi possiamo pensare ai container come simili ad una virtual machine con alcune sostanziali differenze. La differenza più importante (e più sostanziale) è che una vm virtualizza un intero sistema operativo all’interno di un guest dovendo anche simulare lo strato hardware, mentre un container sfrutta una tecnologia presente nel kernel di Linux chiamata “LXC – Linux containers” per poter isolare una parte del sistema operativo dove far quindi girare le nostre applicazioni. Docker nasce nel 2013 come framework al di sopra di LXC come tool per poter pacchettizzare le applicazioni all’interno di scatole che poi vengono eseguite dal kernel, togliendo quindi l’overhead di una macchina virtuale.

Docker & Laravel

Un esempio di ambiente di sviluppo lo potete trovare sul mio repository di GItHub.  Per prima cosa procediamo con il creare il nostro progetto in Laravel:

$ composer create-project --prefer-dist laravel/laravel blog
$ cd blog/
$ php artisan serve
Laravel development server started: <http://127.0.0.1:8000>

Se abbiamo fatto tutto correttamente collegandoci alla porta 8000 della macchina locale visualizzeremo la pagina di default:

Laravel: pagina di default

Per maggiori informazioni su come avviare un progetto in Laravel vi rimando alla documentazione ufficiale. Il passo successivo è quindi clonare il mio repository di esempio all’interno del nostro progetto:

[marco@localhost blog]$ git clone git@github.com:marcocot/php-docker.git docker
Cloning into 'docker'...
remote: Counting objects: 17, done.
remote: Compressing objects: 100% (13/13), done.
remote: Total 17 (delta 1), reused 13 (delta 1), pack-reused 0
Receiving objects: 100% (17/17), done.
Resolving deltas: 100% (1/1), done.
Checking connectivity... done.
[marco@localhost blog]$

Dockerfile

In /docker/php/Dockerfile possiamo trovare la definizione del nostro primo container:

FROM php:7.1-cli
MAINTAINER Marco Cotrufo <marco.cotrufo@devncode.it>

RUN pecl install xdebug && docker-php-ext-enable xdebug \\
&& pecl install -o -f redis \\
&& rm -rf /tmp/pear \\
&& docker-php-ext-enable redis && \\
docker-php-ext-install opcache && \\
docker-php-ext-enable opcache && \\
docker-php-ext-install pdo pdo_mysql && docker-php-ext-enable pdo pdo_mysql

ADD ./xdebug.ini /tmp/xdebug.ini
RUN cat /tmp/xdebug.ini >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini

VOLUME /code
WORKDIR /code

EXPOSE 8000
CMD ["php", "artisan", "--host=0.0.0.0", "serve"]

Sostanzialmente ci preoccupiamo di estendere il container ufficiale di php per eseguire alcune operazioni aggiuntive (4-13):

  1. Attivare l’estensione xdebug
  2. Attivare le estensioni redis, opcache, pdo, pdo_mysql
  3. Copiamo la configurazione di xdebug all’interno del container. Questa configurazione ci permetterà di collegarci a xdebug dall’esterno del container, argomento di un prossimo post.

Alla riga 15 creiamo un mountpoint che ci permetterà di condividere la folder del nostro progetto con il container. Alle righe 18-19 invece istruiamo Docker ad esporre la porta 8000 ed eseguiamo artisan per effettuare il serve della nostra applicazione.
Per i dettagli vi rimando alla documentazione sulla sintassi.

docker-compose, uniamo i pezzi

Abbiamo visto come creare il container per la nostra applicazione, ma nel nostro ambiente di sviluppo mancano ancora un paio di componenti essenziali: MySQL, Redis, Mailcatcher.
Visto che il nostro intento è quello di creare un ambiente di sviluppo assolutamente isolato e portabile possiamo trasformare anche questi servizi in container. In aiuto ci viene docker-compose: un tool che possiamo utilizzare per definire ed avviare più container. Nel file /docker/docker-compose.yml possiamo trovare la configurazione di tutti i nostri servizi/container.

version: '2'

services:
  php:
    build:
      context: ./php/

    volumes:
      - ../:/code

    ports:
      - "8080:8000"

    links:
      - db
      - redis
      - mailhog

    environment:
      - DB_HOST=db
      - DB_DATABASE=db
      - DB_USERNAME=root
      - DB_PASSWORD=root

  db:
    build:
      context: ./mariadb

    ports:
      - "3306:3306"

  redis:
    image: "redis:alpine"

  mailhog:
    build:
      context: ./mailhog

    ports:
      - "8081:80"

Il punto chiave di questa configurazione sono le chiavi sotto services:

php:
    build:
      context: ./php/

    volumes:
      - ../:/code

    ports:
      - "8080:8000"

    links:
      - db
      - redis
      - mailhog

    environment:
      - DB_HOST=db
      - DB_DATABASE=db
      - DB_USERNAME=root
      - DB_PASSWORD=root

Qui stiamo definendo un servizio di nome php:

  1. il cui Dockerfile è presente nella folder ./php/
  2. con cui shariamo il contenuto della folder .. nella folder /code del container
  3. che linkiamo ai servizi db, redis e mailhog
  4. a cui bindiamo la porta locale 8080 del host verso la porta 8000 del container
  5. e a cui passiamo alcune variabili d’ambiente

Il link dei servizi (15-17) è necessario per permettere al container php di poter comunicare con i container degli altri servizi.
Per maggiori dettagli sulla sintassi di docker-compose vi rimando alla documentazione ufficiale.

Up&Running

Come ultimo step ci basterà eseguire:

$ docker-compose up -d 

docker-compose si preoccuperà di buildare e avviare i singoli container, configurare la rete e montare lo share in modo che il nostro progetto sia disponibile nella folder /code del container php.

A questo punto potremo visualizzare l’url localhost:8080 per accedere al nostro progetto all’interno del container.

Leave a Reply

Your email address will not be published. Required fields are marked *