¡Feliz año nuevo, querido lector! Espero que hayas pasado unas fantásticas navidades y que la resaca de hoy no sea demasiado dura. Yo, por mi parte, he decidido empezar el año con fuerza y traerte lo que hace unas semanas os prometí por Twitter: un tutorial para desarrollar en WordPress con Docker.
Y es que después de haber usado el típico LAMP (Linux + Apache + MySQL + PHP) y estar harto de pelearme con configuraciones y tener todas las instalaciones conviviendo y compartiendo recursos; después de haber probado Vagrant y haber sufrido su lentitud (supongo que ejecutarlo sobre Virtual Box en un ordenador que pronto cumplirá los 6 añitos no es la mejor idea); después de ver cómo Antonio disfruta desarrollando con Local by Flywheel mientras a mí me tocaba esperar a que se dignaran a sacar una versión para Linux… Después de todas estas penas, decidí que ya había llegado el momento de aprender cómo funciona Docker y cómo montar entornos de desarrollo rápidos, cómodos y multiplataforma con él.
Si quieres aprender un poquito sobre Docker y quieres poder usarlo en tu día a día, sigue leyendo. Te recomiendo que leas toda la entrada, porque no es hasta el final de la misma donde te explicaré cómo uso yo Docker exactamente. ¡Vamos allá!
Docker
Docker es un programa que permite empaquetar software en «contenedores» y ejecutarlos encima de máquinas virtuales. Hasta aquí, no difiere mucho de otras soluciones como Vagrant. La ventaja de esta forma de proceder (la cual podríamos comparar con, por ejemplo, el clásico LAMP o MAMP o WAMP) es que los contenedores se ejecutan en entornos aislados, de tal forma que:
- un contenedor no puede, en principio, acceder a otro, lo cual aumenta la seguridad del sistema,
- todas las herramientas, librerías, ficheros de configuración, etc. que necesita el contenedor para funcionar están empaquetados en él mismo, con lo que no «ensucian» nuestro ordenador con software innecesario ni aparecen incompatibilidades entre ellos.
En mi opinión, la ventaja de Docker sobre otros softwares para ejecutar contenedores es que por defecto usa runC como entorno de virtualización, con lo que todo el software que se ejecuta en el contenedor es gestionado por el sistema operativo del anfitrión. En otras palabras, se comparten un montón de recursos entre el anfitrión (nuestro ordenador) y el huésped (el contenedor que ejecutamos) y, por lo tanto, todo es mucho más rápido y eficiente. Ideal para un ordenador de 2013 como el mío ?
Instalación de Docker
Para instalar Docker en Linux (Debian/Ubuntu), lo único que tenemos que hacer es ejecutar el siguiente comando en una consola:
y esperar a que acabe el proceso.
Un pequeño inconveniente de Docker es que, por defecto, para poder usarlo deberás ejecutarlo con permisos de administrador usando sudo
. Pero, tal y como nos cuentan en la propia documentación del proyecto, basta con que añadamos nuestro usuario en el grupo docker
para no tener que usar sudo
cada vez:
cambiando your-user
por el nombre de tu usuario (usuario del sistema operativo, ¿eh?). Por cierto, es posible que tengas que cerrar tu sesión en el sistema operativo y volver a iniciarla para que te aparezca el nuevo grupo y puedas usar docker
sin sudo
.

Nelio Content
Estoy tan contento con Nelio Content que parece que me hayan pagado para hablar bién de él… pero es que también a ti te encantará: funciona como prometen, la programación automática de mensajes es increíble, la calidad/precio no tiene parangón y su equipo de soporte se siente como si fueran parte del tuyo.

Panozk
Cómo instalarlo en Mac o en Windows
Si estás usando alguno de estos otros dos sistemas operativos, aquí te dejo un par de enlaces sobre cómo instalarlo en ellos:
Cómo usar Docker
Vale, ahora que ya tenemos Docker en nuestro ordenador instalado y listo para ser usado es el momento de probarlo. Como te decía, Docker es una herramienta que nos permite lanzar aplicaciones empaquetadas en contenedores. Para ello, deberemos ejecutar el siguiente comando desde un terminal:
Por ejemplo, el primer comando que podemos ejecutar es:
para ver la aplicación clásica de «Hola Mundo» ejecutándose dentro de un contenedor Docker. Si echamos un vistazo a la salida que vemos por terminal, lo primero que veremos es esto:
Lo que nos está diciendo esto es que no teníamos ningún contenedor llamado hello-world
en local y, por lo tanto, Docker ha dado por sentado que tenía que ir a buscarlo al repositorio de contenedores que tiene, decargarlo y montarlo en local para ejecutarlo. Y con esto descubrimos uno de los primeros aspectos interesantes de Docker: existe un repositorio de contenedores que podemos usar, parecido a los directorios de plugins o temas que tenemos en WordPress.
Finalmente, vemos que el resto de la salida que tenemos en nuestro terminal es:
el cual se corresponde a la ejecución en sí del contenedor «Hola Mundo». Y si ahora volviéramos a ejecutar el comando anterior, veríamos únicamente el resultado del contenedor (nos ahorraríamos la parte de descargarlo, vaya).
Y esto es así porque, aunque no lo veamos, el contenedor está instalado y configurado en Docker. Si ejecutamos:
veremos cómo aparece creado el contenedor que acabamos de descargarnos y ejecutar (y que, por cierto, ya no está en ejecución):
Para borrarlo, basta con ejecutar:
y listo. Por cierto, fíjate que el numerito que he puesto se corresponde con el CONTAINER ID
del contenedor.
Entonces, ahora que ya entiendes un poco cómo funciona Docker, vamos a ver qué es Docker Compose y por qué vamos a usarlo con WordPress.
Docker Compose
Como puedes imaginar, en el repositorio de contenedores de Docker existe un contenedor (varios, de hecho) de WordPress. Dicho contenedor tiene varios inconvenientes:
- Por un lado, con él sólo no podremos ejecutar WordPress, ya que no incluye la base de datos. Así que si queremos usar WordPress debemos tener corriendo una base de datos en nuestro propio ordenador, en otra máquina o, ¿cómo no?, en otro contenedor.
- Por otro lado, el contenedor de WordPress dispone de varios parámetros de configuración que debemos especificar para que funcione (por ejemplo, dónde está la base de datos y qué credenciales usar para conectarse a ella).
Gestionar docker
a pelo es un poco tedioso: tienes que levantar los contenedores en orden, meter los parámetros de configuración por línea de comandos, etc. Por suerte, existe una herramienta llamada docker-compose
que nos permite crear un fichero de configuración con todos los contenedores que queremos levantar, establecer las dependencias entre ellos y configurarlos individualmente. Veamos un ejemplo sencillo.
Empecemos por crear un directorio vacío donde meter el fichero de configuración. Por ejemplo, crea el directorio ~/docker/test
y añade un fichero de texto plano llamado docker-compose.yml
con el siguiente contenido:
No te asustes, que se trata de un fichero muy sencillo. Fíjate bien. En él definimos dos servicios: mysql
y wordpress
. En el primer servicio (mysql
) indicamos la imagen que queremos descargarnos (un MySQL versión 5.7) y algunos parámetros de configuración. Los más relevantes son la redirección de puertos (del 8081 del anfitrión al 3306 del huésped) y parámetros de la base de datos en sí (usuario, contraseña, etc).
El segundo servicio es WordPress (wordpress
) y sigue un patrón parecido. Aquí, por ejemplo, indicamos que queremos usar el puerto 8080 para acceder a nuestro WordPress. También especificamos que mysql
es una dependencia de WordPress (este contenedor no puede funcionar sin el otro). Y también indicamos parámetros adicionales como, por ejemplo, dónde está la base de datos y cómo acceder a ella.
Una vez tenemos el fichero listo, ejecutamos:
y Docker se descargará las imágenes de WordPress y MySQL (si no las tenemos ya) y pondrá en marcha nuestro WordPress.
Cuando esté listo (dale un momento, porque a veces tarda un poco en tenerlo todo en marcha), podremos ir a nuestro navegador web y en la dirección http://localhost:8080
(fíjate que es el mismo puerto que hemos puesto en el fichero de configuración) encontraremos nuestro WordPress esperándonos para completar su instalación:

A partir de este punto, si quieres nuevos WordPress en paralelo, sencillamente tendrías que repetir el proceso. Es decir, creas un nuevo directorio en ~/docker/
, añades el fichero docker-compose.yml
, cambias los puertos para acceder a él (por ejemplo, 8082
para WordPress y 8083
para MySQL) para que no colisione con el contenedor que ya tenemos en marcha y lo pones a correr también.
Cuando acabes de trabajar, puedes ejecutar:
para detener la instancia. ¡Cuidado! Si en lugar de stop
usaras down
:
también detendrías la instancia pero, además, se eliminaría, con lo que la próxima vez que hicieras el docker-compose up
empezaría todo el proceso de cero (base de datos vacía, WordPress sin instalar, etc).
Docker y el desarrollo en WordPress
Llegados a este punto, ya casi tienes todo lo necesario para desarrollar un plugin o un tema WordPress con Docker. Espero que las explicaciones que te he dado hasta aquí te hayan ayudado a entender un poco mejor cómo funciona Docker.
Ahora, pues, es hora de que te presente exactamente la configuración que uso yo para desarrollar en WordPress con Docker. En concreto, se trata de una configuración que soluciona los dos únicos puntos que quedan por tratar:
- ¿Cómo puedo hacer que el proyecto en el que estoy trabajando esté dentro del contenedor Docker?
- ¿Puedo usar nombres de dominio del tipo
http://content.local
en lugar dehttp://localhost:puerto
con Docker?
Pues vamos a responder estas dos cuestiones y, ahora sí, ya tendrás todos los ingredientes para crear entornos de desarrollo WordPress en Docker como un campeón.
Cómo meter mi proyecto dentro de Docker
En mi caso, cuando monto un entorno de desarrollo en WordPress es para desarrollar un nuevo plugin. En este caso, lo que a mí me gustaría es que mi plugin estuviera dentro de la carpeta wp-content/plugins/
del entorno de desarrollo. Por desgracia, aún no hemos visto cómo hacer que el directorio (que, recordemos, está dentro del contenedor huésped) esté visible desde el sistema de archivos de mi ordenador anfitrión.
Aunque hay varias opciones sobre qué contenidos del contenedor están mapeados a una carpeta de mi ordenador (que los tengo disponibles, vaya), la que más me gusta a mí es la que mapea la carpeta de mi plugin a una carpeta del plugin dentro del contenedor. Veamos cómo lograrlo.
Supongamos que estoy desarrollando mi plugin en ~/dev/nelio-content/
. Como quiero poder usar mi plugin Nelio Content en un entorno de desarrollo Docker, lo primero que haré será añadir el ya famoso fichero docker-compose.yml
con todo lo que hemos visto hasta ahora. Pero ojo, esta vez tendrá algún parámetro de configuración extra:
¿Ves cuál es la diferencia? Sencillamente he añadido una nueva opción en el servicio WordPress llamada volumes
en la que le digo el directorio actual (identificado por el punto .
) lo tienes que mapear (indicado por los dos puntos :
) al directorio /var/www/html/wp-content/plugins/nelio-content
(que es donde está instalado WordPress, seguido de wp-content/plugins/
y seguido del nombre de mi propio plugin). Fíjate que la sintaxis es la misma que cuando mapeábamos los puertos.
Y ya está, haciendo esto conseguimos que nuestro plugin aparezca dentro del WordPress que acabamos de «crear». Yendo al Escritorio » Plugins podemos activarlo y ver qué tal funciona en un entorno seguro y aislado.
Cómo usar nombres de dominio
Entrar en las instalaciones de desarollo usando localhost y números de puerto es bastante pesado; es muchísimo más cómo usar un nombre de dominio del tipo http://content.local
. Para ello necesitaremos realizar algunos pasos extra, pero una vez lo tengas montado ya todo será muy sencillo.
Lo primero que necesitamos es decirle al ordenador que un cierto nombre de dominio (por ejemplo, content.local
) está en el propio ordenador. Para ello, editamos el fichero /etc/hosts
(como sudo
) y añadimos la línea que indica esto:
A continuación necesitamos un proxy que sepa que cuando nos llega una petición a http://content.local
, queremos que sea atendida por http://localhost:8080
. Esto es muy sencillo de montar (en serio). Sencillamente crea una nueva carpeta ~/docker/proxy
con el siguiente fichero de configuración docker-compose.yml
:
A continuación, ejecuta docker network create proxy
y pon en marcha el nuevo contenedor con docker-compose up -d
. Esto creará una nueva red que todos nuestros proyectos usarán (en un par de párrafos te explico qué es esto) y pondrá en marcha el contenedor que traduce nombres bonitos a localhost con puerto.
Finalmente, lo único que tenemos que hacer es modificar la configuración de nuestro proyecto (el que habíamos creado en el apartado anterior) para que, cuando se ponga en marcha, avise a nuestro proxy de que está disponible para atender peticiones y bajo qué dominio lo va a hacer:
Soy consciente de que parece un poco magia negra, pero no lo es. Si te fijas, lo único que hemos añadido en nuestro Docker son las siguientes cosas:
- En la configuración de WordPress, en el apartado
environment
, hemos añadido dos nuevos parámetros:VIRTUAL_HOST
yVIRTUAL_PORT
. Estos dos atributos son los que se le pasarán al contenedor del proxy para que se pueda auto-configurar y sepa que las peticiones ahttp://content.local
tienen que ir ahttp://localhost:8080
. - Como queremos que WordPress pueda comunicarse con el proxy, tenemos que meter a los dos en la misma red. Esto lo hacemos metiendo la opción
networks
en el servicio WordPress e indicando que WordPress está en la red llamadafrontend
(podría haberle puesto el nombre que me diera la gana). Por otro lado, al final del documentodocker-compose.yml
especificamos que dicha red es externa y su nombre (proxy
), lo cual se corresponde con la red que habíamos metido en el contenedor que hemos creado en~/docker/proxy
y que hemos llamado proxy. - Finalmente, metemos a la base de datos y al propio WordPress en otra red privada para ellos dos, que hemos llamado
backend
. Esto permite que WordPress se comunique con MySQL pero que nadie se meta en medio.
¡Y eso es todo! Espero que te haya gustado la entrada de hoy y, si tienes cualquier duda o te atascas en cualquier punto, aproveches la sección de comentarios para preguntar.
Imagen destacada de Abigail Lynn.
Deja una respuesta