Podcast: Descargar (40.1MB)
Antes de decir lo que es Docker es casi mejor decir qué hace, que al final es lo que nos interesa.
Docker maneja contenedores aislados que contienen un código determinado. Ese código se independiza de tal forma que hasta permite que el contenedor que lo contiene sea compartido entre diferentes máquinas.
Ahora vamos a lo que no es.
Los contenedores de docker no son máquinas virtuales ya que lo que contiene son piezas de software y no máquinas completas.
Un contenedor de docker es una unidad de software que está autocontenida en el contenedor que contiene todo lo necesario para ejecutar ese código incluyendo código, configuración, procesos, dependencias o red e incluso puede contener la parte del sistema operativo necesaria para ejecutar la aplicación concreta.
Lo primero que necesitamos es instalar docker en nuestro sistema operativo, si es windows o mac tenemos que bajarnos el programa de docker.com y si es linux o bien seguimos las intrucciones de la web de docker o instalamos de los repositorios, de todos modos es bastante sencilla su instalación y no requiere nada en especial.
Una imagen es cualquier fichero que tiene lo suficiente del sistema operativo para hacer lo que necesitamos. Pensad que en una máquina virtual completa instalaríamos todo el sistema operativo, aquí no es necesario con lo que la imagen resultante será más pequeña que una máquina virtual completa.
Para ver las imagenes que tenemos en nuestro sistema, si es que tenemos alguna sería con el comando
docker images
Este comando nos va a dar entre otros valores el repositorio, la etiqueta y el ID de la imagen.
El repositorio es de donde viene la imagen, la etiqueta nos indica la versión, es muy probable que veáis como versión latest, y el ID de imagen es el identificativo interno de Docker.
Para referirnos a una imagen podemos hacerlo con el nombre y la etiqueta, o en caso de no tener tendríamos que hacerlo a través del ID de imagen.
Para ejecutar un contenedor usaremos el comando
docker run -ti repositorio:versión bash
Donde -ti significa terminal interactive
Y si en otra pantalla en paralelo ponéis
docker ps
Podréis ver los contenedores que estáis ejecutando. Es importante cuando lo ejecutéis que os deis cuanta que el ID del contenedor no es el mismo ID que el de la imagen, son números diferentes que no se pisan. Una cosa es la imagen y otra el contenedor.
Ahora bien, si ejecutamos un contenedor y luego lo cerramos todos los cambios que hayamos hechos se perderán, así que tenemos que hacer una copia del contenedor en imagen.
Para convertir un contenedor en imagen mientras el contenedor está activo haremos un
docker commit <id_contenedor> docker tag xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx mi-etiqueta
Al hacer el commit nos creará una imagen con una etiqueta larguísima, así que habrá que renombrarla por algo más fácil de recordar.
Para borrar una imagen
docker image rm etiqueta
En este punto ya sabemos arrancar una instancia, pero necesitamos saber como ejecutar algo en un contendor, que al final esa es la razón para la que utilizar contenedor .
El contendor va a parar cuando termine lo que estamos ejecutando, para ello
docker run imagen proceso
Poniendo un ejemplo añadiendo comandos al bash como parámetro
edu@thinkpad ~ # docker run -ti nginx:latest bash -c "sleep 3; ls -lisa; echo ya termine" total 72 2 4 drwxr-xr-x 33 root root 4096 Apr 21 12:58 . 2 4 drwxr-xr-x 33 root root 4096 Apr 21 12:58 .. 67 0 -rwxr-xr-x 1 root root 0 Apr 21 12:58 .dockerenv 27 4 drwxr-xr-x 2 root root 4096 Oct 20 2016 bin 70 4 drwxr-xr-x 2 root root 4096 Sep 12 2016 boot 2 0 drwxr-xr-x 5 root root 360 Apr 21 12:58 dev 11 4 drwxr-xr-x 58 root root 4096 Apr 21 12:58 etc 73 4 drwxr-xr-x 2 root root 4096 Sep 12 2016 home 31 4 drwxr-xr-x 10 root root 4096 Oct 21 22:31 lib 29 4 drwxr-xr-x 2 root root 4096 Oct 20 2016 lib64 72 4 drwxr-xr-x 2 root root 4096 Oct 20 2016 media 75 4 drwxr-xr-x 2 root root 4096 Oct 20 2016 mnt 74 4 drwxr-xr-x 2 root root 4096 Oct 20 2016 opt 1 0 dr-xr-xr-x 292 root root 0 Apr 21 12:58 proc 71 4 drwx------ 2 root root 4096 Oct 20 2016 root 45 4 drwxr-xr-x 3 root root 4096 Oct 20 2016 run 26 4 drwxr-xr-x 2 root root 4096 Oct 20 2016 sbin 69 4 drwxr-xr-x 2 root root 4096 Oct 20 2016 srv 1 0 dr-xr-xr-x 13 root root 0 Apr 21 12:58 sys 68 4 drwxrwxrwt 2 root root 4096 Oct 21 22:31 tmp 20 4 drwxr-xr-x 15 root root 4096 Oct 21 22:31 usr 43 4 drwxr-xr-x 15 root root 4096 Oct 21 22:31 var ya termine
También podemos dejar los contenedores corriendo en background, lo que en docker se llama dettach container, en este caso el conenedor correrá hasta que se mate o se salga de él (control +q).
Con control + q el contenedor se quedará corriendo en background, para volver a el tendremos que hacer un
docker attach CONTAINER_ID
Aquí me gustaría que tuieráis una cosa en cuenta cuando leyerais mucha de la documentación porque lleva a confusión, para hacer un dettach del contenedor en mucha documentación pone que es con control + p , pero realmente es control + q, al menos en Ubuntu que es donde yo siempre lo he usado para hacer pruebas.
Otra cosa es que cuando vais a hacer un docker attach hay que poner el Container_ID que es el número largo, el primero que os da con un docker ps y no el nombre del contenedor, es una tontería pero os podéis tirar un rato ahí intentando ver por qué no os funciona si no sabéis esto.
Ahora vamos a intentar hacer más de una cosa a la vez en el contenedor. Para ello iniciamos con docker run -ti imagen comado y luego añadiremos la segunda consola con docker exec NAMES comando.
Esto desglosado es de la siguiente manera
edu@thinkpad ~ # docker run -ti nginx:latest bash root@2cc2b836fb2a:/# EN OTRA CONSOLA edu@thinkpad ~ # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2cc2b836fb2a nginx:latest "bash" 35 seconds ago Up 34 seconds 80/tcp, 443/tcp boring_knuth edu@thinkpad ~ # docker exec -ti boring_knuth bash root@2cc2b836fb2a:/#
En este caso hemos utilizado exec para añadir una consola al docker run del principio, para añadir comandos, en este caso hemos añadido también bash.
Si creáis un fichero en una consola lo veréis en la otra obviamente.
Pero claro, cuando ejecutamos algo en docker lo normal no es ejecutar un bash sino algún comando concreto, así que vamos a ejecutar
docker run --name nginx -ti -d nginx:latest bash -c "ouch hola"
Esto nos va a dar error porque el comando ouch no existe, así que lo que haremos será
docker logs nginx
Y nos dirá que el comando no existe:
bash: ouch: command not found
Ojo que le hemos puesto –name para indicar un nombre al contenedor y no hemos dejado que lo bautice directamente docker.
Para borrar un contenedor poder hacer
docker kill nombre
y luego
docker rm nombre
El primero matará el contenedor y el segundo borrará logs y demás, porque si queremos usar el mismo nombre nos dirá que ese contenedor ya existe, aunque no sea así y eso es porque no hemos hecho el rm del mismo.
Por defecto los contenedores pueden usar toda la memoria que tenga el sistema disponible, sin limitación, y claro, no es lo más óptimo, o al menos no es lo ideal.
Podemos limitar la cantidad de memoria asignada a un contenedor de forma similar a como lo haríamos en otro tipo de paravirtualiación como por ejemplo LXC.
Para limitar la memoria usaremos el comando:
docker run --memory 200m -ti nginx:latest bash
En este caso hemos limitado a 200 megas la imagen nginx:latest
Para ver que realmente hemos limitado en otra consola pondremos
docker stats infallible_bell CONTAINER CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS infallible_bell 0.00% 504KiB / 200MiB 0.25% 6.41kB / 0B 0B / 0B 1
Por supuesto también podemos limitar la CPU, y aquí docker nos ofrece dos posibilidades:
- Limitar de forma relativa
- Limitar de forma absoluta
Limitar de forma relativa significa limitar de forma relativa a otros contenedores y absoluta es en función de la CPU del sistema.
Si usamos la forma relativa
docker run --memory 200m --cpu-shares 1024 -ti nginx:latest bash
En este caso le hemos dado 1024 acciones (shares) y si tenemos otra máquina con otros 1024 tendrá el 50% de la capacidad, si hubiera 10 todas iguales un 10%, pero si estuvuera con otra que tuviera 2048 entonces tendría un 33%, es decir, depende del total en el sistema, esto es útil para un laboratorio o cosas así.
Para calcular la CPU que se puede utilizar de forma absoluta lo hacemos teniendo en cuenta ciclos de reloj, indicando la quota y el periodo por core, si indicamos que el periodo es 50.000 entonces 25.000 es medio core y hablaríamos del 50% de la CPU, si hubiera 4 cores sería el 12,5% de la CPU, pero el comando el mismo, es decir, es dependiente del hardware.
docker run -it --cpu-period=50000 --cpu-quota=25000 nginx:latest /bin/bash
Vamos a pasar a hablar de la red en docker. Lo primero que tenemos que saber es que Docker tiene su propia red privada dentro del host, realmente se puede dividir esa red en varias de forma no demasiado complicada.
Obviamente podemos asignar contenedores a las redes que queramos dentro del host.
Una de sus funcionalidades, quizás de las más usadas es conectar un puerto externo a uno de docker
docker run --rm -ti -p 8080:8080 -p 8081:8081 --name ubuntu ubuntu:latest bash
Y este chorizo significa ejecuta docker, luego borralo, muy recomendable hacer eso siempre para que no se quede porquería, con terminal interactiva y me mapear el puerto 8080 externo al del contendor 8080, igual con el 8081, llamas al contenedor ubuntu y lo haces a partir de la versión latest de la imagen ubuntu y ejecutas el proceso bash.
Llegados a este punto ya podemos instalar alguna imagen de docker, vamos a empezar con una que seguro que a Ángel de uGeek le hace mucha ilusión, un nextcloud, lo comento porque Ángel es un gran experto en nextcloud y un gran admirador de esta plataforma.
Lo primero será buscar un contenedor de nextcloud, vosotros pensar que casi cualquier cosa que se os ocurra ya existe, lo haremos con el comando docker search
edu@thinkpad ~ # docker search nextcloud NAME DESCRIPTION STARS OFFICIAL AUTOMATED wonderfall/nextcloud Nextcloud - a safe home for all your data.... 179 [OK] nextcloud A safe home for all your data 73 [OK] greyltc/nextcloud Nextcloud: a safe home for all your data. ... 29 [OK] rootlogin/nextcloud Nextcloud docker image running on top of N... 10 [OK] indiehosters/nextcloud Docker image for Nextcloud application. 9 [OK] sameersbn/nextcloud Dockerized Nextcloud 3 [OK] freenas/nextcloud Access & share your files, calendars, cont... 3 [OK] aheimsbakk/nextcloud Nextcloud - a safe home for all your data.... 2 [OK] skybosh/nextcloud A simple Nextcloud image. 2 [OK] jremy/nextcloud A docker image for Nextcloud, compatible w... 1 [OK] cyphar/nextcloud NextCloud is a fork of OwnCloud. This is a... 1 [OK]
Vamos a instalar nextcloud directamente, no es la que tiene más votos, pero vamos a probar esa misma.
Procedemos a instalar con docker pull
edu@thinkpad ~ # docker pull nextcloud Using default tag: latest latest: Pulling from library/nextcloud 6d827a3ef358: Pull complete 87fe8fbc743a: Pull complete f6d1a8d304ab: Pull complete caf3547d9b73: Pull complete 1004db2760ff: Pull complete 66e2d66a547e: Pull complete bbfaa62c234a: Pull complete 19ce8807f4d1: Pull complete ccf3ec7b3529: Pull complete 7b0fb921474a: Pull complete 8cde875cb7f5: Pull complete 2e8b672a5081: Pull complete c1b547802173: Pull complete 688c5e582e3a: Pull complete 41307daccaf3: Pull complete c6f9b9f60c06: Pull complete b9bfa2b24ad2: Pull complete 8d965230aa8e: Pull complete 9c528fa83dc0: Pull complete a340a28467ca: Pull complete Digest: sha256:087fb214ab4aac1754fee23c75662902c8b0f0707bebd29368c455b386f3483f Status: Downloaded newer image for nextcloud:latest
Y ahora arrancamos el contenedor en el puerto 80 y el 443
docker run --name nc -p 80:80 -p 443:443 -d nextcloud
Y en este caso al abrir la web entráis como admin/admin
De todos modos todos y cada uno de estos contenedores tienen la documentación en hub.docker.com, así que entráis ahí y podréis verlo.