Recursos

Resursos de ampliación

1 - Presentación

Presentación del sitio

En construcción

Objetivo

Recursos para el módulo de DAW

https://cpilosenlaces.aeducar.es/course/view.php?id=384

1.1 - Programación

Programación del módulo. Boceto.

IDENTIFICACIÓN DEL MÓDULO

  • Real Decreto del Título: 686/2010, de 20 de mayo

  • Orden del Currículo: 8 de julio de 2011

  • Código del módulo: 0614

  • Denominación: Despliegue de aplicaciones web

  • Horas totales: 84 (88 reales)

  • Horas semanales: 4

  • Pérdida de la evaluación continua, en horas: 13

OBJETIVOS

Este módulo profesional contiene la formación necesaria para desempeñar la función de despliegue de aplicaciones Web en un servidor.

La formación del módulo contribuye a alcanzar los siguientes objetivos generales del ciclo:

  • Instalar módulos analizando su estructura y funcionalidad para gestionar servidores de aplicaciones.

  • Ajustar parámetros analizando la configuración para gestionar servidores de aplicaciones.

  • Utilizar herramientas específicas, cumpliendo los estándares establecidos, para elaborar y mantener la documentación de los procesos.

  • Establecer procedimientos, verificando su funcionalidad, para desplegar y distribuir aplicaciones.

  • Analizar y utilizar los recursos y oportunidades de aprendizaje relacionadas con la evolución científica, tecnológica y organizativa del sector y las tecnologías de la información y la comunicación, para mantener el espíritu de actualización y adaptarse a nuevas situaciones laborales y personales.

Competencias profesionales

  • Configurar y explotar sistemas informáticos, adaptando la configuración lógica del sistema según las necesidades de uso y los criterios establecidos.

  • Aplicar técnicas y procedimientos relacionados con la seguridad en sistemas, servicios y aplicaciones, cumpliendo el plan de seguridad.

  • Gestionar servidores de aplicaciones adaptando su configuración en cada caso para permitir el despliegue de aplicaciones Web.

  • Desarrollar e integrar componentes software en el entorno del servidor Web, empleando herramientas y lenguajes específicos, para cumplir las especificaciones de la aplicación.

  • Elaborar y mantener la documentación de los procesos de desarrollo, utilizando herramientas de generación de documentación y control de versiones.

  • Desplegar y distribuir aplicaciones Web en distintos ámbitos de implantación, verificando su comportamiento y realizando modificaciones.

  • Adaptarse a las nuevas situaciones laborales, manteniendo actualizados los conocimientos científicos, técnicos y tecnológicos relativos a su entorno profesional, gestionando su formación y los recursos existentes en el aprendizaje a lo largo de la vida y utilizando las tecnologías de la información y la comunicación.

Resultados de aprendizaje

RA nº 1.- Implanta arquitecturas Web analizando y aplicando criterios de funcionalidad.

RA nº 2.- Gestiona servidores Web, evaluando y aplicando criterios de configuración para el acceso seguro a los servicios.

RA nº 3.- Implanta aplicaciones Web en servidores de aplicaciones, evaluando y aplicando criterios de configuración para su funcionamiento seguro.

RA nº 4.- Administra servidores de transferencia de archivos, evaluando y aplicando criterios de configuración que garanticen la disponibilidad del servicio.

RA nº 5.- Verifica la ejecución de aplicaciones Web comprobando los parámetros de configuración de servicios de red.

RA nº 6.- Elabora la documentación de la aplicación Web evaluando y seleccionando herramientas de generación de documentación y control de versiones.

UNIDADES DIDÁCTICAS

EvaluaciónU.D.TítuloHoras previstasPeriodo de tiempo
nº 0Repaso conceptos previos6Septiembre
1ª Ev.nº 1Sistemas de control de versiones y documentación12Septiembre - Octubre
nº 2Servicios de red implicados en el despliegue de una aplicación Web18Octubre - Noviembre
nº 3Implantación de arquitecturas web8Noviembre – Diciembre
Examen 1ª Evaluación + corrección + repasos4Diciembre
2ª Ev.nº 4Administración de servidores Web y de aplicaciones18Diciembre – Febrero
nº 5Instalación y administración de servicios de transferencia de ficheros y acceso remoto12Febrero
nº 7Ampliación de contenidosMarzo
Examen 2ª Evaluación + corrección + repasos4Marzo
Examen final + corrección + repasos6Marzo

2 - Escribir documentación técnica

Escribir documentación técnica con markdown

Objetivos

  • Aprender a escribir documentación técnica.

2.1 - Markdown

Objetivo

  • Qué es Markdown?
  • Por qué usar Markdown

Documentación

Qué es Markdown?

Guías de estilo de documentación

Más recursos sobre markdown y documentación

Herramientas

2.2 - Ejercicio Markdown

Objetivo

Sigue las instrucciones de este vídeo tutorial https://www.lemoncode.tv/curso/vscode-markdown/leccion/basico

Previo

Tienes que tener instalado Visual Studio Code (https://code.visualstudio.com/)

Ampliación

Puedes ampliar exportando a pdf y usando el corrector ortográfico

3 - Introducción a los codespaces de GitHub

Uso de codespaces para desarrollo y despliegue

¿Qué es un codespace?

Aquí tienes una descripción: https://docs.github.com/en/codespaces/overview Es un servicio de GitHub que permite crear un entorno de desarrollo en la nube. Puedes usarlo para desarrollar y desplegar aplicaciones en la nube.

Codespace

Vídeotutoriales

4 - NGINX

NGINX

Práctica Inicial: Instalación de NGINX en una instancia EC2

  • Acceder a Lab y a la consola
  • EC2
  • Crear instancia
  • par claves

  • ver instancias
  • clic en id de instancia
  • conectar -> conectar
  • public IP

sudo dnf update
sudo dnf install nginx -y
sudo systemctl enable nginx
sudo systemctl start nginx
sudo systemctl status nginx
  • Comprobamos si se puede acceder a esa ip desde el navegador

  • No tiene abierto el puerto http (80)

  • Seguridad > grupos de seguridad > editar reglas de entrada

  • agregar regla > tcp > HTTP > anywhere

  • Vuelve a comprobar si puedes acceder a esa ip desde el navegador

  • test: cambio datos de mi index.html

Dónde está el index.html? $ cat /etc/nginx/nginx.conf

Práctica 1: Subir la web que hemos hecho con Hugo

  • Genera la web con Hugo
$ hugo --minify
  • Conecta con tu learner lab y descárgate la clave del lab labsuser.pem. En las instrucciones del lab tienes la explicación detallada para cada sistema operativo.
  • Comprime la carpeta public de tu web
  • Sube el fichero comprimido a tu servidor EC2
$ scp -i labuser.pem <fichero_comprimido> ec2-user@<ip_de_tu_ec2>:/home/ec2-user
  • Descomprímelo en la carpeta /usr/share/nginx/html
$ sudo unzip <fichero_comprimido> -d /usr/share/nginx/html
  • Comprueba si puedes acceder a tu web desde el navegador

Práctica 2: Crear un virtual host

Objetivo: queremos servir otra web distinta en la misma instancia EC2

En nginx se llaman server blocks

Pasos:

1. Estructura de Directorios

Por convención, se suele colocar el contenido de cada sitio web en su propio directorio dentro de /var/www/ o /usr/share/nginx. Por ejemplo:

/usr/share/nginx/site1.com
/usr/share/nginx/site2.com

o

/var/www/site1.com/public_html
/var/www/site2.com/public_html

2. Crear los directorios y añadir contenido de prueba:

sudo mkdir -p /usr/share/nginx/site1.com
sudo mkdir -p /usr/share/nginx/site2.com

echo "Bienvenido a site1.com" | sudo tee /var/www/site1.com/public_html/index.html
echo "Bienvenido a site2.com" | sudo tee /var/www/site2.com/public_html/index.html

3. Configurar los Server Blocks

Por convención, cada server block (o virtual host) se define en su propio archivo dentro de /etc/nginx/sites-available/ y luego se crea un enlace simbólico hacia /etc/nginx/sites-enabled/.

Crearemos dos archivos de configuración:

sudo nano /etc/nginx/sites-available/site1.com

Y añade lo siguiente (ajustando donde sea necesario):

server {
    listen 80;
    server_name site1.com www.site1.com;

    root /usr/share/nginx/site1.com;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

Guarda y cierra el archivo, luego crea el segundo server block:

sudo nano /etc/nginx/sites-available/site2.com

Y añade:

server {
    listen 80;
    server_name site2.com www.site2.com;

    root /usr/share/nginx/site2.com;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

4. Activar los Server Blocks

Para activar estos server blocks, crea un enlace simbólico de estos archivos hacia sites-enabled:

sudo ln -s /etc/nginx/sites-available/site1.com /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/site2.com /etc/nginx/sites-enabled/

5. Verificar la Configuración de Nginx

Es recomendable verificar la configuración de Nginx para asegurarte de que no hay errores sintácticos:

sudo nginx -t

Si todo está bien, deberías ver algo como:

nginx: configuration file /etc/nginx/nginx.conf test is successful

6. Reiniciar Nginx

Por último, reinicia Nginx para que los cambios surtan efecto:

sudo systemctl restart nginx

7. Crea las entradas en tu archivo hosts local

En linux: /etc/hosts En Windows: C:\Windows\System32\drivers\etc\hosts

con las siguientes líneas:

<ip_pública_de_tu_ec2> site1.com
<ip_pública_de_tu_ec2> site2.com

8. Comprueba si puedes acceder a tus webs desde el navegador

O desde la consola con curl:

$ curl site1.com
$ curl site2.com

Comprueba también los registros de log del servidor:

$ sudo tail -f /var/log/nginx/access.log
$ sudo tail -f /var/log/nginx/error.log

Práctica 3: Crear un virtual host con un certificado SSL

En construcción

5 - Webs basadas en PHP + BBDD

Despliegue de webs escritas en php con acceso a bases de datos.

Objetivos

  • Instalar los requisitos (servidor web + php + bbdd) en un servidor
  • Identificar los requisitos de la web a instalar
  • Descargar e instalar un CMS Wordpress

Documentación general

5.1 - Instalación base

Introducción a entornos lamp

El acrónimo LAMP se refiere a un entorno configurado en un servidor que nos posibilita servir aplicaciones web escritas en PHP.

Para ello usamos las siguientes tecnologías:

  • Linux, sistema operativo;
  • Apache o nginx, servidor web;
  • MySQL, MariaDB, gestores de bases de datos;
  • PHP, lenguaje de programación.

Instalación base

Partimos de una configuración base

vagrant init bento/ubuntu-22.04

Edita el Vagrantile para hacer el forward del puerto 8080 al puerto 80 por ejemplo

Vagrant.configure("2") do |config|
  config.vm.box = "bento/ubuntu-22.04"
  config.vm.network "forwarded_port", guest: 80, host: 8080
end

Levanta y actualiza el sistema

vagrant up
vagrant ssh
sudo apt update

mariadb

Instalación del servidor de base de datos

sudo apt install mariadb-server

Por defecto el usuario root no tiene contraseña, para acceder necesitaremos hacer con el root del sistema. Es muy recomendable ejecutar el programa mariadb-secure-installation para configurar la base de datos de manera segura, por ejemplo para indicar una contraseña al root.

Si necesitas crear una base de datos y un usuario que tenga acceso a la misma:

 mysql -u root -p
 CREATE DATABASE newdb;
 CREATE USER 'username'@'localhost' IDENTIFIED BY 'userpassword';
 GRANT ALL PRIVILEGES ON newdb.* to 'username'@'localhost';
 FLUSH PRIVILEGES;
 quit

Apache y PHP

Instalación de apache2 y del módulo que permite que apache2 interprete PHP (apache2 hará el papel de servidor web y de servidor de aplicaciones).

sudo apt install apache2 libapache2-mod-php php php-mysql

Configuración de PHP

Archivos de configuración de PHP (según versión. En este caso 7.4, que serguramente es más antigua):

  • /etc/php/7.4/cli: Configuración de php para php7.4-cli (ejecución de php desde la línea de comandos)
  • /etc/php/7.4/apache2: Configuración de php para apache2 usado como módulo
  • /etc/php/7.4/apache2/php.ini: Configuración de php
  • /etc/php/7.4/fpm: Configuración de php para php-fpm
  • /etc/php/7.4/mods-available: Módulos disponibles de php

Comprobación

Creamos un fichero info.php en el documentRoot (/var/www/html ) con el siguiente contenido:

<?php phpinfo(); ?>

Accedemos con el navegador. Si no aparece la información de php y vemos el contenido que hemos escrito, es que no se ha instalado correctamente. Tendrías que ver algo similar a esto:

Ahora podemos acceder a la URL: http://localhost:8080/info.php

Si tenemos problemas de acceso podemos ver los logs del servidor. El fichero de logs de acceso por “defecto”: /var/log/apache/access.log o el de errores: /var/log/apache/error.log

También podemos ver los logs del servicio ejecutando: sudo journalctl -u apache2

Instalación desatendida

Si ha funcionado esta instalación manual y atendida, destruye el entorno y haz que se genere toda la instalación de forma automática cuando ejecutas vagrant up

Tienes que usar un bootstrap.sh que ejecute tus comandos. Busca ejemplos en internet o usa ChatGPT si tienes dudas. Se trata de que no tengas que perder tiempo ejecutando comandos cuando hagas una nueva instalación.

README.md

Elimina el contenido del fichero README.md del repositorio y crea uno nuevo con la documentación (recuerda que tiene que estar escrito en markdown) de todo el proceso de instalación. Incluye también las instrucciones para que alguien pueda usar el repositorio y usar tu instalación de php.

5.2 - Instalación de Bookmedic

Objetivo:

  • Desplegar una aplicación PHP construida a medida en tu servidor LAMP.

Recuerda

Como ya sabemos tenemos 3 maneras principales para ejecutar código PHP:

  1. Desde la línea de comandos (cli).
  2. Con el servidor web Apache2 y el módulo libapache2-mod-php.
  3. Con un servidor web y el servidor de aplicaciones fpm-php.

La configuración de php está dividida según desde donde se use (este ejemplo es para php 7.4):

  • /etc/php/7.4/cli: Configuración de php para php7.4-cli, cuando se utiliza php desde la línea de comandos.
  • /etc/php/7.4/apache2: Configuración de php para apache2 cuando utiliza el módulo.
  • /etc/php/7.4/fpm: Configuración de php para php-fpm.
  • /etc/php/7.4/mods-available: Módulos disponibles de php que puedes estar configurados en cualquiera de los escenarios anteriores.

Si nos fijamos en la configuración de php para apache2 con el módulo:

  • /etc/php/7.4/apache2/conf.d: Módulos instalados en esta configuración de php (enlaces simbólicos a /etc/php/7.4/mods-available).
  • /etc/php/7.4/apache2/php.ini: Configuración de php para este escenario.

¿Qué tienes que hacer?

A partir de una instalación básica de Apache + MariaDB + PHP, tienes que instalar la aplicación BookMedik, una aplicación web a medida para llevar el control de citas médicas, pacientes, médicos, historiales de citas, áreas médicas y mucho mas, pensado para centros médicos, clínicas y médicos independientes. Puedes encontrar la aplicación en https://github.com/lmorillas/bookmedik.

Para realizar la instalación sigue los siguientes pasos:

  1. Crea la base de datos y las tablas necesarias recuperando la copia de seguridad de la base de datos que encuentras en el fichero schema.sql. Se creará una base de datos llamada bookmedik. Crea un usuario que tenga privilegios sobre dicha base de datos.
  2. Crea un virtualhost con el que accederás con el nombre bookmedik.tunombre.org. Copia en el DocumentRoot los ficheros de la aplicación (podrías clonar el repositorio en el DocumentRoot).
  3. Vamos a configurar el acceso a la base de datos desde la aplicación, para ello cambia el fichero core\controller\Database.php indicando el usuario de acceso (el que has creado en el punto 1), su contraseña, la base de datos que se llama bookmedik y la dirección donde se encuentra la base de datos, que en este caso es localhost.
  4. Accede a la aplicación web usando la URL configurada en el virtualhost (usa el usuario admin y contraseña admin).
  5. Para esta aplicación no es necesario, pero en determinadas aplicaciones es posible que necesitemos cambiar la memoria RAM que puede utilizar. Cambia la memoria máxima de uso de un script PHP (parámetro memory_limit) a 256Mb. ¿En qué fichero lo tienes que cambiar?. Investiga.

Una vez que esté la aplicación funcionando, configura un archivo bootstrap.sh que instale la aplicación automáticamente.

7 - Webs basadas en Python

Despliegue de webs escritas en python con acceso a bases de datos y cache.

Objetivos

Python es otro lenguaje de programación muy popular. Muchas webs y aplicaciones están programadas en Python. Tenemos que aprender cómo se instala un web escrita en python.

7.1 - Introducción

Objetivo

Introducción al despliegue de webs con python

Python

Python es un lenguaje:

  • Interpretado
  • Alto nivel
  • Multiparadigma, ya que soporta orientación a objetos, programación imperativa y programación funcional.
  • Multiplataforma
  • https://www.python.org/

Entornos virtuales Python

Entorno virtual: “espacios aislados” (directorio) donde poder instalar distintas versiones de programas y paquetes python. Nos permiten:

  • Utilizar versiones de paquetes python que no son las que vienen empaquetadas oficialmente en nuestra distribución linux
  • Acercar los entornos de desarrollo, prueba y producción.
  • Tener en producción vaias aplicaciones con versiones de librerías pythons distintas.

Entronos virtuales Python

Uso general (en Ubuntu). Por defecto ya está instalado python3. Puede

$ sudo apt-get install python3-venv 
$ python3 -m venv env
$ source env/bin/activate
(env)$ pip install <paquete>  # Instala paquetes en el entorno virtual
(env)$ pip install -r requirements.txt  # Instala paquetes desde un archivo requirements
(env)$ deactivate
$

Generar el archivo de requisitos (paquetes y versiones que usa el entorno)

(env)$ pip freeze > requirements.txt

Recuerda introducir siempre la carpeta del entorno virtual en el fichero .gitignore para que no se suba al repositorio. Sólo tienes que incluir el fichero requirements.txt.

Introducción al protocolo WSGI

¿Cómo podemos hacer que un servidor web como apache2 sea capaz de servir una aplicación escrita en python?

  • Para ello se utiliza un protocolo que nos permite comunicar al servidor web con la aplicación web: WSGI (Web Server Gateway Interface).
  • WSGI define las reglas para que el servidor web se comunique con la aplicación web.

Introducción al protocolo WSGI

Para que un servidor web o un servidor de aplicaciones pueda ejecutar el código python:

  • El servidor accede a un único fichero (fichero de entrada). Este fichero se llama fichero WSGI.
  • La aplicación web python con la que se comunica el servidor web utilizando el protocolo WSGI se debe llamar application. Por lo tanto el fichero WSGI entre otras cosas debe nombrar a la aplicación de esta manera.

Ejemplo de fichero WSGI

Para una aplicación flask podemos tener un fichero wsgi.py con el siguiente contenido:

from programa import app as application
  • programa corresponde con el nombre del módulo, es decir del fichero del programa, en nuestro caso se llama programa.py.
  • app corresponde a la aplicación flask creada en programa.py: app = Flask(__name__).
  • Importamos la aplicación flask, pero la llamamos application, necesario para que el servidor web pueda enviarle peticiones.

Configuración de servidores web

  • Si tenemos apache2 podemos usar el módulo wsgi: libapache2-mod-wsgi-py3.
  • Con apache2 y nginx podemos usar un servidor de aplicación python: Lista. Vamos a usar uwsgi.
  • En este caso el contenido estático lo devuelve el servidor web y la ejecución del código python lo hace uwsgi. El servidor web hará de proxy inverso para que podamos acceder a la aplicación.

Frameworks python

Un framework es una aplicación, que nos ayuda en el desarrollo de aplicaciones web. Ejemplos de frameworks python: flask, django,…

Django

Django es un framework de desarrollo web de código abierto, escrito en Python, que respeta el patrón de diseño conocido como modelo–vista–controlador (MVC).

El modelo MVC es un patrón de diseño software que separa los datos de la aplicación, la lógica del programa y la representación de la información:

  • El Modelo: Es la representación de la información con la cual el sistema opera, por lo tanto gestiona todos los accesos a dicha información.
  • El Controlador: Es la parte del programa donde se implementa la lógica y las funciones de la aplicación.
  • La Vista: Representa la información ofrecida por la aplicación en un formato adecuada.

Lista de cms desarrollados en Django

7.2 - Entorno básico con apache2 + mod_wsgi

Objetivo

Documentación

¿Qué es WSGI?

Pasos instalación

Levanta una máquina vagrant Ubuntu (la Ubuntu-22.04 que estás usando por ejemplo) e instala apache2, git, python3 y python3-venv si no está instalado.

Clonar el repositorio

En /var/www/

$ sudo git clone https://github.com/lmorillas/flask_temperaturas.git

Prepara máquina virtual para entornos de python

En /var/www/flask_temperaturas ejecuta:

$ python3 -m venv env   # Crea un entorno virtual
$ source env/bin/activate  # Activa el entorno virtual
$ cd flask_temperaturas
$ pip install -r requirements.txt  # Instala dependencias

Instala y configura el módulo wsgi para apache2

$ sudo  apt install libapache2-mod-wsgi-py3

Activar el módulo wsgi

Nuestra aplicación se encuentra en /var/www/flask_temperaturas. Nuestro entorno virtual está en /var/www/flask_temperaturas/env.

Creación del fichero wsgi

Lo primero que vamos a hacer es crear el fichero WSGI, que vamos a llamar wsgi.py estará en /var/www/flask_temperaturas y tendrá el siguiente contenido:

    from app import app as application

Explicación:

  • El primer app corresponde con el nombre del módulo, es decir del fichero del programa, en nuestro caso se llama app.py.
  • El segundo app corresponde a la aplicación flask creada en app.py: app = Flask(__name__).
  • Importamos la aplicación flask, pero la llamamos application necesario para que el servidor web pueda enviarle peticiones.

Configuración de apache2

Yo he utilizado el virtualhost por defecto, si usamos otro virtualhost esta configuración ira en el fichero correspondiente:

    WSGIDaemonProcess flask_temp python-path=/var/www/flask_temperaturas:/var/www/flask_temperaturas/env/lib/python3.10/site-packages
    WSGIProcessGroup flask_temp
    WSGIScriptAlias / /var/www/flask_temperaturas/wsgi.py process-group=flask_temp
    <Directory /var/www/flask_temperaturas>
            Require all granted
    </Directory>

Fíjate en la ruta /var/www/flask_temperaturas/env/lib/python3.10/site-packages Si usas otra versión de python, tendrás que cambiarla.

Vamos a explicar la configuración:

  • El DocumentRootse indica el directorio donde está la aplicación. Realmente el servidor web siempre va a llamar al fichero WSGI wsgi.py, pero el DocumentRoot es necesario por si hay contenido estático.
  • La directiva WSGIDaemonProcess: Se define un grupo de procesos que se van a encargar de ejecutar la aplicación (servidor de aplicaciones). A estos procesos se le ponen un nombre (flask_temp) y se indica los directorios donde se encuentran la aplicación y los paquetes necesarios (python-path), como puedes observar se pone el directorio donde esta la aplicación y el directorio donde se encuentran los paquetes en el entorno virtual, separados por dos puntos.
  • WSGIProcessGroup: Nos permite agrupar procesos. Se pone el misimo nombre que hemos definido en la directiva anterior.
  • La directiva WSGIScriptAlias nos permite indicar que programa se va a ejecutar (el fichero WSGI: /var/www/flask_temperaturas/wsgi.py) cuando se haga una petición a la url / y que proceso lo va a ejecutar.

La carpeta /var/www/flask_temperaturas debe tener los siguientes permisos:

$ sudo chown -R www-data:www-data /var/www/flask_temperaturas

Reinicia el servicio web y prueba el funcionamiento. Si te da algún erro 500 puedes ver los errores, en /var/log/apache2/error.log.

7.3 - Despliegue con Gunicorn

Objetivo

Documentación

Gunicorn es un servidor web que permite ejecutar una aplicación en un proceso independiente. Usamos los servidores web como proxies inversos que envían la petición python al servidor WSGI que estemos utilizando

Configuración Vagrant

Configura el forward del puerto 8080 al puerto 8080 de la máquina virtual

Instalar Gunicorn

En /home/vagrant/

Activa en entorno virtual

source env/bin/activate
pip install gunicorn

(env) /home/vagrant/flask_temperaturas$ gunicorn -w 2 -b :8080 wsgi

Comprueba con tu navegador que puedes acceder al puerto 8080 y que responde ahora gunicorn

Sigue la documentación base

Atento porque puede cambiar alguna dirección

  • Crea un servicio en systemd
  • Activa e inicia el servicio
  • Configura Apache2 compo un proxy inverso.

Comprueba con tu navegador que puedes acceder al puerto 8000 y que resonde apache. Elimina el forward del puerto 8080 y reinicia vagrant. Comprueba que la aplicación sigue funcionando.

7.4 -

8 - Introducción a AWS

Introducción al despliegue en la nube AWS

¿Qué es AWS Academy?

Crear instancia EC2

EC2 con User Data

8.1 - Práctica Inicial

Primera práctica

Introducción a EC2

Revisa documentación del módulo 6: https://awsacademy.instructure.com/courses/34868/modules#module_390032

Taller guiado de EC2 del curso Cloud Foundations

https://awsacademy.instructure.com/courses/34868/modules/items/2944677

8.2 - Práctica Apache con VirtualHosts

Práctica de instalacion de apache con 2 virtualhosts

Learner Lab

Ayuda configuración apache:

Objetivo:

Instalar apache en una instancia ECS y configurar 3 virtualhosts: uno para la página principal, otro para la página de relojesvex y otro para airspace. Las dos últimas webs están en la tarea de moodle.

Tareas:

  • Instala apache en la instancia EC2 y configura los vhosts
  • Tendrás que configurar el archivo hosts de tu máquina local para que puedas acceder a las páginas web desde tu navegador.
  • La web principal (a la que accedes por la ip pública de la instancia EC2) debe mostrar un mensaje de bienvenida y un enlace a las otras dos páginas.
  • Los archivos de las webs los puedes subir por scp (revisa cómo se configura el ssh en los Learner Lab) o si lo subes a un sitio público, puedes descargarlo con wget y descomprimirlo dentro de la máquina en la nube

8.3 - Despliegue de una web estática con S3 + CloudFront

Despligue de una web estática en S3 + CloudFront

Static Web S3

Objetivo:

Desplegar una web estática en S3 y añadir CloudFront como CDN.

Tarea1: Despliegue de una web estática en S3

Sigue las instrucciones de https://docs.aws.amazon.com/AmazonS3/latest/userguide/HostingWebsiteOnS3Setup.html

  • Crear un bucket S3
  • Configurar el bucket para que sea accesible como web estática
  • Añade los ficheros de una de las webs estáticas del ejercicio anterior. Puedes subirlos desde la misma interfaz web de la consola de AWS. Veremos también cómo puedes hacerlo desde AWS CLI.

Tarea2: Añadir CloudFront como CDN

Sigue el ejemplo de https://aws.amazon.com/es/blogs/aws-spanish/como-alojar-tu-sitio-web-estatico-en-amazon-s3-y-amazon-cloudfront/

Nosotros no integraremos AWS CodePipeline, AWS CodeCommit y AWS CodeBuild.

Aquí tienes un ejemplo paso a paso:

8.3.1 - Despliegue de una web hecha con Hugo en S3

Despligue de una web estática con Hugo en S3 + CloudFront

Pasos

Previo

Configurar AWS CLI

  • Conecta con el Learner Lab
  • Copia las credentials de tu usuario de IAM en ~/.aws/credentials

Configurar hugo.yml

Ejemplo

[deployment]
# By default, files are uploaded in an arbitrary order.
# Files that match the regular expressions in the "Order" list
# will be uploaded first, in the listed order.
order = [".jpg$", ".gif$"]


[[deployment.targets]]
# An arbitrary name for this target.
name = "mydeployment"

# S3; see https://gocloud.dev/howto/blob/#s3
# For S3-compatible endpoints, see https://gocloud.dev/howto/blob/#s3-compatible
URL = "s3://<Bucket Name>?region=<AWS region>" # Configura aquí tu bucket

# If you are using a CloudFront CDN, deploy will invalidate the cache as needed.
cloudFrontDistributionID = <ID>  # Sólo si quieres usar cloudfront

# Optionally, you can include or exclude specific files.
# See https://godoc.org/github.com/gobwas/glob#Glob for the glob pattern syntax.
# If non-empty, the pattern is matched against the local path.
# All paths are matched against in their filepath.ToSlash form.
# If exclude is non-empty, and a local or remote file's path matches it, that file is not synced.
# If include is non-empty, and a local or remote file's path does not match it, that file is not synced.
# As a result, local files that don't pass the include/exclude filters are not uploaded to remote,
# and remote files that don't pass the include/exclude filters are not deleted.
# include = "**.html" # would only include files with ".html" suffix
# exclude = "**.{jpg, png}" # would exclude files with ".jpg" or ".png" suffix


# [[deployment.matchers]] configure behavior for files that match the Pattern.
# See https://golang.org/pkg/regexp/syntax/ for pattern syntax.
# Pattern searching is stopped on first match.

# Samples:

[[deployment.matchers]]
# Cache static assets for 1 year.
pattern = "^.+\\.(js|css|svg|ttf)$"
cacheControl = "max-age=31536000, no-transform, public"
gzip = true

[[deployment.matchers]]
pattern = "^.+\\.(png|jpg)$"
cacheControl = "max-age=31536000, no-transform, public"
gzip = false

[[deployment.matchers]]
# Set custom content type for /sitemap.xml
pattern = "^sitemap\\.xml$"
contentType = "application/xml"
gzip = true

[[deployment.matchers]]
pattern = "^.+\\.(html|xml|json)$"
gzip = true

Crear web

Genera la web en el directorio public

$ hugo

Desplegar web

$ hugo deploy

8.3.2 - Crear web estática en S3 con CLI

Crear Web estática en S3 con AWS CLI

Pasos

Previo

Configurar AWS CLI

  • Conecta con el Learner Lab
  • Copia las credentials de tu usuario de IAM en ~/.aws/credentials

Crear Bucket S3


bucket_name="miwebs3-nombre-bucket-unico"

aws s3api create-bucket --bucket "${bucket_name}"

Configuramos el bucket para que sea publico

aws s3api put-public-access-block --bucket "${bucket_name}" --public-access-block-configuration "BlockPublicPolicy=false"

aws s3api put-bucket-policy --bucket "${bucket_name}" --policy '{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::'"${bucket_name}"'/*"
 
            ]
        }
    ]
}'

Subimos un fichero html

Mostramos un ejemplo, puedes subir tu web estática

echo "<html><center><h1>My Static Website on S3</h1></center></html>" > index.html

aws s3 cp index.html s3://"${bucket_name}"

Configuramos el bucket para que sea un sitio web

aws s3 website s3://"${bucket_name}" --index-document index.html

Comprobamos que funciona

curl http://"${bucket_name}".s3-website.us-east-1.amazonaws.com

8.4 - Práctica 3 Apaches en EC2 + EFS

Práctica de instalacion de dos máquinas compartiendo un volumen EFS

Objetivo:

  • Crear un servicio web con un sistema de ficheros compartido

Tareas:

En construcción

8.5 - Práctica - Certificado SSL

Requisitos

  • Nombre de dominio
  • Configurado con la ip pública de una máquina ECS
  • Servidor web configurado en esa máquina

Instalación Certbot

# instalación paquetes
$ sudo dnf install -y python3 augeas-libs pip

# Creación entorno virtual python
$ sudo python3 -m venv /opt/certbot/

# Actualización pip 
$ sudo /opt/certbot/bin/pip install --upgrade pip

# Instalación certbot
$ sudo /opt/certbot/bin/pip install certbot certbot-apache

Creación certificado

# parar servidor (certbot levanta uno)
$ sudo systemctl stop httpd

$ sudo /opt/certbot/bin/certbot certonly --standalone

# o también más fácil

$ sudo /opt/certbot/bin/certbot --apache

# Sigue los pasos

# Instala el certificado si certbot no ha configurado los archivos de httpd

Al final tendremos estos archivos de configuración.

/etc/httpd/conf.d/ssl.conf

# Dentro tendrá unas líneas similares
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/www.cpilosenlaces.ninja/fullchain.pem
SSLCertificateKeyFile  /etc/letsencrypt/live/www.cpilosenlaces.ninja/privkey.pem

/etc/httpd/conf/httpd.conf

Configuración del virtualhost y la redirección de http a https

<VirtualHost *:80>
    DocumentRoot "/var/www/html"
    ServerName "www.cpilosenlaces.ninja"
    ServerAlias "cpilosenlaces.ninja"
    #Redirect HTTP to HTTPS
    RewriteEngine On 
    RewriteCond %{HTTPS} off
    RewriteCond %{HTTP:X-Forwarded-Proto} !https 
    RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</VirtualHost>

Vuelve a iniciar apache

$ sudo systemctl stop httpd

Y comprueba que funciona correctamente el certificado y la redirección

Configuración renovación automática

Puedes configurar la renovación automática del certificado

$ echo "0 0,12 * * * root /opt/certbot/bin/python -c 'import random; import time; time.sleep(random.random() * 3600)' && sudo certbot renew -q" | sudo tee -a /etc/crontab > /dev/null

$ sudo systemctl restart crond

8.6 - Práctica - Flask App en EC2

Pasos

  • Instalar app flask
  • Ejectar con Gunicorn
  • Configurar Gunicorn como servicio
  • Configurar Apache o Nginx como proxy inverso

Gunicorn y Flask

Conexión con Putty

Apapche / Nginx proxy inverso

Requisitos

# /etc/systemd/system/temperaturas.service
[Unit]
Description=Gunicorn daemon to serve my flaskapp
After=network.target

[Service]
User=ec2-user
#Group=apache
WorkingDirectory=/home/ec2-user/Weather-App
ExecStart=/home/ec2-user/Weather-App/env/bin/gunicorn -w 2 -b 127.0.0.1:8080 run:app
ExecReload=/bin/kill -s HUP $MAINPID

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload 
sudo systemctl restart temperaturas
sudo systemctl status temperaturas

Configurar Apache como proxy inverso

Versión sencilla

# /etc/httpd/conf.d/temperaturas.conf

DocumentRoot "/home/ec2-user/Weather-App"

ProxyPass / http://127.0.0.1:5000/
ProxyPassReverse / http://127.0.0.1:5000/

<Directory /home/ec2-user/Weather-App>
 Require all granted
</Directory>

User Data

Si configuras la instacia (tipo, tamaño, claves, puertos, etc) desde la consola de AWS, puedes añadir un script de arranque que se ejecutará al arrancar la máquina.

#!/bin/bash
yum update -y
yum install -y httpd git
#Apache
systemctl start httpd
systemctl enable httpd
# Tempertaturas
cd /home/ec2-user
git clone https://github.com/DAW-distancia/Weather-App.git
cd Weather-App
python3 -m venv env
source env/bin/activate
pip install -r requirements.txt
# inicializa db
python -c "from weather_app import db; db.create_all()"
# Gunicorn
pip install gunicorn
# Permisos (si no, serán los archivos de root)
chown -R ec2-user:apache /home/ec2-user/Weather-App
# Servicio
cat <<EOF > /etc/systemd/system/temperaturas.service
[Unit]
Description=Gunicorn daemon to serve my flaskapp    
After=network.target

[Service]
User=ec2-user
#Group=apache
WorkingDirectory=/home/ec2-user/Weather-App
ExecStart=/home/ec2-user/Weather-App/env/bin/gunicorn -w 2 -b 127.0.0.1:8080 run:app
ExecReload=/bin/kill -s HUP $MAINPID

[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl start temperaturas
systemctl enable temperaturas
# Apache
cat <<EOF > /etc/httpd/conf.d/temperaturas.conf
DocumentRoot "/home/ec2-user/Weather-App"

ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/

<Directory /home/ec2-user/Weather-App>
 Require all granted
</Directory>
EOF
systemctl restart httpd

8.7 - Route53 + CloudFront + S3

Alojar un sitio web estático en Amazon S3, Amazon CloudFront y Route 53

Guión basado en https://aws.amazon.com/es/blogs/aws-spanish/como-alojar-tu-sitio-web-estatico-en-amazon-s3-y-amazon-cloudfront/

Aprenderás:

  • Cómo alojar un sitio web estático en Amazon S3
  • Cómo configurar Amazon CloudFront para que sirva el contenido de Amazon S3
  • Cómo configurar Amazon Route 53 para que resuelva los nombres de dominio de tu sitio web
  • Cómo configurar tu sitio web para que se sirva a través de HTTPS
  • Enlazar el nuevo suddominio con CloudFront
  • Manejar S3 y CloudFront con AWS CLI
  • Invalidar páginas del caché de CloudFront

Cómo alojar un sitio web estático en Amazon S3, Amazon CloudFront y Route 53

Motivación

Hoy en día es muy habitual tener que servir algún tipo de sitio web estático, desde sencillas páginas web para que tus clientes puedan conocerte hasta complejas aplicaciones basadas en frameworks como React, Vue.js o Angular. En un escenario tradicional, este contenido se ofrecería desde un servidor web como Apache o NGINX ejecutándose, por ejemplo, en una instancia de Amazon EC2. Por lo tanto, el operador de la infraestructura debe encargarse de tareas como la configuración de los servidores y de la aplicación de parches y actualizaciones, y asegurarse de que hay redundancia para seguir respondiendo peticiones aunque alguna de las máquinas tenga algún problema.

En este artículo veremos cómo utilizar nuestro servicio de almacenamiento de objetos, Amazon S3, y nuestra red de entrega de contenido (CDN), Amazon CloudFront, para liberarte de esa carga de trabajo y servir tus aplicaciones y sitios estáticos de manera eficiente, segura, rápida y económica. Además, haremos uso de Amazon Route 53 para gestionar los registros DNS.

Descripción del escenario

  • Queremos crear un sitio web estático
  • El sitio debe alojarse de manera sencilla y requerir el mínimo esfuerzo de operación por nuestra parte.
  • El sitio debe poder visitarse a través de HTTPS usando nuestro propio dominio

Recuerda que tienes que crear tu propio dominio en name.com usando la promoción del student pack de github

  • El sitio debe estar disponible el máximo tiempo posible (alta disponibilidad).
  • El sitio debe servirse con baja latencia a todos nuestros clientes, que se encuentran repartidos por todos los países de habla hispana.
  • El sitio debe ser fácil de actualizar, de manera que podamos cambiar el contenido sin tener que preocuparnos por la infraestructura.

El siguiente diagrama muestra la arquitectura de la solución: S3-CF-Route53

Alojamiento del sitio en Amazon S3

Amazon S3 es el servicio de almacenamiento de objetos de AWS, que permite guardar y acceder a cualquier tipo de fichero de hasta 5 TB de tamaño de manera segura a través de una API. Los clientes no tienen que gestionar ningún tipo de servidor. Internamente, Amazon S3 se encarga de almacenar múltiples copias del objeto en diferentes Zonas de Disponibilidad dentro de la región seleccionada, razón por la que ofrece una durabilidad que alcanza los 11 nueves (99.999999999%).

La unidad lógica de almacenamiento en S3 es el bucket. El primer paso consiste en crear un bucket, dentro del cuál subiremos los archivos de nuestra web. Recuerda que en los lab usamos la región us-east-1.

Pasos

  • Dirígete a la consola de administración de Amazon S3.
  • En la lista de buckets, haz click en Create bucket.
  • Dale un nombre arbitrario a tu bucket (recuerda que los nombres deben ser únicos dentro de S3 de manera global). Puedes dejar el resto de opciones como están.
  • Haz click en Create bucket.
  • Ve a la vista de detalle del bucket. Haz click en Upload y sube los ficheros de tu web.

Ahora mismo, estos objetos son privados y no son accesibles por ningún usuario excepto nosotros. Este es el comportamiento por defecto de S3, aunque los clientes pueden ajustar los permisos de manera granular (idealmente, siguiendo siempre el principio de mínimo privilegio).

S3 ofrece una característica que permite acceder a los objetos de un bucket como si se tratara de un servidor web. Técnicamente esta solución nos podría servir, pero entonces obligaríamos a todos nuestros clientes a acudir a nuestro bucket, que está en la región de us-east-1. Un usuario de Europa lo tendría muy lejos. Incumplimos uno de los requisitos que nos propusimos al inicio. Sin embargo, tenemos otras opciones.

Uso de Amazon CloudFront para servir el sitio

Las redes de entrega de contenidos (content delivery network, CDN) son servidores distribuidos por todo el mundo que actúan como caché para cierto contenido web, idealmente contenido estático que no varía de manera frecuente. Cuando un cliente visita un sitio que se sirve a través de una CDN, su petición acude primero a su caché local (que debería estar muy cerca de él, en su mismo país o incluso en la ciudad). Si el contenido no se encuentra en la caché, la CDN solicita el contenido al origen, lo devuelve al cliente y lo almacena en la caché. A partir de ahí, las peticiones de otros clientes se servirán desde la propia caché mientras el objeto siga ahí, reduciendo de manera notable la latencia de respuesta.

Amazon CloudFront es el servicio de CDN de AWS. Con más de 220 puntos de presencia (PoPs) en todo el mundo, podemos usar CloudFront para servir nuestro contenido a usuarios de manera global con una latencia baja, usando el bucket de S3 que creamos previamente como origen. Para ello tenemos que crear una distribución.

Pasos

  1. Ve a la consola de administración de Amazon CloudFront.
  2. En la lista de distribuciones haz click en Create Distribution, y luego selecciona una distribución Web.
  3. En Origin Domain Name, introduce el nombre de dominio de tu bucket completo, por ejemplo mi-bucket-de-daw.s3-us-east-1.amazonaws.com.
  4. En Restrict Bucket Access selecciona Yes.
  5. En Origin Access Identity escoge Create a New Identity.
  6. En Grant Read Permissions on Bucket selecciona Yes, Update Bucket Policy.
  7. En Viewer Protocol Policy escoge Redirect HTTP to HTTPS.
  8. En Default Root Object introduce el archivo correspondiente, en principio index.html.
  9. Haz click en Create Distribution.

Con los pasos 4, 5, y 6 nos aseguramos de que sólo CloudFront puede acceder a los objetos de S3, mediante una identidad de acceso a origen (origin access identity, OAI). Un cliente llamando directamente al bucket de S3 vería su acceso denegado.

La distribución tiene que desplegarse ahora. Tras unos minutos, la distribución pasará a estado Deployed. Si visitas la URL que aparece bajo la columna Domain Name, verás tu web.

Dominio personalizado

Ya tenemos la distribución de CloudFront sirviendo nuestra web por todo el mundo. Sin embargo, el dominio por defecto que CloudFront nos asigna (ab12cd34ef56gh.cloudfront.net) no es, digamos, muy atractivo. Sería ideal poder usar nuestro propio dominio (por ejemplo, www.anycompany.example).

Amazon Route53 es el servicio de AWS para adquirir y gestionar nombres de dominio. Con un SLA del 100%, a través de Route 53 podemos configurar registros DNS que resolverán nuestro dominio a las IPs adecuadas. Además, usaremos AWS Certificate Manager (ACM) para generar de manera gratuita un certificado TLS para nuestro dominio, que asociaremos a CloudFront para poder servir tráfico HTTPS. De nuevo, esto se hará fácilmente y sin tener que gestionar servidores ya que se trata de servicios totalmente gestionados.

Creación de una hosted zone en Amazon Route 53

Con los Learner Lab no podemos adquirir dominios, pero sí gestionarlos.

En Amazon Route 53 todos los registros DNS pertenecientes a un dominio se configuran en una hosted zone. El primer paso es, por lo tanto, crear una:

Dirígete a la consola de administración de Amazon Route 53.

  • En el menú de la izquierda, haz click en Hosted zones.
  • En la lista de hosted zones, haz click en Create hosted zone.
  • En Domain name introduce el dominio raíz que quieres gestionar (el que hayas adquirido en name.com).
  • Asegúrate de que el tipo es Public hosted zone, y haz click en Create hosted zone.

Todas las hosted zones vienen con un registro NS. Éste contiene los servidores de nombres autoritativos para esta hosted zone a los que debes apuntar desde tu registrador, en caso contrario los cambios que realices a continuación no tendrán efecto. En name.com ve a manage nameservers del dominio que has registrado y cambia los servidores de nombres por los que te proporciona Route 53.

nameservers

Creación de un registro DNS hacia la distribución de Amazon CloudFront

En la vista de detalle de la hosted zone de route53, sigue estos pasos para añadir un registro DNS que permita resolver nuestro subdominio a la distribución de CloudFront:

  • Haz click en Create record, selecciona Switch to wizard y escoge Simple routing.
  • Haz click en Define simple record.
  • En Record name, escribe el prefijo del subdominio. En nuestro caso, www.
  • En Value/Route traffic to selecciona Alias to CloudFront distribution, e introduce el dominio de tu distribución (similar a “ab12cd34ef56gh.cloudfront.net”) en el campo Choose distribution.
  • Haz click en Define simple record, y a continuación en Create records.

Si ahora resuelves el subdominio completo con una herramienta como nslookup o dig, verás que Route 53 proporciona un conjunto de IPs correspondientes al PoP de CloudFront más cercano a ti.

Creación de un certificado TLS con AWS Certificate Manager

Antes de poder servir tráfico HTTPS usando nuestro dominio personalizado necesitamos crear un certificado TLS. AWS Certificate Manager (ACM) permite generar certificados de manera gratuita. Además, ACM se encarga de aplicarlos a servicios como CloudFront e incluso de renovarlos automáticamente antes de la fecha de expiración. Una vez más, de forma totalmente gestionada.

Antes de emitir el certificado, ACM comprobará que nosotros somos los propietarios del dominio. ACM se integra con Route 53 para crear automáticamente los registros DNS necesarios, haciéndolo si cabe aún más sencillo:

  • Ve a la consola de administración de AWS Certificate Manager.
  • En la lista de certificados, haz click en Request a certificate.
  • Selecciona Request a public certificate y haz click en Request a certificate.
  • En Add domain names escribe el subdominio que hemos registrado en Route 53 (en nuestro ejemplo, www.anycompany.example) y haz click en Next.
  • Selecciona DNS validation y haz click en Next.
  • Haz click en Review, y posteriormente en Confirm and request.
  • El dominio estará en el estado Pending validation. Para añadir automáticamente los registros de Route 53 necesarios para que ACM los valide, despliega el detalle del dominio y haz click en Create record in Route 53.
  • Haz click en Create tras revisar el registro que será creado.
  • Por último, haz click en Continue.

Tras pocos minutos, el certificado pasará al estado Issued y ya podrá usarse en CloudFront.

Modificación de la distribución de Amazon CloudFront para usar nuestro dominio

El último paso consiste en modificar la distribución de CloudFront para que acepte tráfico dirigido a nuestro dominio:

Ve, de nuevo, a la consola de administración de Amazon CloudFront y selecciona la distribución creada previamente.

  • En la pestaña General, haz click en Edit.
  • En el campo Alternate Domain NAmes (CNAMEs), que antes dejamos en blanco, añade tu dominio (en nuestro caso, www.anycompany.example).
  • En SSL Certificate, escoge Custom SSL Certificate (example.com), y en el campo de texto selecciona el certificado que has creado en ACM.

Cuando el cambio se propague a todos los PoPs, podrás visitar el sitio web con el dominio personalizado.

Despliegue automático de cambios y cache busting

Esta parte la haremos en otra práctica

Despliegue con el cliente de AWS CLI

Subir archivos a s3

# Listado de buckets
aws s3 ls
# Copiar archivos al bucket. En mi caso:
aws s3 cp index.html s3://exhibit-lmorillas/

Invalidar cache de cloudfront

La caché de cloudfront se puede configurar para que expire cada cierto tiempo, pero también podemos invalidar la caché de forma manual. Por defecto los objetos estarán 24 horas. Pero si hacemos un cambio y queremos que se vea inmediatamente, podemos invalidar la caché.

Ejemplo con AWS CLI:

# Listado de distribuciones de cloudfront
aws cloudfront list-distributions
# crear invalidación. Fíjate el el id de la distribución
aws cloudfront create-invalidation --distribution-id ET29UE5BESTWD --path "/index.html"

8.8 - Práctica - Instalación de Docker en EC2

Presentación:

AWS tiene un servicio de contenedores ECS que permite ejecutar contenedores en la nube. Pero en esta práctica vamos a instalar Docker en una instancia EC2 y ejecutar un contenedor de prueba.

Para desarrollo con contenedores, mejor usar ECS y ECR

Instalación de Docker

Probado en AMI 2023

Todos los comando se ejecutan como root (con sudo)

sudo yum update
# Puedes buscar el paquete
yum search docker
yum info docker

# Instalar docker
sudo yum install docker

# servicio y comprobación
sudo systemctl enable docker
sudo systemctl start docker
sudo systemctl status docker

# Hay que añadir el usuario al grupo docker para que pueda ejecutar los comandos
sudo usermod -a -G docker ec2-user
id ec2-user

# recargar el user (o salir y entrar en el shell)
newgrp docker

Puedes comprobar que funciona correctamente con:

docker run hello-world

Instalación de docker-compose

# 1. Instalar pip 
sudo yum install python3-pip
# 2. Elige uno de los 3 métodos siguientes
sudo pip3 install docker-compose # con  root access
 
# O
pip3 install --user docker-compose # sin root access for security reasons

# O también
wget https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) 
sudo mv docker-compose-$(uname -s)-$(uname -m) /usr/local/bin/docker-compose
sudo chmod -v +x /usr/local/bin/docker-compose

Comprobación:

docker-compose --version

Un ejemplo complejo

Vamos a instalar una aplicación más compleja y a interactuar con los contenedores. La aplicación a instalar es BakeryDemo, un CMS de prueba de Wagtail.

En el README tienes las instrucciones para instalar con docker-compose. Si analizas el docker-compose:

version: '2'

services:
  db:
    environment:
      POSTGRES_DB: app_db
      POSTGRES_USER: app_user
      POSTGRES_PASSWORD: changeme
    restart: unless-stopped
    image: postgres:14.1
    expose:
      - '5432'

  redis:
    restart: unless-stopped
    image: redis:6.2
    expose:
      - '6379'

  app:
    environment:
      DJANGO_SECRET_KEY: changeme
      DATABASE_URL: postgres://app_user:changeme@db/app_db
      REDIS_URL: redis://redis
      DJANGO_SETTINGS_MODULE: bakerydemo.settings.dev
    build:
      context: .
      dockerfile: ./Dockerfile
    volumes:
      - ./bakerydemo:/code/bakerydemo
    links:
      - db:db
      - redis:redis
    ports:
      - '8000:8000'
    depends_on:
      - db
      - redis

Ves 3 servicios: una base de datos postgres, un redis para caché y la aplicación del CMS (con un Dockerfile específico para python)

Instalación:

# clonamos repositorio
git clone https://github.com/wagtail/bakerydemo.git
cd bakerydemo/

# construir y levantar el contenedor
docker-compose up --build -d

# Comprobar el estado
docker-compose ps

# Ejecutar carga inicial de datos. Son instrucciones que se ejecutan dentro del contenedor de la app
docker-compose run app /venv/bin/python manage.py migrate
docker-compose run app /venv/bin/python manage.py load_initial_data

# Comprobamos que funciona correctamente
curl localhost:8000

Para verlo desde el navegador tendrás que abrir el puerto 8000 en el grupo de seguridad y acceder con el navegador a la ip pública de la instancia EC2, puerto 8000

8.9 - Infraestrucutra como código: CloudFormation

Despliegue usando CloudFormation

Despliegue de una aplicación web con CloudFormation

Despliegue de una web estática en EC2 con NGINX usando CloudFormation

Requisitos

  • Instalar AWS CLI

Creación de la plantilla

Podemos tenerla en S3 o en local. En este caso la tendremos en local.

AWSTemplateFormatVersion: '2010-09-09'
Description: |
  Esta plantilla crea un grupo de seguridad con los puertos 22, 80 y 443 abiertos,
  crea una instancia EC2 con la AMI Amazon Linux 2023 y le asocia el grupo de seguridad.
  También crea una IP elástica y la asocia a la instancia EC2 mediante el recurso AWS::EC2::EIP.
  Configura nginx en la instancia EC2 y despliega una web estática en el directorio /usr/share/nginx/html. La web está en un recurso compartido en drive.google.com.
  En el output muestra la IP pública de la instancia EC2 (la IP elástica).  
Resources:
  MySecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: sg_web-nginx
      GroupDescription: Grupo de seguridad del web-nginx
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: 0.0.0.0/0
  MyEC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-04cb4ca688797756f
      InstanceType: t2.small
      SecurityGroups:
        - !Ref MySecurityGroup
      KeyName: vockey
      Tags:
        - Key: Name
          Value: nginx-user-data
      UserData:
        Fn::Base64: 
          !Sub |
            #!/bin/bash -xe
            dnf update -y
            dnf install nginx -y
            dnf install unzip -y
            systemctl start nginx
            systemctl enable nginx  
            cd /usr/share/nginx/html
            curl -L -o airspace.zip  "https://drive.google.com/uc?export=download&id=1CXihQ2U-EFzHaO3OnggQ6qkkxdC-ibsp"
            unzip airspace.zip
            # extracción de archivos: están en la carpeta airspace.com
            cd airspace.com
            mv * ..
            cd ..
            rm -r airspace.com/
            rm airspace.zip 
  MyEIP:
    Type: AWS::EC2::EIP
    Properties:
      InstanceId: !Ref MyEC2Instance

Outputs:
  Website:
    Description: The Public IP for the EC2 Instance (Elasic IP)
    Value: !Sub 'http://${MyEIP.PublicIp}'

Despliegue de la plantilla

Recuerda que tienes que tener instalado AWS CLI

Conecta con el Learner Lab (Start Lab) y configura las credenciales de AWS CLI (AWS Details -> AWS CLI -> Show)

Descarga el archivo nginx-user-data.yml con la plantilla anterior y ejecuta el siguiente comando:

$ aws cloudformation create-stack --stack-name nginx-user-data --template-body file://nginx-user-data.yml

Comprobación del despliegue

$ aws cloudformation describe-stacks --stack-name nginx-user-data

Cuando se haya desplegado podremos comprobar que la web está desplegada en la IP pública de la instancia EC2 (la IP elástica que muestra el output del comando anterior).

Eliminación de la pila

$ aws cloudformation delete-stack --stack-name nginx-user-data

Propuestas

  • Configurar https con certbot automatizado.
  • Desplegar varias páginas en nginx para diferentes dominios.

8.10 - Uso de AWS CLI con AWS CloudShell

Introducción al uso del CLI desde AWS CloudShell

Acceso AWS CloudShell

Tienes un botón para abrir el CloudShell

CloudShell ya tiene instalado y configurado el AWS CLI.

Uso del AWS CLI EC2

Listar instancias EC2

Todas las instancias. Toda la información. Salida como json

$ aws ec2 describe-instances

Todas las instancias. Toda la información. Salida como tabla

$ aws ec2 describe-instances --output table

Uso con filtros

Ip, nombre y estado de las instancias que están en ejecución. Salida como tabla

$ aws ec2 describe-instances  \
--query "Reservations[*].Instances[*].{PublicIP:PublicIpAddress,Name:Tags[?Key=='Name']|[0].Value,Status:State.Name}" \
--filters Name=instance-state-name,Values=running \
--output table

Id y nombre de las instancias

$  aws ec2 describe-instances  --query "Reservations[*].Instances[*].{Name:Tags[?Key=='Name']|[0].Value,InstanceId:InstanceId}" --output table

Parar instancia

$ aws ec2 stop-instances --instance-ids <id de instancia>

Arrancar instancia

$ aws ec2 start-instances --instance-ids <id de instancia>

Uso del AWS CLI S3

listar buckets

$ aws s3 ls

listar objetos de bucket

$ aws s3 ls s3://bucket-name

O recursivo

$ aws s3 ls s3://bucket-name --recursive

subir un archivo a un bucket

$ aws s3 cp file.txt s3://bucket-name

subir un directorio a un bucket

$ aws s3 cp --recursive dir s3://bucket-name

descargar un archivo de un bucket

$ aws s3 cp s3://bucket-name/file.txt .

eliminar bucket

$ aws s3 rb s3://bucket-name --force

eliminar objeto de un bucket

$ aws s3 rm s3://bucket-name/file.txt

8.10.1 - AWS CLI en AWS Academy

Configuración de AWS CLI con AWS Academy

Instalación de AWS CLI

https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html

Configuración en AWS Academy

9.1 - Introducción a los contenedores

Inicio:

Usa el vagrantfile para crear una máquina virtual con docker instalado. Tambén puedes probar a crear una máquina virtual vacía e instalar docker siguiendo estas instrucciones: https://josedom24.github.io/curso_docker_2022/sesion1/instalacion.html

Hola mundo

Conéctate a la máquina virtual por ssh y sigue estas instrucciones: https://josedom24.github.io/curso_docker_2022/sesion1/holamundo.html

Ejecución de comandos en contendores

Conéctate a la máquina virtual por ssh y sigue estas instrucciones: https://josedom24.github.io/curso_docker_2022/sesion1/contenedor.html

Ejecución interactiva

Conéctate a la máquina virtual por ssh y sigue estas instrucciones: https://josedom24.github.io/curso_docker_2022/sesion1/interactivo.html

Ejecución en detach

Conéctate a la máquina virtual por ssh y sigue estas instrucciones: https://josedom24.github.io/curso_docker_2022/sesion1/demonio.html

Contenedor con Apache

Conéctate a la máquina virtual por ssh y sigue estas instrucciones: https://josedom24.github.io/curso_docker_2022/sesion1/web.html

Ten en cuenta que el contenedor abre el puerto 80 dentro de la máquina virtual. Configura el forward de los puertos para que puedas verlo en tu navegador.

Variables de entorno

https://josedom24.github.io/curso_docker_2022/sesion1/configuracion.html

9.2 - Instalación mediawiki

Uso con Vagrant

Este Vagrantfile crea una máquina virtual con docker y docker-compose instalados.

Instalación de mediawiki con contenedores.

Sigue las instrucciones de https://josedom24.github.io/curso_docker_2022/sesion2/mediawiki.html

Las instrucciones anteriores instalan mediwiki con la base de datos sqlite.

Si quieres usar MySQL/MariaDB es mejor que uses docker-compose.

Tienes instrucciones en https://hub.docker.com/_/mediawiki Aquí tienes una versión más detallada usando también docker-compose: https://blog.programster.org/deploy-your-own-mediawiki-wiki o https://culturalibre.ar/2022/06/12/montar-una-wiki-de-lo-que-quieras-y-libre/

Información más detallada y específica hay en https://www.mediawiki.org/wiki/MediaWiki-Docker

Ejemplo del docker-compose.yml de mediawiki

# MediaWiki with MariaDB
#
# Access via "http://localhost:8080"
#   (or "http://$(docker-machine ip):8080" if using docker-machine)
version: '3'
services:
  mediawiki:
    image: mediawiki
    restart: always
    ports:
      - 8080:80
    links:
      - database
    volumes:
      - images:/var/www/html/images
      # After initial setup, download LocalSettings.php to the same directory as
      # this yaml and uncomment the following line and use compose to restart
      # the mediawiki service
      # - ./LocalSettings.php:/var/www/html/LocalSettings.php
  # This key also defines the name of the database host used during setup instead of the default "localhost"
  database:
    image: mariadb
    restart: always
    environment:
      # @see https://phabricator.wikimedia.org/source/mediawiki/browse/master/includes/DefaultSettings.php
      MYSQL_DATABASE: my_wiki
      MYSQL_USER: wikiuser
      MYSQL_PASSWORD: example
      MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
    volumes:
      - db:/var/lib/mysql

volumes:
  images:
  db:

Si no quieres usar docker-compose

Tienes que montar los contenedores de MariaDB y MediaWiki en la misma red para que puedan comunicarse.

docker network create miwiki
docker run -d \
    --network miwiki \
    --network-alias mariadb \
    -v todo-mysql-data:/var/lib/mysql \
    -e MARIADB_USER=userwiki \
    -e MARIADB_PASSWORD=userwikipwd \
    -e MARIADB_ROOT_PASSWORD=my-secret-pw \
    -e MYSQL_DATABASE=miwiki \
    mariadb:latest
 docker run \
    --network miwiki \
    --name mimediawiki  \
    -p 8080:80 \
    -d mediawiki    

En la instalación de mediawiki tendrás que usar como host de la base de datos mariadb y como usuario userwiki y contraseña userwikipwd (o lo que configures en el entorno de docker)

Una vez instalado, descarga el archivo LocalSettings.php y guárdalo. Para el contenedor de mediawiki y vuélvelo a lanzar añadiendo el volumen con el archivo LocalSettings.php:

docker run \
    --network miwiki \
    --name mimediawiki  \
    -v ./LocalSettings.php:/var/www/html/LocalSettings.php \
    -p 8080:80 \
    -d mediawiki    

10 - Varios

Documentación adicional al curso de DAW

En construcción

10.1 - Integración continua

¿Qué es?

Lee el artículo de wikipedia e investiga sobre el tema.

Aquí tienes un vídeo explicativo sencillo:

¿Cómo podemos implementarlo con GitHub Actions?

Podemos implentar la integración continua y el despliegue continuo con GitHub Actions. Para ello, debemos crear un fichero de configuración en la carpeta .github/workflows de nuestro repositorio.

¿Qué son GH Actions?

La documentación de GH Actions la puedes encontrar en este enlace. Comienza por el inicio rápido y el tutorial.

Seguramente encontrarás ya acciones hechas para lo que necesites en el Marketplace.

Un ejemplo

Aquí tienes un ejemplo para despliegues con Kubernetes. Kubernetes (K8s) es una plataforma de código abierto para automatizar la implementación, el escalado y la administración de aplicaciones en contenedores. No lo hemos utilizado en el curso pero es una tecnología muy interesante.

11 - Repasos, ampliación y más

11.1 - Sesión 18 sept

Revisión de la sesión

Revisión de la sesión

En la sesión del 18 de septiembre hemos visto:

12 - Soluciones a ejercicios

Soluciones a ejercicios del curso.