Como Crear Un Sitio Web Con Docker PDF
Como Crear Un Sitio Web Con Docker PDF
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.
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…
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.
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
Instalamos Docker
Actualizamos el índice de paquetes de yum
Instalamos Docker-CE
docker version
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:
Client:
Version: 17.03.1-ce
API version: 1.27
Go version: go1.7.5
Git commit: c6d412e
Built: Mon Mar 27 [Link] 2017
OS/Arch: linux/amd64
Server:
Version: 17.03.1-ce
API version: 1.27 (minimum version 1.12)
Go version: go1.7.5
Git commit: c6d412e
Built: Mon Mar 27 [Link] 2017
OS/Arch: linux/amd64
Experimental: false
MariaDB: mariadb:10.0.29
WordPress: wordpress:4.7.2-apache
InfluxDB: influxdb:1.2.0-alpine
Telegraf: telegraf:1.1.2-alpine
Grafana: grafana/grafana:4.1.2
Nginx: nginx:1.10
PhpMyAdmin: phpmyadmin/phpmyadmin:4.6.6-1
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.
Accedemos al repositorio ([Link] 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
…
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
0b255bad8202cb48e43af418e627d92767111edcd2dc03504df7f3d2c3f7e115
# docker ps
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
# docker network ls
NETWORK ID NAME DRIVER SCOPE
9c435956de8f bridge bridge local
98d7b2d36ca4 host host local
77b2fad06ea6 none null local
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:
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.
wordpress01
# docker rm wordpress01
wordpress01
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)
45e7fdef188bcb798cb25e3beb30da1e69db2728d227aa7cc518dcbdb6a54472
Ahora en la columna Ports vemos el enlace de los puertos entre el puerto del host (8080) y el puerto del contenedor (80)
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
NAMES
45e7fdef188b wordpress:4.7.2-apache "docker-entrypoint..." 17 seconds ago Up 16 seconds [Link]:8080-
>80/tcp wordpress01
Si accedemos con un navegador a la url [Link] 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.
Descargamos la imagen
# docker pull mariadb:10.0.29
2754d6410c164a3d23f33f1b15d8f8740c04d9a5bdf4d87abf3c8881a83c132e
# docker ps
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»
# docker ps -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
3f33340e0623f51aea8b2d4a8eecca64801f18d0f9c4d21a8894987f39453f44
Volvemos a comprobar los contenedores y ahora si que tenemos los dos contenedores ejecutándose:
# docker ps
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
root@3f33340e0623:/#
Ahora estamos en la shell del contenedor y podemos conectarnos con el cliente de mysql y comprobar la existencia de la base de datos
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
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.
wordpress01
# docker rm wordpress01
wordpress01
Volvemos a ejecutar el contenedor de wordpress pero esta vez enlazándolo al contenedor de mysql
428f50e26dd69f705f383d0b9603b31450536aef7016c96b4a8b325a44453069
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
ha sido necesario ejecutar los siguientes comandos de docker para crear 2 contenedores:
# docker network ls
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
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.
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
# docker info
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 1
Server Version: 17.03.1-ce
Storage Driver: overlay
Backing Filesystem: xfs
Supports d_type: false
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
Volume: local
Network: bridge host macvlan null overlay
Swarm: inactive
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:
/volume01:
total 0
drwxr-xr-x. 2 root root 6 May 14 08:05 .
drwxr-xr-x. 1 root root 58 May 14 08:05 ..
Si inspeccionamos el contenedor vemos en el apartado Mount, los volúmenes a los que accede el contenedor:
"Mounts": [
{
"Type": "volume",
"Name": "5a7c85ba5d84ed6c823d66a5c663777d2557f1dab6975c0adbd63145ff78391f",
"Source": "/var/lib/docker/volumes/5a7c85ba5d84ed6c823d66a5c663777d2557f1dab6975c0adbd63145ff78391f/_data",
"Destination": "/volume01",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
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:
# docker volume ls
/var/lib/docker/volumes/5a7c85ba5d84ed6c823d66a5c663777d2557f1dab6975c0adbd63145ff78391f/_data
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
Podemos ver que al crear los contenedores, tenemos dos volúmenes creados:
# docker volume ls
DRIVER VOLUME NAME
local aeaaf3890d571f4189d0abe08036101db31c5cf1aeb17b2c8f64522b7cbe7721
local f560914d5536100c648a2cbaca874c47e3be2bd2f583a01bd309013188cdc76e
Si inspeccionamos los contenedores podemos ver los volúmenes asociados a cada uno de ellos:
"Mounts": [
{
"Type": "volume",
"Name": "aeaaf3890d571f4189d0abe08036101db31c5cf1aeb17b2c8f64522b7cbe7721",
"Source": "/var/lib/docker/volumes/aeaaf3890d571f4189d0abe08036101db31c5cf1aeb17b2c8f64522b7cbe7721/_data",
"Destination": "/var/www/html",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
"Mounts": [
{
"Type": "volume",
"Name": "f560914d5536100c648a2cbaca874c47e3be2bd2f583a01bd309013188cdc76e",
"Source": "/var/lib/docker/volumes/f560914d5536100c648a2cbaca874c47e3be2bd2f583a01bd309013188cdc76e/_data",
"Destination": "/var/lib/mysql",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
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:
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.
[
{
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/VL_wordpress01/_data",
"Name": "VL_wordpress01",
"Options": {},
"Scope": "local"
}
]
# ls /var/lib/docker/volumes/VL_wordpress01/_data
[Link] [Link] [Link] [Link] [Link] [Link] [Link]
[Link] wp-admin [Link] wp-includes [Link] [Link]
[Link] [Link] wp-content [Link] [Link] [Link]
Vemos que el directorio «/var/lib/docker/volumes/VL_wordpress01/_data» contiene los archivos y directorios de la aplicación wordpress
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
En estos momentos, vemos que la última versión es la 1.13.0, por lo que ejecutamos
chmod +x /usr/local/bin/docker-compose
# docker-compose version
docker-compose version 1.13.0, build 1719ceb
docker-py version: 2.2.1
CPython version: 2.7.13
OpenSSL version: OpenSSL 1.0.1t 3 May 2016
mkdir -p SitioWeb01
El archivo [Link] 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:
version: '3'
services:
mariadb01:
image: mariadb:10.0.29
volumes:
- VL_mariadb01:/var/lib/mysql
restart: always
environment:
- MYSQL_ROOT_PASSWORD=root_P@ssw0rd
- MYSQL_DATABASE=wordpress01
- MYSQL_USER=user_wordpress01
- MYSQL_PASSWORD=user_P@ssw0rd
networks:
- BackEnd
wordpress01:
depends_on:
- mariadb01
image: wordpress:4.7.2-apache
ports:
- "80:80"
restart: always
volumes:
- VL_wordpress01:/var/www/html
environment:
- WORDPRESS_DB_HOST=mariadb01
- WORDPRESS_DB_NAME=wordpress01
- WORDPRESS_DB_USER=user_wordpress01
- WORDPRESS_DB_PASSWORD=user_P@ssw0rd
networks:
- FrontEnd
- BackEnd
volumes:
VL_mariadb01:
VL_wordpress01:
networks:
FrontEnd:
driver: bridge
BackEnd:
driver: bridge
Una vez creado el archivo [Link] con el contenido indicado, ejecutamos el comando:
docker-compose up
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
# docker-compose up -d
Creating network "sitioweb01_FrontEnd" with driver "bridge"
Creating network "sitioweb01_BackEnd" with driver "bridge"
Creating sitioweb01_mariadb01_1 ...
Creating sitioweb01_mariadb01_1 ... done
Creating sitioweb01_wordpress01_1 ...
Creating sitioweb01_wordpress01_1 ... done
Redes
sitioweb01_BackEnd
sitioweb01_FrontEnd
# docker network ls
NETWORK ID NAME DRIVER SCOPE
bb9e7f4cc904 bridge bridge local
98d7b2d36ca4 host host local
77b2fad06ea6 none null local
67abdb08ebe8 sitioweb01_BackEnd bridge local
63b6b2ed7641 sitioweb01_FrontEnd bridge local
Volúmenes
sitioweb01_VL_mariadb01
sitioweb01_VL_wordpress01
# docker volume ls
DRIVER VOLUME NAME
local sitioweb01_VL_mariadb01
local sitioweb01_VL_wordpress01
Contenedores:
sitioeweb01_wordpress01_1
sitioeweb01_mariadb01_1
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
NAMES
545063308b87 wordpress:4.7.2-apache "docker-entrypoint..." 7 minutes ago Up 4 minutes [Link]:80-
>80/tcp sitioweb01_wordpress01_1
27fd925ad553 mariadb:10.0.29 "docker-entrypoint..." 8 minutes ago Up 4 minutes 3306/tcp
sitioweb01_mariadb01_1
# docker-compose restart
Restarting sitioweb01_wordpress01_1 ... done
Restarting sitioweb01_mariadb01_1 ... done
# docker-compose down
Stopping sitioweb01_wordpress01_1 ... done
Stopping sitioweb01_mariadb01_1 ... done
Removing sitioweb01_wordpress01_1 ... done
Removing sitioweb01_mariadb01_1 ... done
Removing network sitioweb01_FrontEnd
Removing network sitioweb01_BackEnd
Si queremos borrar los servicios parados
# docker-compose rm
Going to remove sitioweb01_wordpress01_1, sitioweb01_mariadb01_1
Are you sure? [yN] y
Removing sitioweb01_wordpress01_1 ... done
Removing sitioweb01_mariadb01_1 ... done
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)