2. Docker
Docker es una herramienta que puede empaquetar una aplicación y sus
dependencias en un contenedor virtual que se puede ejecutar en cualquier
servidor Linux. Esto ayuda a permitir la flexibilidad y portabilidad en donde la
aplicación se puede ejecutar, ya sea en las instalaciones físicas, la nube pública,
nube privada, etc
https://es.wikipedia.org/wiki/Docker_(software)
3. VirtualVox
Oracle VM VirtualBox es un software de virtualización para arquitecturas
x86/amd64, creado originalmente por la empresa alemana innotek GmbH.
Actualmente es desarrollado por Oracle Corporation como parte de su familia de
productos de virtualización. Por medio de esta aplicación es posible instalar
sistemas operativos adicionales, conocidos como «sistemas invitados», dentro de
otro sistema operativo «anfitrión», cada uno con su propio ambiente virtual.
https://es.wikipedia.org/wiki/VirtualBox
4. Vagrant
Vagrant es una herramienta para la creación y configuración de entornos de
desarrollo virtualizados.1 Originalmente se desarrolló para VirtualBox y sistemas
de configuración tales como Chef, Salt y Puppet. Sin embargo desde la versión
1.1 Vagrant es capaz de trabajar con múltiples proveedores, como VMware,
Amazon EC2, LXC, DigitalOcean, etc.2 Aunque Vagrant se ha desarrollado en
Ruby se puede usar en multitud de proyectos escritos en otros lenguajes, tales
como PHP, Python, Java, C# y JavaScript
https://es.wikipedia.org/wiki/Vagrant_(software)
7. Vagrant - Primeros pasos
crear una carpeta y acceder a ella
# mkdir vagrant_test
# cd vagrant_test
inicializar un fichero Vagrantfile
# vagrant init ubuntu/trusty64
editar el fichero (o no) para ajustar la configuración
# nano Vagrantfile
9. Vagrant - Primeros pasos
Editando Vagrantfile
config.vm.box: indica la “box” que se utiliza como “plantilla” para crear y levantar
la máquina virtual.
config.vm.box_url: indica la url del repositorio donde se buscarán las diferentes
“boxes” y sus versiones, si no se indica este parámetro, por defecto, apunta al
repositorio público de https://atlas.hashicorp.com/boxes/search (más adelante se
indica como crear un repositorio privado, con lo cual este parámetro toma sentido)
10. Vagrant - Primeros pasos
config.vm.synced_folder: ej (config.vm.synced_folder "src/", "/srv/website")
indica carpetas a compartir (Synced folders) entre la máquina anfitrión y la
máquina virtual, esto por ejemplo nos da la posibilidad de tener el código fuente
de nuestra aplicación en la máquina real, editarlo desde nuestro IDE de elección y
automáticamente estará disponible para ejecutarse en la máquina virtual. Por
defecto la carpeta desde la que lanzamos nuestra máquina virtual, es decir donde
se encuentra nuestro Vagrantfile es compartida automáticamente y montada en
nuestra máquina virtual en la carpeta /vagrant.
11. Vagrant - Primeros pasos
config.vm.network: Esta opción nos permite configurar todo lo relacionado con el
networking de nuestra máquina virtual, tal vez el formato que más nos interese
sea (config.vm.network "forwarded_port", guest: 80, host: 8080) que
redireccionaría el puerto 80 de la máquina virtual al 8080 de la máquina anfitrion
dandonos acceso desde nuestro navegador en la forma de http://127.0.0.1:8080
La documentación oficial la encontraremos en https://www.vagrantup.com/docs/
donde tenemos tanto información de los comandos como de las opciones de
configuración.
12. Vagrant - Primeros pasos
Vagrant nos permite configurar muchas más cosas, como puede ser software a
instalar, ficheros de configuración a copiar, etc. esto se hace desde las secciones
de provisioning (config.vm.provision) en el fichero Vagrantfile que nos creó por
defecto podemos ver:
13. Vagrant - Primeros pasos
otro ejemplo puede ser esta configuración que hemos añadido para la instalación
de docker.
El aprovisionador de docker se encarga de instalar el software necesario para
docker y después ejecuta las instrucciones que le indiquemos en este caso la
descarga de 2 imágenes y la compilación de una imagen personalizada que se
encuentra en nuestro “Synced folder”
14. Vagrant - Primeros pasos
En el caso de definir o redefinir uno o más “provisioner” sera necesario ejecutar:
# vagrant provision
# vagrant up
o
# vagrant up --provision
Para acceder a nuestra máquina virtual una vez levantada
# vagrant ssh
15. Vagrant - Primeros pasos
Para forzar el apagado de una máquina virtual usaremos:
# vagrant halt
que realizará un shutdown completo de la máquina o si preferimos:
# vagrant suspend
que pondrá la máquina en estado de hibernación y se iniciará más rápido con:
# vagrant resume
16. Vagrant - Para el señor de sistemas
Como se ha comentado antes, todas las “boxes” se descargan por defecto del
repositorio Atlas de HashiCorp, pero, si queremos tener un/unos “box/es
personalizado/s” y estar preparado para una instalación rápida de nuestras
máquinas necesitamos un repositorio propio donde poder publicar estos boxes y
poder versionalos para adaptarlos a los nuevos requerimientos (nuevos módulos
de php, otras configuraciones de virtualhost, etc). En el siguiente enlace tenemos
un manual paso a paso de como crear nuestrar propias “boxes”, como
versionarlas y como crear un repositorio para almacenarlas.
https://github.com/hollodotme/Helpers/blob/master/Tutorials/vagrant/self-hosted-
vagrant-boxes-with-versioning.md
17. Docker - Conceptos básicos
Imagen: Fichero físico que contiene el sistema operativo básico y el servicio o
servios implementados y preconfigurados.
Container: instancia de una imagen
Registro: servicio que almacena imágenes Dockerizadas de forma pública o
privada.
Docker Engine: Hasta la versión 1.10 estaba formado básicamente por un fichero
“docker” que hacia tanto las veces de demonio (servicio) y herramienta cliente, a
partir de la versión 1.11 este está compuesto por docker y docker-containerd
18. Docker - Primeros pasos
La instalación de Docker es bastante sencilla, si se utiliza una máquina virtual
como hemos indicado antes, añadiendo en la configuración el provisioner de
docker ya lo tenemos todo hecho, si lo queremos instalar en una distro
debian/ubuntu esto son los pasos a seguir.
Asegurarse de tener device-mapper instalado
# ls -al /sys/class/misc/device-mapper
o
# sudo grep device-mapper /proc/devices
19. Docker - Primeros pasos
si no lo encontramos con ninguna de las dos opciones anteriores provad con
# sudo modprobe dm_mod
Ahora toca revisar que repositorio usar con vuestra distribución linux, copiar la
siguiente url en vuestro navegador:
https://apt.dockerproject.org/repo/dists/
del listado, tomar nota del nombre de distro que os interesa
21. Docker - Primeros pasos
Ejecutar los siguientes comandos cambiando xxx por el nombre de vuestra distro
ejemplo debian-jessie
# sudo sh -c "echo deb https://apt.dockerproject.org/repo xxx main >
/etc/apt/sources.list.d/docker.list"
# sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys
58118E89F3A912897C070ADBF76221572C52609D
# sudo apt-get update
# sudo apt-get install docker-engine
22. Docker - Primeros pasos
Si todo ha ido bien comprobaremos
la instalación con:
# sudo docker info
23. Docker - Primeros pasos
# sudo docker run -it ubuntu /bin/bash
Descarga la imagen de ubuntu y la ejecuta el parámetro -i indica que el container
en ejecución mantenga STDIN abierto y -t que cree un pseudo terminal, por último
/bin/bash es el comando que se ejecutará dentro del container una vez levantado.
Hay que tener en cuenta que docker finaliza la ejecución de un container una vez
que el comando inicial termina, eso quiere decir que una vez que ejecutemos exit
para salir de la sesión bash tambien terminará la ejecución del container ubuntu.
24. Docker - Primeros pasos
# hostname
# cat /etc/hosts
# ps -aux
# apt-get update && apt-get install -qy mc
# exit
# docker ps
Nos mostrará los container en ejecución
25. Docker - Primeros pasos
# docker ps -a
Nos mostrará todos los containers existentes
# docker ps -l
Nos mostrará el último container ejecutado
# docker run --name ubuntu_test -it ubuntu /bin/bash
Creará un nuevo container, pero esta vez le asignará un nombre conocido
26. Docker - Primeros pasos
# docker run --name ubuntu_test -it ubuntu /bin/bash
Este comando fallará pues ya existe un container llamado ubuntu_test, en vez de
esto usaremos
# docker start ubuntu_test
Esto levantará el container con los mismos parámetros que en la última ejecución,
pero no nos conectaremos directamente a el.
# docker ps
27. Docker - Primeros pasos
para volver a conectarnos al terminal de nuestro container en ejecución:
# docker attach ubuntu_test
# docker run --name ubuntu_daemon -d ubuntu /bin/sh -c "while true; do echo
hello world; sleep 1; done"
El parámetro -d hace que nuestro container ejecute el comando como un demonio
por lo que no veremos nada en pantalla, para ver información sobre la actividad
de nuestro container
28. Docker - Primeros pasos
# docker logs ubuntu_daemon
# docker logs -f ubuntu_daemon
# docker logs -f --tail 0 ubuntu_daemon
“logs” muestra la actividad en los logs del container, -f obliga a quedarse
mostrando los nuevos mensajes de log, --tail 0 indica que no muestre mensajes
anteriores.
para ver los procesos en ejecución dentro de nuestro container
# docker top ubuntu_daemon
29. Docker - Primeros pasos
y para tener infomación más detallada del uso de recursos
# docker stats
ejecutar un comando no interactivo en un container en ejecución
# docker exec -d ubuntu_daemon touch /etc/aaaa
ejecutar un comando interactivo en un container en ejecución
# docker exec -it ubuntu_daemon /bin/bash
30. Docker - Primeros pasos
Parar la ejecución de un container
# docker stop ubuntu_daemon
Para ver más información sobre un container parado o en ejecución
# docker inspect ubuntu_daemon
Para inspeccionar un valor más concreto (muy util en scripts de automatización)
# docker inspect --format="{{ .State.Running }}" ubuntu_test
31. Docker - Primeros pasos
Multiples configuraciones en multiples containers
# docker inspect -f="{{ .Name }} {{ .State.Running }}" ubuntu_test ubuntu_daemon
# docker inspect -f="{{ .Name }} {{ .State.Running }}" `docker ps -a -q`
Eliminar un container
# docker rm ubuntu_test
Ver la imagenes descargadas en nuestro sistema (/var/lib/docker)
# docker images
32. Docker - Primeros pasos
Hemos visto como levantar un container a partir de una image (ubuntu) pero
tenemos muchas más imágenes disponibles
https://hub.docker.com/explore/
Este es el repositorio oficial de Docker, en él encontraremos imágenes
preparadas para funcionar y toda una serie de explicaciones de cómo
configurarlas a nuestra medida.
# docker search nginx
33. Docker - Primeros pasos
Si hemos creado una cuenta en Docker Hub, podemos logearnos con ella para
poder compartir nuestras nuevas imágenes subiendalos al repositorio
# docker login
la configuración se guardará en ~/.docker/config.json
34. Docker - Personalizando imágenes
Primero cambiaremos a la carpeta donde tendremos nuestro repositorio local en
este caso /vagrant/docker
# cd /vagrant/docker
creamos una carpeta para nuestra nueva imagen
# mkdir staticserver && cd staticserver
y creamos un Dockerfile
# touch Dockerfile
35. Docker - Personalizando imágenes
# nano Dockerfile
FROM ubuntu:14.04
MAINTAINER Sergio Zambrano Delfa <sergio.zambrano@gmail.com>
ENV REFRESHED_AT 2016-05-25T23:30
RUN apt-get update && apt-get install -y nginx
RUN echo “Hola, mi primera imagen” > /usr/share/nginx/html/index.html
EXPOSE 80
# docker build -t="szambrano/static_web" .
# docker images
36. Docker - Personalizando imágenes
Podemos comprobar que se ha creado nuestra imagen y que la versión de
nuestra compilación es “latest”, es aconsejable indicar una versión siempre que
sea posible así que borraremos la imagen y crearemos nuestra versión 1.0.0
# docker rmi szambrano/static_web
# docker build -t="szambrano/static_web:1.0.0" .
# docker images
# docker run -d -p 80:80 --name staticserver szambrano/static_web:1.0.0 nginx -g
"daemon off;"
37. Docker - Personalizando imágenes
# docker ps
“run” lanza el contaniner, “-d” en modo daemon, “-p 80:80” enlaza el puerto 80 del
container con el puerto 80 de nuestra máquina, “--name staticserver” ponemos
nombre al container, “szambrano/static_web:1.0.0” imagen base desde la que
creamos nuestro container, ‘nginx -g "daemon off;’” comando que lanzamos en
nuestro container, ¿porque “daemon off”? tenemos que ejecutar el demonio en
modo standalone, pues si lo ejecutasemos “daemonized” liberaria la consola
terminado la ejecución de nuestro container.
38. Docker - Personalizando imágenes
# curl 127.0.0.1
Ya podemos acceder a nuestro servidor, pero solo podemos hacerlo desde la
máquina virtual, lo cual es un problema. La solución es sencilla, paramos nuestro
container, salimos de la máquina virtual y la paramos, editamos Vagrantfile
# docker stop staticserver
# exit
# exit
39. Docker - Personalizando imágenes
# vagrant halt
# nano Vagrantfile
buscamos config.vm.network “forwarded_port”
lo descomentamos y si es necesario cambiamos los puertos, si necesitasemos
redireccionar más puertos simplemente copiariamos esta línea tantas veces
40. Docker - Personalizando imágenes
como puertos debamos abrir y los configuramos, en nuestro caso nos basta con
Lo óptimo sería “guest: 80, host: 80” para que desde nuestra máquina real
podamos acceder al puerto estándar, pero en mi caso tengo apache instalado por
lo tanto el puerto 80 ya está ocupado. Reiniciamos la máquina virtual, reiniciamos
nuestro container y testeamos.
41. Docker - Personalizando imágenes
# vagrant up
# vagrant shh
# cd /vagrant/docker/
# docker start staticserver
42. Docker - Personalizando imágenes
Tenemos montones de opciones para personalizar nuestro Dockerfile, esta es la
documentación oficial https://docs.docker.com/engine/reference/builder/ algunas
de ellas las veremos a continuación.
CMD [“command”, “paremeter0”, “parametern”]
comando a ejecutar, esto nos permite no tener que especificar el comando en la
línea de comandos.
# docker stop staticserver
# nano Dockerfile
43. Docker - Personalizando imágenes
FROM ubuntu:14.04
MAINTAINER Sergio Zambrano Delfa <sergio.zambrano@gmail.com>
ENV REFRESHED_AT 2016-05-26T10:39
RUN apt-get update && apt-get install -y nginx
RUN echo "Hola, mi primera imagen" > /usr/share/nginx/html/index.html
CMD ["/usr/sbin/nginx", "-g", "daemon off;"]
EXPOSE 80
# docker rm staticserver
45. Docker - Personalizando imágenes
Si realizamos la misma operacion sustituyendo
CMD ["/usr/sbin/nginx", "-g", "daemon off;"]
por
ENTRYPOINT ["/usr/sbin/nginx", "-g", "daemon off;"]
Obtendremos el mismo resultado, la diferencia es que si al ejecutar el container
añadimos un comando este sustituirá al CMD, sin embargo ENTRYPOINT no se
verá afectado.
46. Docker - Personalizando imágenes
Otras opciones interesantes son:
WORKDIR: con esta le indicaremos desde qué directorio se ejecutarán las
siguientes instrucciones RUN y CMD
USER: para indicar el usuario o usuario:grupo con el que se ejecutarán las
siguientes instrucciones RUN y CMD o ENTRYPOINT
ENV: Define variables de entorno que se pueden usar a lo largo de todo el
Dockerfile, “ENV carpeta /var/www” y despues RUN $carpeta/app/console cache:
clear por ejemplo
47. Docker - Personalizando imágenes
VOLUME: En este caso nos permite crear un volumen compartido entre todas los
containers creador a partir de una imagen, un container no tiene porqué estar
levantado para compartir sus volúmenes, los cambios en el volumen son
compartidos automáticamente por todas las instancias, los cambios en el volumen
no incluidos al actualizar una imagen, los cambios son persistidos incluso si el
container no usa el volumen.
49. Docker - Personalizando imágenes
# docker build -t="szambrano/dinamic_web:1.0.0" .
# docker run -v /vagrant/dinamic_web_source/:/usr/share/nginx/html/ -d -p 80:80 --
name dinamicserver szambrano/dinamic_web:1.0.0
Ahora ya podemos poner nuestros sources en la carpeta
“/var/www/vagrant_test/dinamic_web_source/”
50. Docker - Personalizando imágenes
al levantar la máquina virtual con “vagrant up” la carpeta “/var/www/vagrant_test”
queda compartida con la máquina virtual en la capeta “/vagrant” y
“/vagrant/dinamic_web_source” queda compartida con los containers que parten
de la imagen “szambrano/dinamic_web:1.0.0” en su carpeta interna
“/usr/share/nginx/html/”
COPY: sirve para copiar ficheros desde nuestro sistema de archivos al
contenedor ejemplo: COPY index.html /usr/share/nginx/html/
ADD: sirve para copiar ficheros desde nuestro sistema de archivos al contenedor
ejemplo: ADD index.html /usr/share/nginx/html/
51. Docker - Personalizando imágenes
La diferencia de COPY y ADD es que ADD descomprimirá el fichero de origen en
caso de ser un TAR, BZ2, ZIP y alguno más.
52. Docker - Personalizando imágenes
Conectar varios containers entre si
# cd /vagrant/docker && mkdir redis && cd redis
# nano Dockerfile
FROM ubuntu:14.04
MAINTAINER Sergio Zambrano Delfa "sergio.zambrano@gmail.com"
ENV REFRESHED_AT 2016-05-26T12:25
RUN apt-get -yq update && apt-get install -yq redis-server redis-tools
EXPOSE 6379
ENTRYPOINT ["/usr/bin/redis-server"]
CMD []
61. Links de interés
Generador de Vagranfile
https://puphpet.com/
Snapshot para Vagrant
http://www.fernandoaparicio.net/snapshot-con-vagrant/
Guia rápida de Vagrant
http://www.fernandoaparicio.net/uso-de-vagrant-para-desarrolladores/
62. Agradecimientos
A Yaencontre por la confianza depositada para impartir la Masterclass de Vagrant
y Docker para la cual se creó esta guía/manual el 26/05/2016.
A Fernando Aparicio por sus aportes, consejos, paciencia y apoyo en la redacción
del documento.
A los asistentes a la Masterclass, que a pesar de la hora y el calor aguantaron
estoicamente y algunos hasta me felicitaron.
A la comunidad Open Source, por casi todo.