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 leo
    leo

    Hola Víctor que gran post, me sirve de mucho, te quería hacer una consulta, estoy implementando angular, django y postgresql con docker, adelante un proxy con jwilder, pero tengo unas dudas al hacer las peticiones desde angular a django(sirve como api para angular) mi consulta va, a que url tendría que apuntar angular para hacer las peticiones a django, acaso a la ip del contenedor? , muchas gracias.

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

      Hola, leo,

      En el caso que me comentas, entiendo que estás usando jwilder/nginx-proxy, y por lo tanto, a cada contenedor le habrás definido una variable de entorno “VIRTUAL_HOST” con la que el proxy redigirá a ellos esas peticiones. Lo más sencillo sería dirigir esas peticiones al virtualhost que has definido y ya el proxy se encargará de que lleguen al contenedor correcto.

      Por cierto, no conocía jwilder/nginx-proxy. Me lo anoto para futuras ocasiones (yo me configuraba el proxy con nginx a mano).

      Espero haber resuelto tus dudas 😉

  2. Avatar de naveganteAnonimo

    Excelente tutorial ! muy practico y sencillo aclaraste muchas dudas que tenia ! sin duda excelente post

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

      ¡Genial que te haya resultado útil! Gracias por comentar 😉

  3. Avatar de Jorge A

    Hola a todos, una consulta, hay alguna forma de montar un servidor web en este caso uso nginx, donde tengo alojado el frontend en angular, que apunte a un servidor de aplicaciones que es nodejs y este a la bd en mongo, sin exponer los puertos de el backend? , ya mapee el backend con la bd por medio de los nombres de los servicios que declaro en el compose, y conectan, ya expuse los puertos internos, pero no quiero exponer el puerto del back al localhost, si no que el angular conecte al back por el puerto interno, espero que se haya entendido.. muchisimas gracias

    1. Avatar de Marta Mariño
      Marta Mariño

      ¡Hola Jorge!

      Lamentamos no poder darte una respuesta. Lo cierto es que tu caso es muy concreto y requeriría componer un escenario específico del que no disponemos en estos momentos.
      A ver si algún lector del post se ha visto con una situación similar y puede responderte 🙂

      ¡Un saludo!

  4. Avatar de Antonio
    Antonio

    Hola
    estoy intentando hacer tu manual en Windows instalando Ubuntu 22.04.

    tengo instalado Docker en Windows y se carga toda la información en los contenedores

    Creo el archivo dockercompose.yml dentro de la carpeta mi web y lo ejecuto.

    elcr4ck@elcr4ck:~/miweb$ sudo nano docker-compose.yml
    elcr4ck@elcr4ck:~/miweb$ docker-compose up -d
    [+] Running 2/26
    ⠴ miservicio_php Pulling 60.6s
    ⠿ a603fa5e3b41 Pull complete 33.8s
    ⠿ c428f1a49423 Pull complete 33.8s
    ⠋ 156740b07ef8 Downloading [==================================> ] … 58.0s
    ⠋ fb5a4c8af82f Download complete 58.0s
    ⠋ 25f85b498fd5 Download complete 58.0s
    ⠋ 9b233e420ac7 Download complete 58.0s
    ⠋ fe42347c4ecf Download complete 58.0s
    ⠋ d14eb2ed1e17 Download complete 58.0s
    ⠋ 66d98f73acb6 Download complete 58.0s
    ⠋ d2c43c5efbc8 Download complete 58.0s
    ⠋ ab590b48ea47 Download complete 58.0s
    ⠋ 80692ae2d067 Downloading [==================================================>] … 58.0s
    ⠋ 05e465aaa99a Download complete 58.0s
    ⠴ miservicio_mysql Pulling 60.6s
    ⠏ d26998a7c52d Downloading [============================> ] … 57.9s
    ⠏ 4a9d8a3567e3 Download complete 57.9s
    ⠏ bfee1f0f349e Download complete 57.9s
    ⠏ 71ff8dfb9b12 Download complete 57.9s
    ⠏ bf56cbebc916 Download complete 57.9s
    ⠏ 2e747e5e37d7 Download complete 57.9s
    ⠏ 711a06e512da Downloading [=============> ] … 57.9s
    ⠏ 3288d68e4e9e Waiting 57.9s
    ⠏ 49271f2d6d15 Waiting 57.9s
    ⠏ f782f6cac69c Waiting 57.9s
    ⠏ 701dea355691 Pulling fs layer

    [+] Running 3/3
    ⠿ Network miweb_default Created 0.9s
    ⠿ Container miweb-miservicio_mysql-1 Started 3.0s
    ⠿ Container miweb-miservicio_php-1 Started 2.4s
    elcr4ck@elcr4ck:~/miweb$

    Apararentemente se instala.

    en docker de windows me sale esto

    Only show running containers

    Search

    NAME
    ACTIONS
    miweb


    Running (2/2)

    miservicio_mysql-1

    dfed5cf57f06

    mysql:5.7
    Running

    3306:3306
    2 minutes ago
    miservicio_php-1

    4a6002f8045f

    php:7-apache
    Running

    80:80
    2 minutes ago

    y en docker me sale cosas en rojo 🙁

    1. Avatar de Marta Mariño
      Marta Mariño

      ¡Hola Antonio!

      Aparentemente, está todo correcto y los servicios de Docker levantados, pero si te salen cosas en rojo puede ser porque te falte algo.
      Te recomendamos revisar si los puertos configurados no están en uso o si los volúmenes que exportas en la configuración existen dentro del directorio.

      ¡Esperamos haberte sido de ayuda!

  5. Avatar de Juan
    Juan

    Hola Víctor, ¿es posible utilizar docker en dinahosting?
    Gracias

    1. Avatar de Marta Mariño
      Marta Mariño

      ¡Hola Juan!
      Sí, es posible utilizar Docker en los servicios No Administrados (Dedicados o VPS). Ahí cuentas con credenciales de Administrador para instalar las herramientas que necesites.

      ¡Un saludo!

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.