Docker: PHP y MySQL
docker-compose
Last updated
Was this helpful?
docker-compose
Last updated
Was this helpful?
Utilizaremos a modo de ejemplo la creación de varios contenedores relacionados entre sí, para levantar un sitio web programado con PHP, que se conecta a una DB en MySQL. De hecho, voy a utilizar una actividad llamada LoginRegister
realizada en 1º año de Asix. Para ello necesitamos los servicios activos de:
Apache o Nginx
para levantar el servicio web
MySql
para la base de datos
PHP
para el lenguaje de programación
Phpmyadmin
, si me quiero conectar a un gestor de DB.
Veamos cómo levantar un docker-compose
creando un archivo de configuración docker-compose.yml
, dado que el docker-compose
busca, por defecto, las instrucciones en el archivo docker-compose.yml
.
Adicionalmente, tengamos en cuenta que docker lo tengo instalado en una VM con Ubuntu Desktop 22.04 LTS
con Portainer
y Docker-compose
.
Como vamos a crear los volúmenes de Docker para tener acceso directo a los contenidos en local, tenemos que crear los directorios y los contenidos necesarios. Los archivos importantes a tener en cuenta serían los ficheros de configuración de nginx y los .php de la aplicación web. Para ello, he creado un directorio con los contenidos necesarios:
Directorio
Contenido
LoginRegister
La aplicación web con sus archivos .php, .css, etc.
DB
La DB users1
que utiliza la aplicación web. Realmente no es necesario, lo hago por comodidad.
log
Para almacenar los log de nginx (error, access) y de php.
Nginx/conf.d
En este directorio guardamos el archivo de configuración: default.conf
La actividad LoginRegister
tiene una estructura de archivos como se muestra en la imagen siguiente. Tener en cuenta que el directorio mysql
no es necesario.
Tenemos que preparar dos archivos de configuración:
default.conf
docker-compose.yml
En este archivo tenemos las siguientes directivas:
Listen - define qué dirección IP y qué puertos escucha el servicio. En este caso, Nginx escucha en el puerto 80 en todas las direcciones IPv4 e IPv6. Si establecemos el parámetro default_server
le indicamos a Nginx que utilice este bloque server por defecto para las peticiones que coincidan con las direcciones IP y los puertos.
server_name - define los nombres de host de los que es responsable este bloque server. Establecer server_name
a _ permite configurar Nginx para aceptar cualquier nombre de host para este bloque server.
root - establece la ruta del contenido web para este bloque server.
log - También hemos configurado los archivos para los log files, que utilizaremos también dentro de los volúmenes de docker.
Aquí dejo como ejemplo el archivo que he utilizado:
Del mismo modo que existen los Dockerfile
, donde se puede configurar el estado de un contenedor de manera declarativa, en docker-compose existe el equivalente: los archivos .yml
.
Por tanto, un archivo de docker-compose es un archivo con extensión y formato yml. Para usarlo basta con crearlo y empezar a agregar el contenido.
El archivo tiene una estructura bastante fácil de entender. Comienza por especificar la versión de docker compose que se utilizará:
Después de la versión viene la sección de servicios. Puede haber tantos servicios como queramos: servidor web, base de datos, documentación, etc. Cada servicio cuenta con sus propias variables de configuración y sus respectivos valores.
version 3.8: Es muy importante indicar la versión de las instrucciones que vamos a utilizar. Docker evoluciona, pero siempre hay compatibilidad con las versiones anteriores.
app: Indica el nombre del servicio, que podría ser cualquiera. El nombre indica el tipo de servicio que estamos construyendo. Por ejemplo: MySQL, Nginx, etc.
Nombres de servicios: El nombre que usamos para cada servicio dentro de nuestro archivo yml
nos sirve como referencia para su uso en otros servicios.
Por ejemplo, si llamamos a un servicio como db
, entonces es db
el nombre que debemos usar en otras aplicaciones para referirnos a un host o ubicación, incluso una base de datos. Veamos algunas de las variables de configuración (que se pueden consultar en documentación oficial de Docker).
image: establece la imagen a partir de la cual se generará el servicio, ideal cuando el servicio no necesita de una personalización muy complicada.
build: si necesitamos una imagen personalizada pudiera ser mejor usar un Dockerfile. La opción build nos permite indicar el directorio donde se encuentra. Indica dónde está el Dockerfile a utilizar para crear el contenedor. Si escribimos build .
se considera que el Dockerfile está en el directorio actual.
command: sobre escribe el comando predeterminado del contenedor. Esta opción es ideal para ejecutar un comando cuando inicia un servicio, por ejemplo, un servidor web.
ports: nos dice los puertos externos e internos que se vincularán, siempre en el formato de host:contenedor
. También podemos especificar los protocolos udp
o tcp
.
expose: también expone puertos. La diferencia con el comando ports
es que los puertos solo estarán disponibles para los servicios vinculados, no para la máquina desde donde estamos ejecutando docker-compose
.
depends_on: Si queremos que uno de nuestros servicios se ejecute después de otro. Por ejemplo, para que un servidor web funcione correctamente es necesario tener una base de datos que ya se encuentre en funcionamiento.
volumes: Se puede enviar partes de nuestro S.O a un servicio usando uno o varios volúmenes. Para esto usamos la sintaxis host:contenedor
, donde Host
puede ser una ubicación en tu sistema o también el nombre de un volumen que hayas creado con docker. Hace un mapeo entre el directorio del host y el directorio del contenedor. De este modo, cualquier cambio en el directorio local en el host, se hará de inmediato en el contenedor.
restart : Podemos aplicar políticas de reinicio a nuestros servicios. Puede tomar varios valores:
no: nunca reinicia el contenedor
always: siempre lo reinicia
on-failure: lo reinicia si el contenedor devuelve un estado de error
unless-stopped: lo reinicia en todos los casos excepto cuando se detiene
A continuación, un ejemplo del archivo docker-compose.yml
que he utilizado:
Como podemos ver tenemos que utilizar la imagen de PHP, FPM - FastCGI Process Manager
que es una implementación alternativa al PHP FastCGI con algunas características adicionales (la mayoría) útiles para sitios web con mucho tráfico.
Un par de características que posee:
Manejo avanzado para detener/arrancar procesos de forma fácil.
Posibilidad de iniciar hilos de procesos con diferentes uid/gid/chroot/environment, escuchar en diferentes puertos y usar distintos php.ini (remplazando).
Ahora es que estamos en condiciones de crear nuestro docker-compose. Para ello nos vamos a Portainer.
Nos vamos a la herramienta stacks de Portainer, donde podremos crear nuestra "composición" de servicios. Recordemos que un stack es una colección de servicios que están relacionados con una aplicación, como por ejemplo, WordPress que incluye un contenedor de servidor web (como nginx o apache) y un contenedor de base de datos como MySQL.
Una vez en el apartado vamos a crear un nuevo stack:
Se nos abrirá una nueva página donde podemos aplicar diferentes opciones para crear una colección entre las que tenemos subir nuestro docker-compose.yml, usar un repositorio de git. Aquí utilizaremos el editor web:
En el editor web volcamos el contenido de nuestro archivo docker-compose.yml
previamente creado. En caso de tener algún aparecerá una notificación en rojo que nos impedirá continuar
Una vez hecho esto, clicamos a deploy
para crear y desplegar todos los contenedores. Si todo está correcto, nos crea la colección y podremos acceder a la misma y veremos algo como lo siguiente:
Podemos observar los diferentes contenedores involucrados en desplegar la aplicación web:
miAppPHP - es el contenedor de php
miAppPhpMyAdmin - el contenedor para el gestor de bases de datos
miAppNginx - el servidor web
miAppMySQL - La base de datos
environment: Permite establecer una lista de que estarán disponibles en nuestro servicio.
BASH_VERSION: versión de que estemos utilizando.
***