Contenido

LAMP con Docker

Hace algún tiempo que escribí los artículos LAMP con Puppet y LAMP con Salt. Desde entonces ha llovido mucho y… bueno, creo que los sistemas tipo Salt y Puppet están casi obsoletos, gracias a nuevas tecnologías como Docker.

Pero antes de criticarme por esa afirmación, ruego al lector que se lea este artículo y luego decida por sí mismo.

Igual que en los otros ejercicios, montaremos una arquitectura LAMP (Linux + Apache + MySQL + PHP) que tan de moda ha estado durante mucho tiempo.

Containers

Código a ejecutar

Como las cosas evolucionan, PHP también lo ha hecho y el programita de ejemplo que usé ya no funciona en PHP 5.6. Así que me he visto obligado a modificar ligeramente el programa de ejemplo.

Podéis descargarlo de GitHub así:

1
$ git clone https://github.com/magmax/small_php_example.git -b mysqli

Veréis que en el directorio small_php_example tenéis un programa muy sencillito que muestra las tablas disponibles en la base de datos.

Docker para PHP con MySQL

Otro problema es que no he encontrado ninguna imagen Docker de PHP con soporte para MySQL, pero es muy sencillo construir una, así que vamos a ello. Aquí podría ayudar el artículo que escribí sobre Docker, que podéis usar para ampliar conceptos.

Necesitamos crear el fichero php.dockerfile:

1
2
FROM php:5.6-apache
RUN  docker-php-ext-install mysqli

Y ejecutar la siguiente orden:

1
docker build -t php-mysql -f php.dockerfile .

Y tendremos disponible la imagen php-mysql.

Con esto tendremos ya todas las piezas. Ahora vamos a unirlas.

Docker Compose

Existe una aplicación (Python :D) que permite gestionar grupos de Dockers llamada docker-compose. Se puede instalar en un virtualenv:

1
2
3
$ virtualenv venv
$ . venv/bin/activate
(venv) $ pip install docker-compose

A continuación necesitamos un archivo de definición. Éste es suficiente:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
version: '2'
services:
  db:
    image: mysql:5.7.11
    environment:
      - MYSQL_ROOT_PASSWORD=foo
  app:
    image: php-mysql
    ports:
      - 80:80
    volumes:
      - ./small_php_example:/var/www/html/
    depends_on:
      - db
    links:
      - db
    environment:
      - MYSQL_SERVER=db
      - MYSQL_PASSWORD=foo
      - MYSQL_USER=root

Poco que explicar… Tenemos 2 servicios: la base de datos y la aplicación. El primero usa una imagen con MySQL (definiendo la contraseña) y el segundo un Apache con PHP que monta nuestra aplicación en /var/www/html, expone el puerto del Docker 80 con el local 80 y enlaza con el primer Docker; bueno, y define algunas variables de entorno para poder conectar.

Lo único digno de explicar aquí es que al linkar la máquina se añade al /etc/hosts, por lo que tenemos acceso a la máquina usando su nombre: db. Por eso el valor de la variable MYSQL_SERVER es, simplemente, db.

Dicho de otro modo: vamos a crear dos Dockers que trabajarán juntos. Y todo con esta orden:

1
(venv) $ docker-compose up

Tardará un poquito, pero tendremos nuestra aplicación corriendo en localhost:80

Conclusiones

Ventajas sobre Puppet, Salt o Chef:

  • es más sencillo.
  • más ortogonal: se crea el Docker con órdenes típicas del sistema elegido y se usa.
  • permite mezclar distribuciones fácilmente.
  • Se pueden lanzar varias copias de un mismo Docker sobre la misma máquina.
  • Es replicable. Con los sistemas de orquestación puede cambiar una versión de una librería entre ejecuciones, haciendo que una funcione y otra falle.
  • Es más difícil que se rompa. No es extraño que la entrada de una máquina nueva en Puppet me descubra un bug en la definición.