Despliegue de aplicaciones: Contenedores y Máquinas virtuales 23-24
Contenido
Prerequisitos
Instalar Docker-Compose
1 #Para asegurar que tengamos la versión más actualizada y estable de Docker Compose, nos la traeremos desde su repositorio de GitHub oficial
2
3 mkdir -p ~/.docker/cli-plugins/
4 curl -SL https://github.com/docker/compose/releases/download/v2.3.3/docker-compose-linux-x86_64 -o ~/.docker/cli-plugins/docker-compose
5
6 #Otorgamos permisos para que el comando docker compose sea ejecutable
7 chmod +x ~/.docker/cli-plugins/docker-compose
8
9 #Para verificar que la instalación fue existosa, ejecutamos:
10 docker compose version
Docker
Creado una imagen para una app Flask en python
- Todo el código fuente está disponible en : https://github.com/EGCETSII/1920-Practica-1
Comenzamos creando nuestra app en el arcvhivo holamundo.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello World'
@app.route('/hello/<name>')
def hello_name(name):
return 'Hello %s!' % name
if __name__ == '__main__':
app.run(host="0.0.0.0")
Definimos las dependencias en el archivo requirements.txt
Flask
Podemos usar la imagen de python3 existente en los repositorios de docker, y modificarla anadiendo la aplicacion que hemos desarrollado
Para ello podemos crear un fichero Dockerfile que nos automatiza la creacion de una imagen modificada:
# Base image
FROM python:3
#copy the requirements txt file with all our dependencies
COPY requirements.txt ./
#install the dependencies
RUN pip install --no-cache-dir -r requirements.txt
#copy the app in the image
COPY holamundo.py ./
#define a default command to execute
CMD [ "python", "./holamundo.py" ]
Este fichero indica que docker tiene que descargar la imagen python en su tercera versión y tiene que añadir el fichero requirements a la carpeta de usuario de la imagen.
Docker nos ofrece un lenguaje de scripting para automatizar la creacion de imagenes.
docker build -t holamundoflask -f Containerfile .
Va a crear la imagen, tras esto podemos lanzar:
docker run -p 8020:80 holamundo-flask
Tras esto, desde un navegador, abrimos la URI: http://localhost:8020/hello/"yourname"
Ejecutando decide en docker-compose
Para ejecutar decide en docker, primero nos situaremos en el directorio docker del repositorio de decide.
Una vez situados en ese directorio, ejecutaremos
docker compose up
Pero antes, deberemos hacer algunos cambios para adaptar la configuración que tenemos a la nueva versión de decide:
- En el docker-compose.yml, hay que actualizar la versión de postgres:19.9-alpine y, también, darle una contraseña al usuario de postgres:
version: '3.4'
services:
db:
restart: always
container_name: decide_db
image: postgres:14.9-alpine
volumes:
- db:/var/lib/postgresql/data
networks:
- decide
environment:
- POSTGRES_PASSWORD=postgres
....
- En el Dockerfile que define la imagen decide_web, hay que actualizar la versión de python a la 3.10 y, también, la URL del repositorio remoto que se clonará para levantar el sistema:
from python:3.10-alpine
RUN apk add --no-cache git postgresql-dev gcc libc-dev
RUN apk add --no-cache gcc g++ make libffi-dev python3-dev build-base
RUN pip install gunicorn
RUN pip install psycopg2
RUN pip install ipdb
RUN pip install ipython
WORKDIR /app
RUN git clone <<URL al repo>> .
RUN pip install -r requirements.txt
WORKDIR /app/decide
# local settings.py
ADD docker-settings.py /app/decide/local_settings.py
RUN ./manage.py collectstatic
- Debemos asegurar que el repositorio remoto tiene el requirements.txt actualizado con los cambios que hemos realizado en las prácticas previas:
Django==4.1
pycryptodome==3.15.0
djangorestframework==3.14.0
django-cors-headers==3.13.0
requests==2.28.1
django-filter==22.1
psycopg2==2.9.4
coverage==6.5.0
jsonnet==0.18.0
django-nose==1.4.6
django-rest-swagger==2.2.0
selenium==4.7.2
pynose == 1.4.8
- Para evitar problemas del tipo "CSRF Trusted", hay que añadir al docker_settings.py permisos:
DEBUG = True
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'postgres',
'USER': 'postgres',
'PASSWORD':'postgres',
'HOST': 'db',
'PORT': 5432,
}
}
STATIC_ROOT = '/app/static/'
MEDIA_ROOT = '/app/static/media/'
ALLOWED_HOSTS = ['*']
CSRF_TRUSTED_ORIGINS = ['http://10.5.0.1:8000', 'http://localhost:8000']
.....
Vagrant
Encapsulado y aprovisionamiento de una app en Vagrant
Creamos un Vagrantfile, podeis ver el código aquí https://github.com/EGCETSII/1920-Practica-1
1 Vagrant.configure("2") do |config|
2 config.vm.box = "ubuntu/bionic64"
3 config.vm.network "forwarded_port", guest: 80, host: 8080
4 config.vm.provision "shell", path: 'provision.sh'
5 end
Creamos nuestra forma de aprovisionar (de momento con un script bash)
1 sudo apt update
2 sudo apt upgrade -y
3 sudo apt install -y git python3 python3-pip screen
4 git clone https://github.com/EGCETSII/1920-Practica-1.git
5 cd 1920-Practica-1
6 pip3 install -r requirements.txt
7 screen -m -d python3 holamundo.py
Levantamos nuestra máquina
vagrant up
Accedemos a localhost:8080
- ¿Qué esta pasando?
- ¿Cómo podemos cambiar el puerto en el que se despliegue la máquina, por ejemplo, al 8081?
- ¿Qué ocurriría si cambiáramos el box base a uno que no soportase "apt"?
Despliegue de decide en Vagrant
Para ejecutar decide en vagrant, primero nos situaremos en el directorio vagrant del repositorio de decide.
Una vez situados en ese directorio, ejecutaremos
vagrant up
Observamos que pasa en la consola.
Pero antes de que todo funcione correctamente, al igual que ocurrió en docker-compose, necesitaremos actualizar algunos aspectos de la configuración para la nueva versión de decide:
- Actualizar el Vagrantfile para que utilice más CPU y más RAM. Del mismo modo, debemos actualizar la versión de la box de ubuntu desde la que partimos, para evitar problemas de incompatibilidad con la versión de python y django que usamos:
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/jammy64"
config.vm.network "forwarded_port", guest: 80, host: 8080
config.vm.provider "virtualbox" do |v|
v.memory = 2048
v.cpus = 3
end
......
- En el fichero python.yml habrá que sustituir la URL del repositorio remoto que se clonará y se utilizará para levantar decide por la URL de nuestro repositorio
- La versión de ubuntu que estamos usando retira unos permisos que ansible necesita para poder generar ficheros temporales. Para solucionar esta cuestión, necesitaremos añadir al fichero packages.yml la dependencia -acl:
- name: Install packages
become: true
apt:
name: "{{ packages }}"
update_cache: yes
vars:
packages:
- acl
- git
- postgresql
- python3
- python3-pip
- python3-psycopg2
- python3-virtualenv
- virtualenv
- nginx
- libpq-dev
- python-setuptools
- build-essential
- python3-dev
- make
- m4
- Igual que ocurrió en docker-compose, para evitar problemas de "CSRF Trusted", añadiremos a vagrant/files/settings.py lo siguiente:
....
STATIC_ROOT = '/home/decide/static/'
MEDIA_ROOT = '/home/decide/static/media/'
ALLOWED_HOSTS = ['*']
ALLOWED_ORIGINS = ['http://*', 'https://*', 'https://localhost:8080', 'http://localhost:8080']
CSRF_COOKIE_SECURE = True
CSRF_COOKIE_SAMESITE = 'Strict'
CSRF_TRUSTED_ORIGINS = ALLOWED_ORIGINS.copy()
....
- Para tener acceso a los estáticos generados mediante collectstatic, es necesario otorgarle permisos de lectura a todo el directorio. Para ello, en django.yml añadiremos lo siguiente:
....
- name: Change permissions on decide (Make static directory tree readable)
become: yes
file:
path: /home/decide
owner: "decide"
recurse: yes
group: decide
mode: "555"
Con todo ello, si levantamos la máquina virtual y accedemos a localhost:8080, accederemos a decide.