Como crear un sitio web con Docker

Como forma de introducción al uso de Docker he decidido implementar este sitio web utilizando contenedores. Para ello he utilizado varios de los componentes y funcionalidades de Docker que me han permitido implementar el sitio web de una forma que creo que es interesante compartir como ejemplo del uso de contenedores.

Objetivo

El objetivo principal de esta entrada es el conocer con un detalle avanzado el funcionamiento de docker, no nos vamos a quedar en sólo descargar y ejecutar una imagen. Para ello vamos a tomar como ejemplo la creación de un sitio web con una infraestructura que tiene las siguientes características:

  • Como plataforma base voy a utilizar un servidor VPS basado en CENTOS 7 con 2GB de RAM y 10GB de disco duro
  • Para la página web voy a utilizar WordPress con MariaDB como base de datos
  • Un sistema de monitorización del estado de la propia web basado en InfluxDB+Telegraf+Grafana
  • Un Proxy inverso basado en Nginx que me permita acceder a los diferentes “servicios” del sitio web
  • Publicación con http y https, utilizando certificados de Let’s Encrypt

Cuando empecé a escribir esta entrada, comencé con la idea de mostrar de forma sencilla como usar Docker para crear una página web, pero ha ido creciendo hasta convertirse un manual de qué es Docker y como funciona.

 

Introducción a Docker

¿Qué es Docker?

Docker es un proyecto de código abierto que permite el uso de aplicaciones dentro contenedores con el objetivo de proporcionar una capa de aislamiento en la ejecución de las mismas. Al iniciarse dentro de un entorno Linux, esta capa de aislamiento es proporcionada por componentes del kernel como cgroups o namespaces, aunque debido a su auge y aceptación por la industria y la comunidad también ha sido adoptado por Microsoft de forma que podemos también utilizar Docker en entornos Windows (a partir de Windows 10 y Windows Server 2016)

El objetivo de un contenedor, es conseguir un paquete de software ligero que incluye todos los componentes y dependencias necesarios para ejecutar una aplicación de forma que siempre se ejecuta de la misma forma independientemente de su entorno o infraestructura donde se ejecuta.

Características de Docker

A continuación voy a enumerar algunas de las principales de Docker:

  • Menor uso de recursos: los contenedores comparten recursos con el kernel de la máquina donde se ejecutan. Además pueden compartir recursos (principalmente almacenamiento) de forma que se reduce en gran medida el tamaño de los contenedores.
  • Rapidez de ejecución: el inicio y ejecución de las instacias de los contenedores se produce de forma casi instantánea
  • Estándar: utiliza componentes estándar por lo que se puede utilizar en la mayoría de las distribuciones Linux y como hemos comentado antes, también en entornos Windows.
  • Aislamiento: con Docker conseguimos un nivel de aislamiento entre las aplicaciones que permiten aumentar la seguridad de la infraestructura
  • Distribución y compartición: permite compartir de una forma muy sencilla y rápida las aplicaciones creadas en contenedores.
  • Escalado: permite automatizar y escalar miles de una forma rápida y sencilla

 

Docker vs Máquinas virtuales

Aunque Dockers y Máquinas virtuales puedan ser un concepto similar y proporcionen características similares (ambos proporcionan aislamiento en la ejecución, permiten mover las aplicaciones entre hosts …) es importante saber que estamos trabajando con sistemas y arquitecturas diferentes.

Para entender las diferencias entre dockers y máquinas virtuales me ha gustado la analogía que he visto en un vídeo de la última DockerCon 2017:

  • Una máquina virtual es una casa individual o chalet que proporciona una infraestructura completa a quién vive en ella. Posee recursos individuales en cuanto a calefacción, electricidad, aislamiento…
  • Un docker es un apartamento o piso, proporciona una infraestructura a  quién vive en él, pero esa infraestructura es compartida con otros apartamentos. En el edificio de apartamentos hay una infraestructura común de la que se sirven los apartamentos y pisos, calefacción, electricidad… Además en un edificio pueden existir pisos de diferentes tamaños para diferentes necesidades.

Dejando de lado el tema inmobiliario, podríamos decir que las máquinas virtuales que se ejecutan en un host comparten los recursos físicos pero no comparten ningún recurso software. En el caso de Docker, además de compartir los recursos hardware también comparten recursos a nivel software. El objetivo de Docker es centrarse en la aplicación, dejando de lado el sistema operativo donde se ejecuta.

Máquina Virtual Docker

Este cambio de modelo implica también un cambio en la mentalidad de los administradores de sistemas:

  • ¿Cómo hago el backup de un contenedor? Directamente no lo hacemos. Uno de los objetivos de los contenedores es que no incluyan datos de la aplicación y se puedan ejecutar y reproducir su ejecución de forma muy sencilla.
  • Pero el contenedor tiene un sistema operativo, aunque sea una imagen mínima y optimizada: ¿cómo mantengo actualizado el contenedor? ¿cómo lo parcheo? Pues no lo parcheamos. Como los contenedores están basados en imágenes y no contienen datos, lo que hacemos es actualizar la imagen y parar y arrancar el contenedor.

Aunque son conceptos diferentes, no son excluyentes. Podemos perfectamente ejecutar Docker sobre una máquina virtual o incluso una aplicación que se ejecuta en un contenedor puede utilizar una base de datos que se ejecuta en una máquina virtual. Los dockers no van a reemplazar de forma competa a las máquinas virtuales. Tendremos aplicaciones donde la ejecución en contenedores nos proporcione ventajas sobre la ejecución de las mismas en máquinas virtuales (agilidad de despliegue, consumo de recursos…) pero habrá otras donde sigamos prefiriendo que se ejecuten en máquinas virtuales (por ejemplo bases de datos)

De esta forma tendremos centros de datos con máquinas virtuales, dockers que se ejecutan en servidores físicos, dockers que se ejecutan en máquinas virtuales…

 

 

Componentes principales de Docker

  • Docker Engine: es la aplicación cliente-servidor que contiene los siguientes elementos
    • Un servidor que se ejecuta como un demonio en el sistema (dockerd)
    • Un interfaz REST API que sirve de acceso para ejecutar comandos en el servidor
    • Un cliente que utiliza el usuario para interactuar con el servidor(docker)
  • Image: es el paquete de software ejecutable que contiene todo lo necesario para ejecutar una aplicación
  • Container: es una instancia en ejecución de una imagen.
  • Network: los contenedores se comunican con otros dockers o con recursos externos a través de la red:
  • Data Volume: permiten almacenar datos de forma persistente.

 

Ediciones de Docker

A principios de este año 2017 se han producido varios anuncios relacionados con las ediciones disponibles de Docker ya que de alguna forma, se está reorganizando su alcance y disponibilidad.

En estos momentos disponemos de las siguientes ediciones:

  • Docker Enterprise Edition (Docker EE): es la versión orientada a utilizarse en empresas y negocios.
  • Docker Community Edition (Docker CE): es la versión gratuita orientada a utilizarse en pequeños proyectos o desarrollos personales:
  • Docker Cloud: es la orientada a servirse en plataformas cloud como AWS o Azure

Nosotros vamos a utilizar Docker CE, y en este caso la versión Docker CE Stable (se publica una versión cada 4 meses) en lugar de la versión Docker CE Edge (se publica una versión nueva cada mes)

 

 

Instalación de Docker

Habilitamos el repositorio para CentOS

  • Instalamos el paquete yum-utils para utilizar la herramienta yum-config-manager

  • Añadimos el repositorio (es el mismo repositorio para la versión Stable como para la versión Edge)

  • (Opcional) Si quisiesemos utilizar la versión Edge es necesario hablitar el repositorio

 

Instalamos Docker

  • Actualizamos el índice de paquetes de yum

  • Instalamos Docker-CE

  • Comprobamos el estado del demonio docker y lo iniciamos si no está arrancado

  • Hablitamos el demonio para que arranque con el sistema

  • Ejecutamos el comando para obtener la versión de docker

Y obtenemos un mensaje en el que se nos indica las versiones del cliente como del servidor (en este caso los dos instalados en la misma máquina) como el siguiente:

 

Creación del sitio Web

Imágenes y versiones de Dockers a utilizar en el sitio web

Vamos a utilizar las versiones oficiales de los diferentes productos, y como en la mayoría de los casos tenemos diferentes versiones (o tags en el lenguaje docker) vamos a especificar la versión concreta a utilizar (en lugar de utilizar la última versión disponible)

 

Voy a ir describiendo como vamos creando el sitio web desde una primera versión con una configuración mínima y paso a paso ver como evoluciona añadiendo más servicios y configuraciones de forma que podamos ver el uso y las diferentes opciones de docker.

 

Ejecutando el primer docker

Como para gestionar el sitio web vamos a utilizar WordPress, lo primer que vamos a hacer es descargarnos la imagen de wordpress oficial.

Accedemos al repositorio (https://hub.docker.com/_/wordpress/) y lo primero que vemos es que tenemos decenas de versiones de imágenes disponibles para utilizar. Además de diferentes versiones y subversiones de wordpress (4.7, 4.7.1, 4.7.2…) tenemos disponibles imágenes basadas en:

  • apache
  • fpm
  • fpm-alpine

Vamos a comenzar eligiendo la imagen: wordpress:4.7.2-apache

  • Descargamos la imagen con el comando “docker pull” y el nombre de la imagen a descargar

 

  • Creamos y ejecutamos un docker de nombre “wordpress01” con la imagen anterior con el comando “docker run” y los situientes parámetros:
    • –name: nombre que le vamos a dar al contenedor
    • -d: el contenedor s e ejecutará en segundo plano

 

  • Si todo es correcto, el comando nos devuelve el identificador asignado al docker

 

  • Comprobamos que el contenedor se está ejecutando

 

  • En este punto hemos creado el contenedor con la imagen de wordpress, pero no tiene ninguna utilidad ya que no podemos acceder a él, no hemos configurado la conectividad desde el exterior del host.

 

Cuando se instala y ejecuta el servicio docker, se crean diferentes redes que pueden ser utilizadas por los contenedores

  • bridge: conecta el contenedor con el interfaz docker0 del host, utilizando una red privada y un servicio DHCP que asigna las direcciones IP a los contenedores. Es la red a la que se conectan por defecto los contenedores si no se indica una red de forma explícita.
  • host: conecta el contenedor con la red del host, de forma que no hay aislamiento entre el host y el contenedor.
  • none: en este caso el contenedor no tiene conectividad

La siguiente imagen podría mostrar una representación gráfica de cada una de las 3 redes

 

En la instalación por defecto de Docker, se crea el interfaz docker0 en el host, como podemos ver en el siguiente ejemplo:

 

En nuestro caso, hemos creado un contenedor conectado a la red “bridge”

Cuando arrancamos el contenedor, en el host se crea un interfaz por cada red a la que está conectado el contenedor:

Pero aunque parece que tiene conectividad con el exterior, realmente el contenedor está aislado y tenemos que “publicar” el puerto correspondiente, en el caso del contenedor wordpress, el puerto tcp-80.

  • Paramos y borramos el contenedor creado

 

  • Volvemos a ejecutar “docker run” pero esta vez vamos a utilizar el parámetro “-p”. Con este parámetro podemos “enlazar” uno de los puertos del host donde se está ejecutando el contenedor, con el puerto por el que está dando servicio el contenedor, en el caso de wordpress, el puerto 80.
    • -p: definimos los puertos en el formato puerto(s) del host:puerto(s) del contenedor (podemos definir un rango de puertos y también indicar una ip específica del host)

  • Ahora en la columna Ports vemos el enlace de los puertos entre el puerto del host (8080) y el puerto del contenedor (80)

  • Si accedemos con un navegador a la url http://host:8080 podremos ver la página donde se inicia el asistente de configuración inicial de wordpress.

Ya temos el sitio de wordpress listo para configurar, pero tenemos un problema, no tenemos una base de datos donde guardar la configuración de wordpress. Para ello vamos a utilizar MariaDB como gestor de base de datos y con la idea de utilizar dockers como microservicios, crearemos un contenedor con la instancia correspondiente.

 

 

Primera versión del sitio web (WordPress + MariaDB)

De forma similar a como hemos hecho con la imagen de wordpress vamos a proceder con la imagen de MariaDB

  • Descargamos la imagen

 

  • Creamos y ejecutamos un contenedor

 

  • Comprobamos los contenedores que tenemos ejecutando

 

  • Vemos que hay un problema, ¿dónde está el contenedor de mariadb01?  Vamos a volver a ejecutar el comando “docker ps” pero esta vez con el parámetro “-a”

 

  • Vemos que el contenedor mariadb01 se ha creado pero se ha parado, vemos que en la columna STATUS tenemos el mensaje “Exited …” Para poder investigar un poco más que ha pasado vamos a utilizar el comando “docker logs”

 

  • El mensaje nos indica claramente que no hemos indicado la contraseña del usuario root (SIEMPRE tenemos que leer la documntación primero) Hay imagenes que requieren o permiten utilizar variables de entorno para poder personalizar diferentes valores del contenedor. Para poder establecer los valores de las variables utilizamos el parámetro “-e” al ejecutar “docker run”

 

  • En el caso de la imagen de MariaDB podemos utilizar las siguientes variables:
    • MYSQL_ROOT_PASSWORD: [obligatoria] permite establecer la contraseña del usuario root.
    • MYSQL_ALLOW_EMPTY_PASSWORD: podemos utilizar esta variable para dejar la contraseña del usuario root en blanco.
    • MYSQL_RANDOM_ROOT_PASSWORD: se genera una contraseña para el usuario root de forma aleatoria y se muestra por pantalla.
    • MYSQL_DATABASE: permite crear una base de datos, y si se indica usuario y contraseña (siguiente variable) se le asignan los permisos de superusuario (GRANT ALL)
    • MYSQL_USER, MYSQL_PASSWORD: estas dos variables permiten crear un usuario y su contraseña sobre el que se aplicarán los permisos de superusuario para la base de datos creada con la variable anterior
  • Tras ver las variables disponibles, vamos a volver a ejecutar el contenedor de MariaDB, pero esta vez vamos a utilizar las variables para definir la contraseña del usuario root y ya definimos el usuario y la base de datos que vamos a utilizar con wordpress:
    • MYSQL_ROOT_PASSWORD: root_P@ssw0rd
    • MYSQL_DATABASE: wordpress01
    • MYSQL_USER: user_wordpress01
    • MYSQL_PASSWORD: user_P@ssw0rd

 

  • Volvemos a comprobar los contenedores y ahora si que tenemos los dos contenedores ejecutándose:

 

  • Para comprobar que el servicio de mysql está funcionando y la base de datos creada, vamos a conectarnos al contenedor con el comando “docker exec” y los parámetros:
    • -i: modo interactivo
    • -t: pseudo-TTY
    • Nombre del contenedor
    • comando

 

  • Ahora estamos en la shell del contenedor y podemos conectarnos con el cliente de mysql y comprobar la existencia de la base de datos

 

  • Hemos avanzado, pero ahora tenemos un problema: ¿cómo le indico al contenedor de wordpress que utilice la base de datos que hemos creado en el contenedor mariadb01?

En el punto anterior, para dar acceso al contenedor de wordpress, lo que hemos hecho es “mapear” un puerto del host al puerto 80 del contenedor. En este caso podríamos hacer lo mismo y mapear un puerto del host para el contenedor de MariaDB, pero no tiene sentido, ya que a este contenedor no tenemos que acceder desde el exterior, sólo es necesario que otro contenedor acceda a él.

Tenemos los dos contenedores conectados a la misma red (la red bridge) por lo que tienen conectividad entre ellos, pero únicamente utilizando sus direcciones IP. Además estas direcciones IP no son estáticas, por lo que no es recomendable utilizarlas para establecer la conectividad entre los contenedores ya que en el futuro, si cambiamos el orden de ejecución de los contenedores o creamos más, pueden cambiar.

Para permiter la conexión entre los contenedores vamos a “enlazarlos”. Cuando enlazamos los contenedores con el parámetro “–link”, se crea un “tunel” que enlaza los dos contenedores, sin la necesidad de exponer puertos. Al enlazar los contenedores, también hacemos que las variables de entorno de un contenedor, sean accesibles desde el otro. También se actualiza el archivo /etc/hosts para poder utilizar los nombres de los contenedores como nombres de red.

Creamos en enlace del siguiente modo:

Conociendo esto vamos a volver a rehacer los contenedores

  • El contenedor de Mariadb lo podemos dejar ejecutando pero paramos y borramos el contenedor de wordpress para volver a crearlo

 

  • Volvemos a ejecutar el contenedor de wordpress pero esta vez enlazándolo al contenedor de mysql

 

  • Si accedemos al docker de wordpress01 podemos comprobar que ahora si hay conectividad entre los contenedores ya que se ha creado una entrada en el archivo /etc/hosts del contenedor wordpress01

 

  • Ahora podemos volver al asistente de configuración de wordpress y configurar la base de datos correspondiente

 

En este punto ya tendríamos un sitio web totalmente funcional con WordPress y MariaDB

 

Para llegar a este punto, en el que tenemos:

  • 1 contenedor con MariaDB y una base de datos
  • 1 contenedor con WordPress siendo accesible en el puerto 80 del host donde se ejecutan los contenedores

ha sido necesario ejecutar los siguientes comandos de docker para crear 2 contenedores:

 

Revisión de la configuración de red

Aunque ya tenemos los dockers funcionando, el utilizar la red “bridge” por defecto no es una práctica recomendada. Para seguir con las buenas prácticas vamos a crear una nueva red, también de tipo bridge, ya que de esta forma tenemos un mayor control de la conectividad de los contenedores y nos aprovechamos de la funcionalidad que proporciona una resolución automática DNS de forma que no tenemos que utilizar los enlaces que hemos visto anteriormente para permitir la conexión entre contenedores.

Vamos a crear un diseño como el siguiente:

Para ello vamos a realizar los siguientes pasos:

  • Crear 2 redes de tipo bridge
    • FrontEnd
    • BackEnd
  • Conectar el contenedor mariadb01 a la red BackEnd
  • Conectar el contenedor wordpress01 a las dos redes, a FrontEnd y a BackEnd

Seguimos los siguientes pasos:

Podemos inspeccionar las redes creadas y ver el direccionamiento asignado a cada una

Al crear las redes, vemos también que se han creado las tarjetas de red asociadas en el host:

Ejecutamos los contenedores, pero esta vez indicando a que red conectamos cada contenedor

El contenedor de mariadb01

Y el contenedor de wordpress01

 

 

Configuración del almacenamiento de los contenedores

Contenedores y capas

El siguiente punto que tenemos que revisar es la configuración del almacenamiento para tener claro donde se están guardando los contenedores y la información generada en el sitio web.

Como hemos hecho antes con la red, vamos ver de forma rápida como funciona el almacenamiento en los contenedores de Docker.

El almacenamiento de los archivos y carpetas de las imágenes y contenedores está organizado por capas. Una imagen está formada por diferentes capas de sólo lectura, que a través del driver de almacenamiento (la implementación correspondiente de Union File System) es mostrada de forma única.

Por ejemplo, la imagen de ubuntu:15:04 está formada por 4 capas, cada una de ellas con diferente información.

El driver es el encargado de mostrar esas 4 capas como una vista única de la imagen. Cada vez que se añade una modificación a una imagen, se le crea una nueva capa con los cambios introducidos, quedando el resto sin tocar.

Al crear un contenedor de esa imagen, lo que hacemos es añadir una nueva capa, en este caso de lectura/escritura. De esta forma, el contenedor está formado por las 4 capas de sólo lectura que proporciona la imagen y la capa de lectura/escritura propia del contenedor.

Los identificadores de cada una de las capas de la imagen corresponden con un hash del contenido. El identificador de la capa del contenedor es generado de forma aleatoria.

Comentábamos que una de las características de Docker es que los contenedores ocupan poco espacio en disco. Esto es así, porque diferentes contenedores creados a partir de una misma imagen, comparten todas las capas de sólo lectura de la imagen y cada uno de ellos tiene su propia capa de escritura.

Si alguno de los contenedores necesita modificar alguno de los archivos que se ubican en las capas de la imagen, se crea una copia (Copy-On-Write) de forma que sólo ese contenedor accede a esa copia modificada y el resto de contenedores siguen accediendo a la imagen original.

Si el contenedor es eliminado, esa capa propia de lectura/escritura también es eliminada.

Docker permite utilizar diferentes drivers para gestionar el almacenamiento. Algunos de los drivers que nos podemos encontrar o utilizar son: OverlayFS, AUFS, Btrfs, Device mapper, VFS, ZFS …

Para ver que driver estamos utilizando podemos ejecutar docker info

Aunque hay diferentes drivers y cada uno tiene diferentes características que se pueden adaptar de una mejor forma a diferentes entornos y necesidades, vamos a utilizar el driver por defecto que proporciona la instalación de Docker en CentOS: overlay

 

 

Data Volumes

Como hemos visto, los datos que modificar un contenedor respecto a los datos de la imagen a partir del cual se crean se gestionan en una capa de lectura/escritura que tiene la vida del mismo contenedor, se elimina cuando se borra el contenedor. Pero podemos tener casos en los que queramos mantener esa información o queramos compartir la información entre dos o más contenedores de forma que accedan a los mismos datos. Para esto tenemos los Data Volumes

Los Data Volumes, son directorios específicos que no utilizan los drivers de almacenamiento y que permiten disponer de un recurso de datos permanente y con la opción de compartirlo entre varios contenedores.

Para poder añadir un Data Volume a un contenedor, utilizamos la opción -v al crearlo, por ejemplo:

Podemos ver que en el contenedor tenemos el directorio /volume01

Si inspeccionamos el contenedor vemos en el apartado Mount, los volúmenes a los que accede el contenedor:

Si ejecutamos el comando docker volume ls, podemos ver el listado de volúmenes del host, donde se encuentra el creado para el contenedor anterior:

Todo lo que el contenedor escriba o modifique en la carpeta local /volume01, se estará escribiendo en el siguiente directorio del host.

Acceso a directorios y archivos del host

También tenemos la opción de mapear un directorio o archivo concreto del host (sin crear un volumen gestionado por docker) de forma que sea compartido entre el host y el contenedor. También utilizamos la opción -v pero en este caso en el formato dir-host:dir-contenedor, siendo dir-contenedor una ruta absoluta dentro del contenedor y dir-host puede ser una ruta absoluta o relativa del host donde se ejecuta el contenedor

De igual forma que hemos indicado un directorio tanto en el host como en el contenedor podemos indicar un archivo en concreto.

Por defecto, cuando se monta un volumen en el contendor, se hace con permisos de lectura y escritura, pero podemos indicar que sea de sólo lectura

 

Almacenamiento persistente para nuestro sitio web

Retomamos nuestro ejemplo de crear un sitio web y volvemos a la situación en la que teníamos creados ya los dos contenedores de wordpress y mariadb

Podemos ver que al crear los contenedores, tenemos dos volúmenes creados:

Si inspeccionamos los contenedores podemos ver los volúmenes asociados a cada uno de ellos:

Estos volúmenes se han creado, aunque nosotros no se lo hemos indicado, porque están así definidos en la imagen de la que partimos:

  • La imagen de wordpress tiene definido el volumen
    • VOLUME /var/www/html
  • La imagen de mariadb tiene definido el volumen
    • VOLUME /var/lib/mysql

De esta forma tenemos ya creados los volúmenes persistentes, pero no los estamos gestionando nosotros, por lo que vamos a modificar la forma en la que creamos los contenedores para ajustarlo a nuestras necesidades y tener un mayor control de los datos, ya que si borramos estos contenedores y volvemos a crear unos nuevos (por un cambio en la configuración o por un actualización) se crearán nuevos volúmenes y los antiguos se quedarán sin utilizar.

Podemos crear un volumen y asignarle un nombre al mismo para poder identificarlo

y volvemos a crear los contenedores, pero ahora con la opción -v

Podemos comprobar el contenido de los volúmenes:

Vemos que el directorio “/var/lib/docker/volumes/VL_wordpress01/_data” contiene los archivos y directorios de la aplicación wordpress

El esquema del sitio web en este punto es el siguiente:

 

Vamos a trabajar con servicios

Si habéis llegado hasta aquí y habéis seguido todo el proceso, habréis comprobado que es bastante tedioso el crear un contenedor, pararlo, borrarlo, crear una nueva versión …

Esto es así porque estamos trabajando con cada uno de los contenedores, redes y volúmenes de forma individual, sin tener la visión en conjunto de lo que es la aplicación (que está formada por todos los componentes) Para facilitar esta gestión tenemos la herramienta Docker-Compose, que con un único comando nos va a permitir gestionar todos los contenedores (servicios) que forman parte de la aplicación.

 

Características de Docker-Compose

  • Permite aislar en un host múltiples proyectos utilizando un nombre de proyecto. Por defecto el nombre del proyecto es el nombre del directorio de trabajo aunque se puede modificar.
  • Mantiene la información de los volúmenes de datos
  • Sólo crea los contenedores que han tenido cambios desde la última ejecución

 

Instalación de Docker-Compose

Docker-Compose no se incluye en los paquetes por defecto de Docker, por lo que vamos a descargar el binario directamente de la página de Git-Hub

Vemos la última versión disponible: https://github.com/docker/compose/releases

En estos momentos, vemos que la última versión es la 1.13.0, por lo que ejecutamos

Asignamos permisos de ejecución al archivo descargado

Comprobamos que tenemos Docker-Compose disponible:

 

Creación del archivo docker-compose.yml

El primer paso es crear una carpeta en nuestro directorio de trabajo con el nombre que le vamos a dar a nuestro proyecto, por ejemplo SitioWeb01

Accedemos al directorio y creamos el archivo docker-compose.yml (también se acepta la extensión .yaml)

El archivo docker-compose.yml utiliza lenguaje YAML para definir los servicios (contenedores), redes y volúmenes.

Vamos a comenzar con un ejemplo simple, que va a replicar el sitio web que habíamos creado:

Una vez creado el archivo docker-compose.yml con el contenido indicado, ejecutamos el comando:

También podemos ejecutarlo con la opción -d, para que se ejecute en segundo plano y sin mostrarnos los logs de ejecución de los contenedores

Tras levantar los servicios comprobamos que elementos se han creado:

  • Redes
    • sitioweb01_BackEnd
    • sitioweb01_FrontEnd

  • Volúmenes
    • sitioweb01_VL_mariadb01
    • sitioweb01_VL_wordpress01

  • Contenedores:
    • sitioeweb01_wordpress01_1
    • sitioeweb01_mariadb01_1

Y podemos comprobar que el sitio web sigue funcionando.

Si queremos reiniciar los servicios

Si queremos parar la aplicación:

Si queremos borrar los servicios parados

De momento llegamos hasta aquí. Más adelante continuaremos añadiendo contenedores que nos proporcionen una monitorización de la infraestructura (Grafana + Influxdb + Telegraf) un publicador (Nginx) y certificados (Let’s encypt)

12 comentarios en “Como crear un sitio web con Docker”

  1. Hola que tal
    excelente post
    solo queria saber cuando le daras continuidad a esto
    esta muy interesante y es muy buena la manera en la que explicas
    saludos desde panama

    1. Gracias Francisco,

      Mi intención es darle continuidad, pero no soy todo lo constante que me gustaría en cuanto a publicar en el blog.

      Gracias y un saludo

      1. hola que tal
        uff que lastima.. que en verdad e aprendido bastante con lo que has mostrado
        en este blog…
        espero pronto puedas seguir dandole continuidad al asinto
        saludos 🙂

  2. hola que tal hermano soy nuevo en el ambito de los contenedores, mira estuve siguiendo todos los paso pero al momento de llegar a configurar el wordpress , asignarle la base de datos desde la interfaz web me envía el siguiente error “error al establecer un conexión con la base de datos”, me puedes dar una mano con esto.
    ley todo el post muy bueno la verdad pero mi inconveniente es solo que no se pega a bd desde la interfaz web.
    al momento de realizar la pruebas desde la consola le hago ping y responde hacia la base de datos de mariadb tambien realize la configuracion de red del backend y fronted y aun asi nada.
    estoy usando CentOS 7 virtualizado.

    te agradezco tu ayuda.

    1. Hola Orlando,

      Por lo que entiendo, puede ser un mensaje de conectividad entre los dos contenedores. Revisa que estás utilizando correctamente el nombre del contenedor con la base de datos y si has utilizado la opción “-link” al crear los contenedores para “enlazarlos”. Hay que tener en cuenta que aunque es el método que utilizo en la entrada, es un método que docker va a retirar y sería necesario recrear redes personalizadas. (https://docs.docker.com/engine/userguide/networking/default_network/dockerlinks/)

      Gracias y un saludo,

  3. Excelente entrada. No he encontrado nada igual. No sabia nada de docker y con tu ayuda he conseguido trabajar con wordpress en local utilizando esta herramienta. Hasta ahora usaba Vagrant con VVV, pero tarda en iniciarse, consume mas ram, etc. Seguiré profundizando con docker porque aunque el concepto es un poco complicado de entender, con post como el que te has currado es mas sencillo. Te animo encarecidamente que continúes con la segunda parte.
    Enhorabuena!
    Un saludo

  4. No puedo estar más de acuerdo con los comentarios que señalan como excelente este artículo.
    Me he llevado muchísimo aprendido. Gracias por tu tiempo y dedicación.

    Saludos

  5. Muy bueno el blog y gracias ya que me esta ayudando muchísimo!
    Pro me gustaría saber si es posible ejecutar la aplicación de docker-compose.yml en un cluster swarm y como hacerlo.
    Gracias

  6. MMUUUUYY BUEN APORTE ROBERTO.
    Mas que un buen inicio, como dices al inicio de tu post se convirtio en un manual de que es docker y como usarlo practicamente… lo mejor que he encontrado en la red.
    Estoy de acuerdo con los demas diciendo que esperamos la segunda parte.

Deja un comentario

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

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.