Docker

Cómo levantar un servicio web con Docker y Docker Compose

|

Tiempo de lectura: 4 minutos

Actualizado el miércoles, 23 noviembre, 2022

Si, como yo, usas Linux en tus desarrollos, te habrás encontrado con que trabajar con las mismas versiones de software en tu sistema operativo que en producción puede llegar a ser un pequeño caos: dependencias que no puedes cumplir, no dispones de paquetería específica y acabas teniendo que compilar a mano servicios que, en muchas ocasiones, implican horas de cambios y reintentos para conseguir que todo funcione medianamente bien.

Por suerte, con la llegada de los contenedores y de Docker, muchos de estos problemas pertenecen ya al pasado. Para que veas lo sencillo que puede ser, preparamos un entorno con Apache, PHP y MySQL que puedes utilizar para probar tu web.

¿Qué es Docker?

Docker

Docker es un servicio que permite ejecutar pequeños contenedores de software sobre el núcleo de nuestro sistema operativo, por lo que es una opción más rápida y liviana que el uso de máquinas virtuales.

Por regla general, se suele empaquetar un solo servicio por contenedor, por lo que, para nuestro ejemplo, vamos a necesitar un orquestador, es decir, una herramienta que nos permita manejar en conjunto varios contenedores relacionados entre sí. De ahí el uso de Docker Compose.

Para servicios conocidos (Apache, PHP, MySQL…), tenemos contenedores oficiales disponibles en Docker Hub. Puedes distinguir fácilmente estas imágenes, puesto que están marcadas como official.

¡A jugar!

Hasta aquí la parte “aburrida”. Toca probar el juguete nuevo 😀

Vaya… No lo tengo instalado

Como ya habrás deducido, lo primero que necesitas es tener instalados Docker y Docker Compose en tu máquina. En muchas distribuciones Linux ya está incluido como parte de la paquetería disponible, por lo que podrás instalarlo desde tu herramienta de gestión de paquetería preferida. Pero, si prefieres estar a la última o no tienes disponible el paquete, siempre puedes seguir las instrucciones de la documentación:

Si usas Linux, mi consejo es que, a mayores, sigas los pasos de instalación adicionales. Te ayudarán, por ejemplo,  a no depender de ser root, o de utilizar sudo, incluyendo a tu usuario en el grupo de Docker.

Ahora que ya tengo Docker, ¿cómo lo configuro?

Para poder levantar los servicios que necesitas, tienes que indicarle a Docker Compose de alguna forma lo siguiente:

  • Contenedores a crear/levantar
  • Relación de los contenedores entre sí

Para ello creamos un fichero YAML, llamado “docker-compose.yml”, donde definimos cada uno de los servicios (puedes ver el fichero completo al final de esta sección).

Comienza tu fichero de configuración indicando la versión de sintaxis a utilizar y abriendo la sección de servicios:

version: "3"


services:

Configuración para MySQL

Primero, nos fijamos en el servicio donde incluiremos nuestra base de datos con el contenedor oficial de MySQL, que permite definir incluso el nombre de la base de datos que queremos usar, junto a sus datos de acceso. Actualmente, la última versión estable de MySQL es la 5.7, por lo que las líneas a incluir en el fichero son:

  miservicio_mysql:
    image: mysql:5.7
    environment:
      - MYSQL_DATABASE=nombre
      - MYSQL_ROOT_PASSWORD=claveroot
      - MYSQL_USER=miusuario
      - MYSQL_PASSWORD=mipassword
    volumes:
      # Montamos un volumen para MySQL para no perder los datos de bd
      - ./volumenes/mysql:/var/lib/mysql
    expose:
      - 3306

Una pequeña mejora. Si quieres acceder fácilmente al servicio MySQL desde tu aplicación favorita, puedes hacer que escuche en el puerto 3306 local, o en el que tú prefieras, solamente con añadir:

ports:
  - 3306:3306

Configuración para el servidor web

Aquí, por ser la opción más sencilla, usamos el contenedor oficial de PHP con Apache ya integrado, aunque también podríamos combinar un contenedor oficial de Apache con la versión FPM de este contenedor de PHP.

Como puedes ver en la documentación del contenedor, puedes elegir entre varias versiones:

  • php: 7-Apache. Última versión de PHP 7, actualmente la 7.2
  • php: 7.2-Apache. Última versión estable de PHP 7.2
  • php: 7.1-Apache. Última versión estable de PHP 7.1
  • php: 7.0-Apache. Última versión estable de PHP 7.0
  • php: 5.6-Apache. Última versión estable de PHP 5.6

Para este ejemplo me he decantado por usar la versión más actual de PHP 7. El servicio se configura así:

miservicio_php:
  image: php:7-apache
    volumes:
      # Montamos nuestra web desde fuera en el directorio web del contenedor
      - ./miweb/:/var/www/html
    expose:
      - 80
    ports:
      - 80:80
    links: 
      - miservicio_mysql

Con esto queda listo el fichero de configuración, así que ya podrías levantar el fichero. Por si prefieres copiar y pegar, aquí tienes la configuración completa de este ejemplo:

version: "3"

services:
  miservicio_mysql:
    image: mysql:5.7
    environment:
      - MYSQL_DATABASE=nombre
      - MYSQL_ROOT_PASSWORD=claveroot
      - MYSQL_USER=miusuario
      - MYSQL_PASSWORD=mipassword
    volumes:
      # Montamos un volumen para MySQL para no perder los datos de bd
      - ./volumenes/mysql:/var/lib/mysql
    expose:
      - 3306
    ports:
      - 3306:3306
  
  miservicio_php:
    image: php:7-apache
    volumes:
      # Montamos nuestra web desde fuera en el directorio web del contenedor
      - ./miweb/:/var/www/html
    expose:
      - 80
    ports:
      - 80:80
    links: 
      - miservicio_mysql

Añadiendo tu código y levantando Docker

Ya solo falta que incluyas el código en el directorio “miweb”, o el que hayas indicado en tu configuración, y ya podrás iniciar todos los servicios.

¡Un detalle! Asegúrate de que no tienes nada en tu máquina que esté utilizando los puertos que hemos definido para nuestros servicios (80 y 3306), pues de lo contrario no podrás iniciar los contenedores.

Lanzando contenedores en background

Esta es la opción más cómoda a la hora de no cerrar todo accidentalmente ya que, al quedar lanzados los contenedores en segundo plano, seguirán funcionando aunque cerremos la terminal. A cambio, para ver los logs tendrás que usar comandos de Docker para cada contenedor por separado. Para iniciar así el contenedor, solamente tendrás que situarte en la misma carpeta donde está el fichero docker-compose.yml y ejecutar:

docker-compose up -d

Si quieres detener los contenedores, puedes hacerlo también con el comando:

docker-compose down

Ejemplo Docker Compose

Lanzando contenedores en primer plano

Si, por el contrario, prefieres ver los logs directamente en pantalla y poder parar los contenedores solamente con pulsar Ctrl+C, inicia el servicio en primer plano, ejecutando el de inicio, pero sin “-d”:

docker-compose up

¡Y listo! Ya tienes funcionando un servicio web, con PHP 7.2 y MySQL 5.7, con el código de tu web en tu máquina. Solamente tendrás que acceder a http://localhost/.

Recuerda que este es un tutorial muy sencillo, con lo básico para arrancar los servicios y que funcionen, pero los límites los pones tú:

  • Añade extensiones al php y Apache, creando tu propio contenedor
  • Cambia rutas, configuraciones, variables de entorno…
  • Juega con el mapeo de puertos, por ejemplo:
    • Añade un segundo servidor web, con otro php y escuchando en otro puerto (por ejemplo 81, 8080), para probar tu web con diferentes versiones
    • Cambia el puerto del apache para mantener levantado tu servicio local

¡Esperamos tus comentarios!  Si te ha resultado útil, si quieres que profundicemos más en el tema… Recuerda que también puedes contactarnos si tienes cualquier duda o sugerencia, ¡que para eso estamos! 😀


Avatar de Víctor Rodríguez

Comentarios

68 respuestas

  1. Avatar de Alejandro
    Alejandro

    Buenas muy bueno el post, mi consulta o mas bien una orientación. Tengo un aplicación básica( ya terminada) que quiero que se utilice en un entorno local, la cual esta desarrollada en Angular y consume una api de Laravel y un motor postgre.
    Ahora es posible deployar y correr de forma local sin llevarlo a un servidor web utilizando docker?? o existe alguna otra herramienta con la cual pueda investigar para este cometido?
    Desde ya muchas gracias

    1. Avatar de Víctor Rodríguez
      Víctor Rodríguez

      Hola Alejandro,

      No deberías tener problema, siempre que en la máquina donde quieres hacerlo funcionar tengas disponibles Docker y Docker Compose, o puedas instalarlos.

      Puedes partir de una configuración similar a la de este post, cambiando el contenedor de MySQL por el de PostgreSQL e irla adaptando a tus necesidades. Posiblemente necesites personalizar el contenedor de PHP (hay un comentario anterior donde se da una explicación de como habilitar pdo_mysql que te puede servir) o, incluso, te puedes plantear el uso de Laradock.

      Otra opción es la de crear tu propio contenedor de PHP partiendo de una imagen básica del sistema operativo, como podrían ser Ubuntu o Debian. En este caso, ten en cuenta que tendrás que preparar todo tú (servidor web, php, librerías…) y dedicar mucho más tiempo, pero tendrás el contenedor tal y como quieres que sea.

      Espero haber resulto tu consulta.

      Gracias por comentar. Un saludo 😉

      1. Avatar de Alejandro
        Alejandro

        Lo estoy invetigandooo!Gracias por tu respuesta, te lo agradezco.

  2. Avatar de Luias
    Luias

    Muchas gracias por el tutorial! Muy completo! Soy totalmente novata en Docker y también bastante en php.

    Estoy desarrollando una aplicación php en Docker. He utilizado el código ampliado que indicaste con un tercer contenedor phpmyadmin.

    Quiero acceder a phpmyadmin (con localhost:8080 que es el puerto asingado) a través del navegador pero me aparece el siguiente error:

    phpMyadmin – Error

    Error during session stat_ please check your PHP and/or webserver log file and configure php installation properly. Also ensure that are enabled in your browser.

    session_write_close() write failed. No space left on device (28)

    session_write_close():Failed to write session data (files). Please verify that the current of session_save_path is correct ().

    He comprobado que sí que tengo espacio en /var tanto de la máquina host como del contenedor. No sé por qué puede ser, si es que tengo que configurar algún archivo más para dar acceso remoto…

    Agradecería alguna idea please!!!

    Gracias!

    Saludos!

    1. Avatar de Adriana Freire
      Adriana Freire

      Hola Luias,

      ¡Gracias por comentar!

      Sin los logs de error no podríamos saber con mayor exactitud qué sucede. De todas formas, lo mejor sería:

      1. Vaciar la caché del navegador y eliminar las Cookies
      2. Verificar que /var/lib/php/session/ tenga permisos de acceso
      3. Verificar en el php.ini que la directiva session.save_path esté correctamente establecida

      Un saludo!

  3. Avatar de Seienshi
    Seienshi

    Ante todo muchisimas gracias por la aclaratoria anterior.

    Ahora tengo otra duca, tengo en un vps dos contenedores cada uno con un sitio web distinto, un sitio lo publico por el puerto 80 del anfitrion y el otro por el 8080, hasta alli todo bien, pero ahora debo hacer que sean visibles al mundo, tengo solo una ip, pero el sitio que publico por el puerto 80 debe apuntar a dominioa.com y el que publico por el puerto 8080 debe apuntar a dominiob.com

    1. Avatar de Ret
      Ret

      Creo que lo que necesitas es un Reverse-proxy. Basicamente es un servidor que recibe pedidos externos y los reenvia a los servicios internos que correspondan.
      Fijate en Traefik que tambien viene en contenedor

    2. Avatar de Adriana Freire
      Adriana Freire

      ¡Hola!

      Asumiendo que están los puertos 80 y 8080 del Docker mapeados con el 80 y 8080 del VPS, y que está correcta la configuración del servicio web y sus VirtualHost (Apache) o ServerBlock (Nginx), entonces habría que apuntar la zona @ de cada uno de los dominios a la IP del VPS. Con esto, luego de que se propague la zona, el dominio será accesible a nivel público.

      ¡Esperamos haberte sido de ayuda!

  4. Avatar de vectorino
    vectorino

    Hola felicitaciones por el excelente blog!

    Por favor podrías orientarme respecto de lo siguiente, estoy experimentando con docker-compose y joomla.
    Utilicé el procdimiento que plantea bitnami y todo funciona muy bien.
    Pero ahora tengo la necesidad de instalar un certificado SSL, y encontré un tutorial para que mediante jrcs/letsencrypt-nginx-proxy-companion pueda agregarlo, sin embargo mi pregunta es, ¿si detengo el actual contenedor con docker-compose down y luego modifico el docker-compose.yml para finalmente levantarlo nuevamente con docker-compose up -d, el sitio que existía no se verá dañado?

    1. Avatar de Adriana Freire
      Adriana Freire

      ¡Hola!

      Cuando se monta el volumen en el docker-compose.yml, lo que hace es enlazar la carpeta indicada del anfitrión con la indicada del Docker. Por ejemplo:
      volumes:
      – ./miweb/:/var/www/html # Donde miweb es la carpeta del anfitrión y /var/www/html la del docker.

      Si se hacen cambios tanto desde fuera del Docker (en la carpeta miweb) como desde dentro del Docker (/var/www/html), estos cambios serán permanentes, por lo que en el momento de hacer un docker-compose down no se eliminará contenido.

      ¡Esperamos haberte sido de ayuda!

  5. Avatar de Mauricio
    Mauricio

    Muy buen post! Bien Claro y simple, gracias!!!

    1. Avatar de Adriana Freire
      Adriana Freire

      A ti por comentar, Mauricio. Quedamos a tu disposición para lo que necesites.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Newsletter

Suscríbete y recibe periódicamente consejos muy útiles para tu web y ecommerce 🙂 Además, te regalamos
3 guías
: Digitalización, WordPress y Ciberseguridad.

Conviértete en afiliado

Gana dinero recomendando dinahosting a todo el mundo.