El otro día vimos como instalar un cluster de docker con swarm. Mas adelante veremos como se monta un cluster de Docker con Kubernettes. Tanto Swarm como Kubernettes son orquestadores de docker y para entender como funcionan antes debemos entender como usar Docker a pelo.
Docker puede funcionar perfectamente en una sola máquina y no es necesario montar un cluster, para tenerlo a mano, pego en modo resumen la parte de instalación de docker del anterior post (instalación en Debian):
root@docker-master:~# apt update && apt -y upgrade && apt -y dist-upgrade root@docker-master:~# apt-get remove docker docker-engine docker.io containerd runc root@docker-master:~# apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common root@docker-master:~# curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - root@docker-master:~# apt-key fingerprint 0EBFCD88 root@docker-master:~# add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable" root@docker-master:~# apt update root@docker-master:~# apt-get install docker-ce docker-ce-cli containerd.io
Una vez instalado Docker, voy a explicar de que va ésto.
Docker es un software de virtualización. La virtualización nace en AIX, el sistema operativo de los mainframes de IBM. La virtualización nace de la necesidad de correr otros sistemas operativos dentro de un sistema operativo. A lo largo de los años y a medida que los servidores y ordenadores de sobremesa han sido mas potentes, han ido apareciendo muchos programas y métodos de virtualización.
Por un lado tenemos los sistemas de virtualización de un sistema operativo entero como podrían ser VirtualBox, VMWare, KVM, Xen, etc. y mas adelante salieron otros sistemas que compartían el núcleo del sistema operativo (kernel) con el host.
Con Docker, tenemos una siguiente evolución, la “virtualización por capas”. Cuando en una máquina virtual con KVM o con LXC tenemos que instalar aplicaciones, en Docker añadimos éstas aplicaciones en capas. Cuando desplegamos un contenedor de docker, las aplicaciones ya están preparadas y desplegadas para su funcionamiento, cosa que ahorra mucho tiempo de instalación y de resolución de fallos, ya que el fabricante, desarrollador o empaquetador nos ha preparado el entorno para que al arrancar el contenedor ya esté la aplicación lista para su uso. La buena práctica de Docker es destinar un servicio por contenedor (microservicios), por ejemplo en un wordpress, un contenedor para la base de datos y otro para el servidor web con los ficheros de la instalación de wordpress.
Mi infraestructura actual se basa en clústers de proxmox corriendo contenedores LXC y máquinas virtuales KVM. En las máquinas virtuales KVM cuando queremos instalar un sistema operativo lo haríamos tal como lo haríamos con un ordenador normal y corriente (iso y seguir los pasos de instalación). En LXC disponemos de unos templates que nos descargamos y luego desplegamos, éstos templates contienen sistemas operativos ya preparados para su uso y sólo tenemos que instalar las aplicaciones que necesitemos. Hay algunos templates ya vienen preparados con aplicaciones. Con LXC nos ahorramos el paso de la instalación pero no nos ahorramos el paso de la configuración. Docker pretende ahorrarnos también el paso de la configuración y permitir así despliegues aún más ágiles.
¿Cómo funciona Docker?
Básicamente nos descargamos una imagen “precocinada” del repositorio de Docker DockerHub y la desplegamos en nuestra máquina.
A continuación vemos un conjunto de comandos que debemos aprender si queremos trabajar con Docker. En algunos manuales que he leído para entender docker el orden de los comandos que se enseñan es otro y personalmente me llevaba a cierta confusión, así que aquí propongo la mía :P
Primero de todo mencionar que todos los ficheros que se generen con Docker van a ir almacenados a /var/lib/docker
root@docker-master:~# ls /var/lib/docker/ builder containers network plugins swarm trust buildkit image overlay2 runtimes tmp volumes
Buscar imagenes en el repositorio de dockerhub
root@docker-master:~# docker search debian NAME DESCRIPTION STARS OFFICIAL AUTOMATED ubuntu Ubuntu is a Debian-based Linux operating sys… 11483 [OK] debian Debian is a Linux distribution that's compos… 3644 [OK] arm32v7/debian Debian is a Linux distribution that's compos… 66 itscaro/debian-ssh debian:jessie 28 [OK] arm64v8/debian Debian is a Linux distribution that's compos… 23 samueldebruyn/debian-git a minimal docker container with debian and g… 22 [OK] multiarch/debian-debootstrap multiarch ports of debian-debootstrap 13 i386/debian Debian is a Linux distribution that's compos… 11 eboraas/debian Debian base images, for all currently-availa… 8 [OK] vergissberlin/debian-development Docker debian image to use for development, … 6 [OK] smartentry/debian debian with smartentry 5 [OK] amd64/debian Debian is a Linux distribution that's compos… 4 ppc64le/debian Debian is a Linux distribution that's compos… 4 vicamo/debian Debian docker images for all versions/archit… 3 arm32v5/debian Debian is a Linux distribution that's compos… 2 vpgrp/debian Docker images of Debian. 2 s390x/debian Debian is a Linux distribution that's compos… 2 spritsail/debian-builder A Docker image based on debian:slim ideal fo… 1 [OK] dockershelf/debian Repository for docker images of Debian. Test… 1 [OK] holgerimbery/debian debian multiarch docker base image 1 fleshgrinder/debian Debian base images for production and multis… 0 [OK] jdub/debian-sources-resource Concourse CI resource to check for updated D… 0 [OK] 1and1internet/debian-9-nginx-php-7.2-wordpress-4 debian-9-nginx-php-7.2-wordpress-4 0 [OK] casept/debian-amd64 A debian image built from scratch. Mostly fo… 0 mdoerges/debian-buster-nginx Debian Buster with Nginx 0
Descargar una imagen del repositorio dockerhub
root@docker-master:~# docker pull debian Using default tag: latest latest: Pulling from library/debian e4c3d3e4f7b0: Pull complete Digest: sha256:8414aa82208bc4c2761dc149df67e25c6b8a9380e5d8c4e7b5c84ca2d04bb244 Status: Downloaded newer image for debian:latest docker.io/library/debian:latest
root@docker-master:~# docker pull wynemo/python38 Using default tag: latest latest: Pulling from wynemo/python38 afb6ec6fdc1c: Pull complete 2cf47e503ea9: Pull complete d7b3e3d1255f: Pull complete e7661b83ac73: Pull complete aab48912491a: Pull complete 960d5d303907: Pull complete 8c6ab51d1b47: Pull complete 6a6d63bba2c3: Pull complete Digest: sha256:60c3f28d6634cf4408712c87f02e52c2e354d070993647a064ef75c98af7f66a Status: Downloaded newer image for wynemo/python38:latest docker.io/wynemo/python38:latest
Ver imagenes montadas/descargadas en nuestra máquina
root@docker-master:~# docker images REPOSITORY TAG IMAGE ID CREATED SIZE debian latest 1510e8501783 3 weeks ago 114MB portainer/portainer-ce a0a227bf03dd 2 months ago 196MB portainer/agent 6b367a5c4fe3 2 months ago 89.8MB wynemo/python38 latest 3200f7c701d5 5 months ago 391MB
Ver datos de la imagen
Aquí nos podemos hacer una idea de como se va a construir ésta imagen, variables de entorno, configuración de puertos, etc.
root@docker-master:~# docker inspect debian
Ver datos de un contenedor contenedor
root@docker-master:~# docker inspect portainer_portainer.1.o2v7ve9123h9c2wcta0paqmi2
Lanzar un contenedor de Docker a partir de una imagen descargada
root@docker-master:~# docker run -dtiP --name contenedor debian 76ec0cdbabcb5b894dabc5e02068e0db620d1ed957b07802904297515efa3eb7 root@docker-master:~# docker run -dti -p 8080:80 --name wp wordpress babc1e111bb3c05f66138ac68f669d5abb049eab4166d75b2e22e46fd437ec91
Opciones disponibles
-d -> dettach -> correr en background -t terminal -> habilitar el acceso con terminal al contenedor -i interactive -> permitir interactuar con el contenedor --name nombrecontenedor -> nombre del contenedor, si no se define esta opción pone un nombre aleatorio -e VAR=valuevar -> definir valores de las variables de entorno definidas en el Dockerfile -P -> publish all, expone los puertos tal como están definidos en la imagen con un puerto aleatorio (30.000 al 32.800) -p 8080:80 -> mapea el puerto 80 del contenedor al puerto 8080 del host --rm -> cuando se pare el contenedor que se borre automáticamente --restart=always -> si se para el contenedor vuelve a ponerlo en marcha -v /voldatos:/var/lib/mysql -> monta el directorio /voldatos del host en /var/lib/mysql del contenedor
Otros ejemplos
docker run -dti nginx docker run -dti --name frontal-nginx nginx docker run -dtiP -v /voldatos:/var/lib/mysql docker run -dti -p80:80 -v /voldatos:/var/lib/mysql docker run -dti --name nomct -e VAR=valuevar
Cuando mapeamos puertos estamos haciendo uso de iptables
root@docker-master:~# iptables -t nat -L DOCKER -v -n Chain DOCKER (2 references) pkts bytes target prot opt in out source destination 0 0 RETURN all -- docker_gwbridge * 0.0.0.0/0 0.0.0.0/0 0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0 0 0 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 to:172.17.0.3:80
Cuando usamos NAT, por defecto la red interna de Docker es 172.17.0.0/16
Ver contenedores
Ver contenedores activos
root@docker-master:~# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES babc1e111bb3 wordpress "docker-entrypoint.s…" 2 minutes ago Up 2 minutes 0.0.0.0:8080->80/tcp wp 76ec0cdbabcb debian "bash" 12 minutes ago Up 12 minutes contenedor 19f3f9919ee0 portainer/agent:latest "./agent" 4 days ago Up 4 days portainer_agent.nty1ejqatx2fsgpb6veclsqi9.s16d83o5fylxptyw6m40txmmp de837dc53a72 portainer/portainer-ce:latest "/portainer -H tcp:/…" 4 days ago Up 4 days 8000/tcp, 9000/tcp portainer_portainer.1.o2v7ve9123h9c2wcta0paqmi2
Ver todos los contenedores
root@docker-master:~# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES babc1e111bb3 wordpress "docker-entrypoint.s…" 2 minutes ago Up 2 minutes 0.0.0.0:8080->80/tcp wp 76ec0cdbabcb debian "bash" 12 minutes ago Up 12 minutes contenedor 19f3f9919ee0 portainer/agent:latest "./agent" 4 days ago Up 4 days portainer_agent.nty1ejqatx2fsgpb6veclsqi9.s16d83o5fylxptyw6m40txmmp de837dc53a72 portainer/portainer-ce:latest "/portainer -H tcp:/…" 4 days ago Up 4 days 8000/tcp, 9000/tcp portainer_portainer.1.o2v7ve9123h9c2wcta0paqmi2 3e43aa6c7ba3 portainer/portainer-ce:latest "/portainer -H tcp:/…" 4 days ago Exited (1) 4 days ago portainer_portainer.1.ifij1hvkc6u3dnzs5s3lia0kh b2bce3f683e6 portainer/portainer-ce:latest "/portainer -H tcp:/…" 4 days ago Exited (1) 4 days ago portainer_portainer.1.d1wnwcnm7e6anc4dt429jfyp9 39f260ff1a59 portainer/portainer-ce:latest "/portainer -H tcp:/…" 4 days ago Exited (1) 4 days ago portainer_portainer.1.ag2ovmy1e7q11k47zm2870fmv d9fc2e2938b6 portainer/portainer-ce:latest "/portainer -H tcp:/…" 4 days ago Exited (1) 4 days ago portainer_portainer.1.q99tmtqpgxffnfv03v46spxui
Ver el último contenedor creado
root@docker-master:~# docker ps -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES babc1e111bb3 wordpress "docker-entrypoint.s…" 2 minutes ago Up 2 minutes 0.0.0.0:8080->80/tcp wp
Entrar en un contenedor
root@docker-master:~# docker exec -ti contenedor /bin/bash root@76ec0cdbabcb:/# cat /etc/os-release PRETTY_NAME="Debian GNU/Linux 10 (buster)" NAME="Debian GNU/Linux" VERSION_ID="10" VERSION="10 (buster)" VERSION_CODENAME=buster ID=debian HOME_URL="https://www.debian.org/" SUPPORT_URL="https://www.debian.org/support" BUG_REPORT_URL="https://bugs.debian.org/"
Otros comandos
docker rm ctname/ctid -> borrar contenedor (usar -f para borrarlo incluso si está encendido)
docker rmi imgname -> borrar imagen (creada con el dockerfile o descargada con docker pull)
docker stop ct -> parar contenedor
docker start ct -> arrancar contenedor
docker pause ct -> pausar contenedor
docker unpause ct -> despausar contenedor
docker logs ct -> ver los logs de la aplicación que corre dentro del contenedor
docker attach ct -> similar a exec -ti
docker stats ct -> ver las estadísticas de consumo del contenedor
docker stop $(docker ps -a -q) -> parar todos los contenedores
docker rm $(docker ps -a -q) -> borrar todos los contenedores
Poner límites y configurar un contenedor
root@docker-master:~# docker update --help Usage: docker update [OPTIONS] CONTAINER [CONTAINER...] Update configuration of one or more containers Options: --blkio-weight uint16 Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0) --cpu-period int Limit CPU CFS (Completely Fair Scheduler) period --cpu-quota int Limit CPU CFS (Completely Fair Scheduler) quota --cpu-rt-period int Limit the CPU real-time period in microseconds --cpu-rt-runtime int Limit the CPU real-time runtime in microseconds -c, --cpu-shares int CPU shares (relative weight) --cpus decimal Number of CPUs --cpuset-cpus string CPUs in which to allow execution (0-3, 0,1) --cpuset-mems string MEMs in which to allow execution (0-3, 0,1) --kernel-memory bytes Kernel memory limit -m, --memory bytes Memory limit --memory-reservation bytes Memory soft limit --memory-swap bytes Swap limit equal to memory plus swap: '-1' to enable unlimited swap --pids-limit int Tune container pids limit (set -1 for unlimited) --restart string Restart policy to apply when a container exits
Ejemplo
# limitar el contenidor a 100Mb i swap desactivada root@docker-master:~# docker update -m 100M --memory-swap -1 ct root@docker-master:~# docker stats contenedor CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 76ec0cdbabcb contenedor 0.00% 1.664MiB / 100MiB 1.66% 1.52kB / 0B 0B / 0B 1
En docker se recomienda desactivar la swap. En kubernettes es obligatorio.
Copias de seguridad (imágenes)
docker save -o httpd.tar httpd -> poner una imagen a un fichero
docker load -i httpd.tar -> restaurar una imagen desde un fichero
Convertir contenedores a imágenes (no recomendable)
No se recomienda porque la forma correcta es la de desplegar contenedores personalizados mediante los Docker file
docker commit -m "Comentario imagen" ct nombreimagen
Cambiar el nombre a la imagen
docker tag nombreimagen nombreimagen:0.1
Publicar una imagen en Docker Hub
Para publicar una imagen en Docker Hub es obligatorio que tenga el siguiente formato
usuariodedockerhub/imagen:version
docker tag imagen usuariodedockerhub/imagen docker login cat /root/.docker/config.json docker push usuariodedockerhub/imagen docker logout docker search usuariodockerhub
Es posible conectar una cuenta de github a la de dockerhub para hacer desarrollo contínuo (wildfly)
Es posible trabajar con un repositorio local (docker registry konradkleine/docker-registry-frontend)
Con ésto tendríamos lo básico para trabajar con Docker. Lo siguiente será construir nuestras propias imágenes con Dockerfile y despliegue de varios contenedores con docker-compose. Ésto lo dejamos para otro post :)
Pingback: Introducción al trabajo con Dockerfile – Blackhold
Pingback: Introducción al trabajo con Dockerfile Blackhold - Blog de Informática
Pingback: Caso real de despliegue con Docker Compose – Blackhold
Pingback: Caso real de despliegue con Docker Compose Blackhold - Blog de Informática