Desarrollo rápido con docker-compose y docker Swarm
En este taller comprobarás la rapidez con la que podemos crear un entorno de trabajo con Docker-compose. Además,...
Aprende cómo arrancar un entorno LAMP con Docker Compose para que construyas tus aplicaciones sobre un sistema distribuido organizado de una forma óptima.
Aprende cómo arrancar un entorno LAMP con Docker Compose con unos sencillos pasos y explicada de la mejor manera para que construyas tus aplicaciones sobre un sistema distribuido bien organizado.
Por supuesto, mi intención además de proponerte la idea, es proporcionarte las herramientas para que puedas ejecutar el entorno LAMP sobre Docker, usando Docker Compose, sin importar en que sistema operativo o distribución estés utilizándolo, a fin de cuentas, se trata de contenedores y obviamente, será ejecutado sobre Docker.
No hace falta que lo diga, pero esta infraestructura que te enseñaré a montar, también lo puedes ejecutar en cualquier proveedor de nube, bien pudiendo ser los más populares y potentes: AWS, Azure, GCP y otros donde se pueda tener acceso a un VPS.
Si te ha llamado la atención este contenido, pero aún no conoces mucho sobre Docker, igualmente, con toda honestidad te recomiendo el excelente Curso de introducción a Docker. Sin embargo, si ya dominas algunas cosas y deseas continuar explorando soluciones más complejas, por supuesto, no debes faltar en el Curso de docker para desarrolladores del experto en la materia, el Ing. Pablo Chico.
Porque pienso de verdad, que es la manera de ir escalando en tu nivel de conocimiento y de acción para desarrollar software.
Usualmente, si escribes tu código en un sistema operativo GNU/Linux, entonces utilizaras el mismo Stack, me refiero a LAMP, donde instalas todos los recursos (paquetes) de forma independiente para levantar un proyecto sobre el servidor Apache. Por otro lado, si escribes tu código sobre Windows, tendrás opciones populares cómo: WAMP Server, XAMPP, etc.
Para cualquier caso, XAMPP es funcional tanto para GNU/Linux como para Windows.
Así que, si eres un PHPero, necesitarás un Stack mínimo que contenga Apache, PHP y MySQL/MariaDB para ejecutar tu aplicación.
Por ende, las pilas:
Ahora en día, estamos inmersos en un avance incontrolable en la tecnología, que no permite que descanses si quieres mantenerte actualizado. Es cuando miramos que muchos sistemas, para desplegarlos en producción o en un punto de desarrollo, se mantienen sistemas homogéneos y estructurados, es donde la infraestructura como código toca a la puerta, brindando facilidades en automatización de procesos.
Si estás usando Docker, perfectamente puedes prescindir de las pilas anteriormente mencionadas, excepto, LAMP, que es el término general donde se representa cada servicio. Pero tú dirás ¿pero en Linux? a lo cual te diré que sí, porque el contenedor donde se instalarán los servicios será en GNU/Linux, en una distro que te brindará rapidez y optimización para con los recursos a instalar.
Propongo Docker por la contenerización, de formar un ambiente donde tu aplicación no falle por temas de dependencias y que tengas un script fiable a la mano que siempre puedas correr. Además, te familiarizas más con los sistemas GNU/Linux y shell scripting.
En principio, se sabe que docker utiliza un fichero para automatizar la creación de imágenes que se lee desde un archivo Dockerfile
. Siendo este un documento de texto que contiene todos los comandos que un usuario puede llamar desde línea de comandos para ensamblar una imagen.
Docker Compose es una herramienta que permite definir y ejecutar aplicaciones Docker compuesto por varios contenedores, simplificando el uso de Docker y entender de una manera sencilla.
Docker Compose permite un tipo de sintaxis más elaborado y fácil de entender, por tal razón le ha ganado la batalla en la composición de scripts para contenerización. El fichero de instrucciones que utiliza Docker Compose es docker-compose.yml
haciendo diferencia con el fichero .Dockerfile
.
Una pila es un conjunto de servicios o paquetes instalables y que se relacionan entre si. En el siguiente diagrama se puede observar una pila LAMP (GNU/Linux, Apache, MySQL y PHP).
Como descripción básica, nos damos cuenta que en primera instancia tenemos 3 contenedores que conforman un sistema distribuido, todos ellos interconectados entre sí. Cada contenedor tiene servicios distintos que hará que la pila LAMP se constituye por medio de una red local.
Servidor web:
www
.80
.Servidor de base de datos:
db
.3306
.Servidor del sistema gestor de base de datos gráfico:
phpmyadmin
.8000
.Se procede a descargar el repositorio docker-lamp que se encuentra en GitHub, de la siguiente manera.
git clone https://github.com/jersonmartinez/docker-lamp.git
En mi caso lo he dejado en Documents/OpenWebinars/docker-lamp
.
La estructura del proyecto es la siguiente:
Ahora bien, hagamos una inspección rápida de los ficheros de configuración que tenemos en este repositorio.
En este sencillo dockerfile
logramos observar que requerimos una imagen de php
en la versión 8.0.0
con apache
.
Se define un argumento donde se modifica una variable de entorno DEBIAN_FRONTED
a modo no interactivo, que lo define para que los demás paquetes de instalación en consecuencia que soliciten una confirmación de algo en ejecución, lo omitan.
Las demás ejecuciones ya son para instalar extensiones de comunicación con docker
, php
y mysqli
, así como las actualizaciones del repositorio de paquetes y por último la instalación de librerías y dependencias.
FROM php:8.0.0-apache
ARG DEBIAN_FRONTEND=noninteractive
RUN docker-php-ext-install mysqli
RUN apt-get update \
&& apt-get install -y libzip-dev \
&& apt-get install -y zlib1g-dev \
&& rm -rf /var/lib/apt/lists/* \
&& docker-php-ext-install zip
RUN a2enmod rewrite
Finalmente, el mágico fichero de configuración de Docker Compose. En este punto, encontramos 3 bloques importantes donde se definen los servicios: www
, db
y phpmyadmin
.
Si analizan la configuración, pueden observar que es tan sencillo que se explica solo, incluso porque antes he explicado un poco el diagrama de stack LAMP y de los servicios como tal.
version: "3.1"
services:
www:
build: .
ports:
- "80:80"
volumes:
- ./www:/var/www/html
links:
- db
networks:
- default
db:
image: mysql:8.0
ports:
- "3306:3306"
command: --default-authentication-plugin=mysql_native_password
environment:
MYSQL_DATABASE: dbname
MYSQL_USER: root
MYSQL_PASSWORD: test
MYSQL_ROOT_PASSWORD: test
volumes:
- ./dump:/docker-entrypoint-initdb.d
- ./conf:/etc/mysql/conf.d
- persistent:/var/lib/mysql
networks:
- default
phpmyadmin:
image: phpmyadmin/phpmyadmin
links:
- db:db
ports:
- 8000:80
environment:
MYSQL_USER: root
MYSQL_PASSWORD: test
MYSQL_ROOT_PASSWORD: test
volumes:
persistent:
Se utiliza la versión de Docker Compose que pueda darle ejecución a la versión 3.1
. La versión 1.21 de docker compose viene bien. Para conocer este dato, solo deben escribir:
docker-compose -v
Los contenedores se catalogan como servicios. En esta configuración son 3 y la explicación de cada uno de los bloques es la siguiente:
www
Si hay algo que falta por comentar, por supuesto, serán los atributos:
build
tiene como valor .
, indicando que se construirá el .dockerfile
sobre este contenedor.ports
mantendrá el mismo puerto con que el servicio internamente está corriendo, que es el 80
y será expuesto hacia afuera.volumes
aplica una definición de donde sincronización entre 2 directorios o volumen de datos, para ello, se sincroniza ./www
con /var/www/html
que se encuentra en el contenedor.links
selecciona con quien podrá verse y compartir recursos en red, para ello es necesario que el servidor web esté conectado al sistema gestor de base de datos que se encuentra en el contenedor db
.networks
define el nombre de la red por la cual estará conectados los contenedores, para este caso default
.
www:
build: .
ports:
- "80:80"
volumes:
- ./www:/var/www/html
links:
- db
networks:
- default
Es habitual que cambiemos el puerto 80 que se expone, pues muchas veces tenemos aplicaciones que ya están corriendo sobre ese puerto. Esto, para tenerlo en cuenta si algo falla.
db
Este bloque tiene un poco más de atributos que revisar, como los siguientes:
build
, dando a entender que no es necesario instalar paquetes desde un .dockerfile
como si lo necesitaba el contenedor www
.image
selecciona la de mysql
en la versión 8.0
.ports
mantendrá el mismo puerto con que el servicio internamente está corriendo, que es el 3306
y será expuesto hacia afuera.command
es funcional para que se inserte un comando, donde dicha instrucción será para habilitar la autenticación con la contraseña nativa de MySQL.environment
es la aplicación de variables de entorno, donde este contenedor recibe 4 con el prefijo de MYSQL_
donde escribe el nombre de la base de datos, nombre de usuario y contraseña.volumes
aplica una definición de donde sincronización entre ficheros, así como la configuración y donde corre el demonio de MySQL.networks
define el nombre de la red por la cual estará conectados los contenedores, para este caso default
, donde ya se puede conocer con el contenedor www
.
db:
image: mysql:8.0
ports:
- "3306:3306"
command: --default-authentication-plugin=mysql_native_password
environment:
MYSQL_DATABASE: dbname
MYSQL_USER: root
MYSQL_PASSWORD: test
MYSQL_ROOT_PASSWORD: test
volumes:
- ./dump:/docker-entrypoint-initdb.d
- ./conf:/etc/mysql/conf.d
- persistent:/var/lib/mysql
networks:
- default
Desde esta configuración, ya se importa la base de datos que se encuentra en dump\dbname.sql
.
Es habitual que cambiemos el puerto 3306 que se expone, pues muchas veces tenemos aplicaciones que ya están corriendo sobre ese puerto. Esto, para tenerlo en cuenta si algo falla.
Se hace notar que en esta configuración tampoco existe el atributo links
para conectar con algún otro contenedor. Esto pasa porque el contenedor donde se encuentra el sistema gestor de base de datos, en este caso MySQL, quedará aislado, proveyendo seguridad en su acceso y ortogándoselo a los que realmente necesitan hacer consultas, tal como el contenedor de www
y phpmyadmin
.
phpmyadmin
Este bloque tiene menos atributos y básicos como los que ya hemos abordado:
image
selecciona la de phpmyadmin/phpmyadmin
.ports
es diferente a los demás, porque internamente el servicio está funcionando con el puerto 80
, pero al exponerlo se necesita hacer con otro, puesto que colisionaría con el puerto que tiene expuesto el contenedor del servidor web www
. De este modo, se expone el puerto 8000
.links
se conecta con el contenedor db
para tener acceso al sistema gestor de base de datos.environment
es la aplicación de variables de entorno, donde este contenedor recibe 3 con el prefijo de MYSQL_
donde escribe el nombre de usuario, contraseña y contraseña de root.
phpmyadmin:
image: phpmyadmin/phpmyadmin
links:
- db:db
ports:
- 8000:80
environment:
MYSQL_USER: root
MYSQL_PASSWORD: test
MYSQL_ROOT_PASSWORD: test
Todos los volúmenes se encuentran en modo persistente, por lo que no hay pérdida de datos y de enlace.
Este es el .sql
que se importa a MySQL.
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
CREATE TABLE `Data` (
`id` int(11) NOT NULL,
`name` varchar(20) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `Data` (`id`, `name`) VALUES (1, 'OpenWebinars Article'), (2, 'Crashell'), (3, 'Jerson Martinez'), (4, 'Antonio Moreno');
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
Este trozo de código php
ubicado en www/index.php
es para comprobar que el sitio carga bien y que existe correcta conectividad con la base de datos y que este puede dar lectura.
<html>
<head>
<title>Welcome to LAMP Infrastructure</title>
<meta charset="utf-8">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container-fluid">
<?php
echo "<h1>¡Hola, OpenWebinars te da la bienvenida!</h1>";
$conn = mysqli_connect('db', 'root', 'test', "dbname");
$query = 'SELECT * From Data';
$result = mysqli_query($conn, $query);
echo '<table class="table table-striped">';
echo '<thead><tr><th></th><th>id</th><th>name</th></tr></thead>';
while($value = $result->fetch_array(MYSQLI_ASSOC)){
echo '<tr>';
echo '<td><a href="#"><span class="glyphicon glyphicon-search"></span></a></td>';
foreach($value as $element){
echo '<td>' . $element . '</td>';
}
echo '</tr>';
}
echo '</table>';
$result->close();
mysqli_close($conn);
?>
</div>
</body>
</html>
A partir de este punto, necesitaremos ejecutar todas las instrucciones de consola con privilegios elevados, para ello, un sudo su
y poner su contraseña bastará.
Para lanzar la configuración, se ejecuta la siguiente instrucción:
docker-compose up -d
Como pueden observar en la imagen, los datos resultantes son de que se crean 3 contenedores, en principio con los prefijos docker-lamp_
que es el directorio donde se encuentra, procediendo a concatenar el nombre del contenedor y el sufijo _1
con resultado done
.
Para verificar los contenedores corriendo desde Docker Compose:
docker-compose ps
Es notable un mayor detalle del estado como de los puertos expuestos, así como el protocolo y la dirección local ::1
, 127.0.0.1
o localhost
por medio de 0.0.0.0
. El comando docker-compose ps
es equivalente a docker ps
, solo que este último con mayor detalle.
Con esto bastará para hacer la prueba en un navegador y escribir 127.0.0.1
, equivalente a 127.0.0.1:80
y localhost:80
con el puerto opcional.
Se procede a realizar una consulta a la dirección 127.0.0.1:8000
para llegar al contenedor phpmyadmin
. El usuario y la contraseña han sido definidos en el .yml
.
Se comprueba que el acceso ha sido correcto. Por otro lado, se verifica que la base de datos se encuentra bien importada con su respectiva tabla y datos dentro, listo para ser gestionada.
A partir de acá, el proyecto que vayas a trabajar, tendrá que colocarlo dentro del directorio www/
, por ejemplo, si tu proyecto se llama Crashell
, lo revisarás en tu navegador como 127.0.0.1/Crashell
.
Para detener el stack con Docker Compose, es de esta manera:
docker-compose stop
Así de fácil.
Conceptualmente y prácticamente ha sido abordado el tema, de una forma meticulosa para que puedas arrancar con tus proyectos web de una forma más profesional, dando el siguiente paso con Docker utilizando Docker Compose y con ello, personalizando tu stack LAMP para tus desarrollos.
Ya con esto, podemos firmar que en producción también funciona.
También te puede interesar
En este taller comprobarás la rapidez con la que podemos crear un entorno de trabajo con Docker-compose. Además,...
Aprende a realizar de forma correcta la instalación y el despliegue de un servidor LAMP en un sistema Linux, te lo contamos...