Herramientas de usuario

Herramientas del sitio


informatica:sistemas_operativos:virtualizacion:docker

Docker

Herramienta que permite desplegar aplicaciones en contenedores de forma rápida y portable.

Utiliza contenedores e imágenes. En las imágenes se define toda la configuración del software, bibliotecas, etc., todo lo que necesita la aplicación para funcionar. En un contenedor se vuelve realidad.

  • Aplicaciones de bolsillo
  • Desplegar y escalar aplicaciones
  • Destruir y recrear.

Ejemplo de uso:

docker run -d -p 80:80 --name web httpd

Para eliminarlo:

docker rm -fv web

Arquitectura de Docker

Imágenes

Una imagen es un paquete que contiene toda la configuración necesaria para que funcione el servicio/aplicación.

Las imágenes se componen de capas y son de solo lectura. En la primera capa definimos qué sistema operativo tendremos en la imagen.

Las capas se definen través de un fichero Dockerfile:

FROM centos:7
# Instalación del servidor web Apache
RUN yum -y install httpd
 
# Definimos el comando que ejecutará Apache. Es importante que se ejecute en primer plano o el contenedor finalizará en el momento en que se haya ejecutado lo que hay en ''CMD''
CMD ["apachectl", "-DFOREGROUND"]

Cuando no se especifica una etiqueta/tag, por defecto se descarga la latest

Imágenes oficiales

Las imágenes se alojan en el Docker Hub

Para descargarlas:

docker pull nombre-imagen

Para saber las imágenes que tenemos descargadas o en el sistema:

docker images

Para eliminar una imagen:

docker rmi nombre-imagen|identificador-imagen

Imágenes propias

Creamos un fichero Dockerfile:

FROM centos:latest
RUN yum -y install httpd

Para convertirla en imagen:

docker build --tag nombre-nueva-imagen .

Para ver las capas que se crearon en una imagen:

docker history -H nombre-imagen

Operaciones

Eliminar imágenes:

docker rmi nombre-imagen

Imágenes huérfanas:

docker images -f dangling=true

Y para eliminarlas:

docker images -f dangling=true -q | xargs docker rmi

Para eliminar las imágenes que no están en uso ni referenciadas también se puede utilizar docker image prune

Dockerfile

Fichero para la creación de imágenes.

  • FROM: imagen de base
  • RUN: cualquier comando disponible en Linux
  • COPY: copia archivos desde la máquina local hacia la imagen (opción recomendada por Docker).
  • ADD: copia archivos desde la máquina local o remota (se puede indicar una URL) hacia la imagen.
  • ENV: variables de entorno
  • WORKDIR: directorio actual de trabajo en la imagen
  • EXPOSE: puerto que se expondrá desde el contenedor.
  • LABEL: etiquetas para mostrar alguna información, metadatos.
  • USER: indica el usuario que ejecutará la tarea (por defecto es root)
  • VOLUME: permite indicar qué datos serán persistentes en la creación del contenedor (volúmenes anónimos).
  • CMD: comando o script para mantener un contenedor en ejecución
FROM centos

LABEL version=1.0
LABEL description="This is an apache imagen"
LABEL vendor=yo

RUN yum install httpd -y

WORKDIR /var/www

# No ponemos /var/www/html como destino de la copia porque
# con WORKDIR nos hemos posicionado en /var/www, así que solo
# quedaría indicar html
COPY app html/

# variable valor
ENV contenido prueba

RUN echo "$contenido" > /var/www/html/prueba.html

RUN useradd pepito

# A partir de aquí, todo lo que se ejecuté, será por el 
# usuario pepito
USER pepito

RUN echo "$(whoami)" > /tmp/user.html

# Volvemos a ser root
USER root

RUN cp /tmp/user.html /var/www/html/user.html
CMD apachectl -DFOREGROUND

En CMD solo se puede indicar un comando, así que si necesitamos más, habría que crear un script con todo lo necesario y luego colocar ese script en CMD

Con el Dockerfile creado, para crear la nueva imagen a partir de él:

docker build -t apache .

Si nuestro Dockerfile tiene otro nombre, hay que indicarlo a la hora de crear la imagen:

docker build -t prueba -f mi-dockerfile .

.dockerignore

Fichero que permite ignorar cualquier cosa que esté en el directorio actual y no incluirlo en una imagen:

fichero-ignorado

Multi-Stage Build

Permite utilizar varios FROM en el Dockerfile:

# La imagen de centos ya ocupa unos 200 MB
FROM centos as test

RUN fallocate -l 10M /opt/file1

RUN fallocate -l 20M /opt/file2

RUN fallocate -l 30M /opt/file3

# La imagen de alpine son poco más de 4 MB
FROM alpine

COPY --from=test /opt/file2 /opt/file

Cuando se cree la imagen, tendrá el tamaño de la imagen alpine y el fichero que hemos copiado de la anterior imagen

Buenas prácticas

  • Un contenedor por servicio
  • .dockerignore
  • Pocas capas
  • Multilínea (\) para facilitar la lectura
  • Varios argumentos en una sola capa
  • No instalar paquetes innecesarios
  • Utilizar labels para añadir metadatos a la imagen

Contenedores

Sería la siguiente capa de una imagen. Ejecución de la imagen. Es de lectura y escritura. Podemos modificar cosas en el contenedor, pero no en la imagen.

Un contenedor contiene:

  • Imagen
  • Volúmenes
  • Redes

Creación

Para crear un contenedor:

docker run -d -p 80:80 --name mi-contenedor imagen
  • -d: ejecuta el contenedor en segundo plano.
  • -p: puerto local:puerto de la imagen
  • --name: nombre que tendrá el contenedor

Podemos ver los contenedores en ejecución:

docker ps

Si queremos ver también los que se han detenido o finalizado:

docker ps -a

Eliminar

docker rm -f nombre-contenedor

Si queremos eliminar todos a la vez:

docker rm -fv $(docker ps -aq)

También se pueden eliminar los contenedores detenidos con docker container prune

Renombrar

docker rename nombre-antiguo nombre-nuevo

Detener

docker stop nombre-contenedor|id-contenedor

Iniciar

docker start nombre-contenedor|id-contenedor

Entrar en el contenedor

docker exec -it contenedor bash

Si queremos entrar como cierto usuario:

docker exec -u root -it contenedor bash

El usuario tiene que existir en la imagen o en el contenedor.

Variables de entorno

Si queremos especificar variables de entorno a la hora de crear un contenedor:

docker run -d -e "prueba:1234" --name mi-contenedor imagen

Es útil para imágenes que ya tienen definidas algunas variables:

docker run -d -e "MYSQL_ROOT_PASSWORD=123456" mysql

Copiar archivos

Si queremos copiar archivos desde nuestro equipo local hacia el contenedor:

docker cp fichero1 mi-contenedor:/ruta/contenedor/fichero1

Para copiar desde el contenedor a nuestra máquina:

docker cp mi-contenedor:/ruta/contenedor/fichero1 fichero1

Eliminar contenedores automáticamente

Para indicar que el contenedor que queremos crear es temporal y que al finalizar, lo borre:

docker run --rm -ti --name mi-contenedor imagen bash

Cuando salgamos del terminal bash del contenedor, Docker lo eliminará.

Recursos consumidos

docker stats nombre-contenedor|id-contenedor

Ejemplo de salida:

CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
9aa067025bbe        cloud.tempwin.net   0.00%               121.2MiB / 7.791GiB   1.52%               669MB / 375MB       0B / 0B             146

Para limitar el uso de RAM que podrá hacer un contenedor:

docker run -d --memory "1gb" --name mi-contenedor imagen

Para limitar el número de CPUs:

docker run -d --cpuset-cpus 0-1 --name mi-contendor imagen

Le hemos indicado que ese contenedor solo podrá usar la CPU 0 y la CPU 1

Registros

Para centrarnos en los registros de un único servicio:

docker logs -t -f <name-of-service>

Volúmenes

Herramienta para almacenar datos del contenedor de forma persistente en nuestra máquina local.

Volúmenes de host

Residen en una carpeta del sistema de ficheros de la máquina local

docker run -d -v /opt/mysql:/var/lib/mysql -p 3306:3306 --name mi-contenedor mysql

De esa manera indicamos que el directorio /var/lib/mysql del contenedor va a estar disponible desde el directorio /opt/mysql de la máquina local.

Volúmenes anónimos

docker run -d -v /var/lib/mysql -p 3306:3306 --name mi-contenedor mysql

Al no definir en qué carpeta quedará asociada la del contenedor, Docker le dará una al azar.

No es recomendable utilizar este tipo de volúmenes ya que, además de tener nombres difíciles de memorizar, en el momento de eliminar el contenedor, Docker borrará el volumen también.

Volúmenes nombrados

Volúmenes creados por el usuario.

Para crear un volumen llamado mysql-data:

docker volume create mysql-data

Para eliminarlo:

docker volume rm mysql-data

Para asociarlo a un contenedor:

docker run -d --name mi-contenedor -v mysql-data:/var/lib/mysq -p 3306:3306 mysql

La ventaja de este tipo de volúmenes es que no se borran al eliminar el contenedor

Volúmenes huérfanos

Se llaman volúmenes dangling, no están referenciados por ningún contenedor. Para encontrarlos:

docker volume ls -f dangling=true

Para borrarlos todos de una vez:

docker volume ls -f dangling=true -q | xargs docker volume rm
  • -q: muestra el identificador del volumen

Redes

Con la instalación de Docker se crea una nueva interfaz de red:

$ ip a | grep docker

11: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0

Todos los contenedores que creemos, estarán dentro de esa red:

docker inspect nombre|id-contenedor

Consultamos el valor IPAddress para saber la IP que usa el contenedor

La red por defecto se llama bridge

Para ver todas las redes:

docker network ls

Tipos

  • Bridge
  • Host: la red de la propia máquina
  • None: los contenedores que se metan ahí no tendrán red
  • Overlay

Creación

docker network create nombre-red

Podemos configurar la subred:

docker network create --subnet 172.120.0.0/24 --gateway 172.120.0.1 nombre-red 

Inspeccionar

docker network inspect nombre-red

Eliminación

docker network rm nombre-red

Para poder eliminar una red, no debe haber ningún contendor que esté usándola

Asignación

Si queremos crear un contenedor en una determinada red:

docker run --network nombre-red -d --name mi-contenedor centos

En las redes creadas por el usuario, podemos ver los contenedores por su nombre.

Esto no es posible en la red por defecto de Docker, solo se podría por IP

Asignar IP

docker run --network mi-red --ip 172.120.0.10 -d --name mi-contendor imagen

Conectar contenedor distintas redes

docker network connect nombre-red contenedor

De esa manera, indicamos a Docker que contenedor también está en la red nombre-red

Si queremos desconectarlo de cierta red:

docker network disconnect nombre-red contenedor

Docker Compose

Herramienta que ayuda a crear aplicaciones multicontenedor. Aplicaciones como aplicaciones web utilizan bases de datos, algún lenguaje de programación y servidor web. Crearíamos un contenedor por cada elemento necesario. En lugar de hacerlo por separado, Docker Compose nos permite definirlo en un único archivo de texto y él gestionará la creación de contenedores, volúmenes, redes, etc.

Instalación

Actualizar el proceso de instalación manual, el que aquí se muestra está desfasado

sudo curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

Y le damos permisos de ejecución:

sudo chmod +x /usr/local/bin/docker-compose

Uso

El fichero de configuración de Docker Compose se llama docker-compose.yml. El fichero se compone de 4 bloques:

# Obligatorias:
version:
services:

# Opcionales:
volumes:
networks:
docker run -d --name nginx -p 80:80 nginx

Traducido al docker-compose.yml:

version: '3'
services:
  web:
    image: nginx
    container_name: nginx
    ports:
      - "80:80"   

En Docker Compose, los contenedores que se crean se ejecutan en segundo plano, como cuando indicamos la opción -d

Para arrancar todo lo definido en el fichero docker-compose.yml:

docker-compose up -d

Si queremos darle un nombre, en lugar del que defina Docker Compose, lo lanzaremos así:

docker-compose -p nombre-proyecto up -d

Si utilizamos un Docker Compose diferentes al esperado (docker-compose.yml), añadimos la opción -f:

docker-compose -f docker-compose-mysql.yml up -d

Eliminar contenedores

docker-compose down

Variables de entorno

Podemos definirlas desde el propio fichero docker-compose.yml:

version: '3'
services:
  web:
    image: mysql
    container_name: mysql
    ports:
      - "3306:3306"   
    environment:
      - "MYSQL_ROOT_PASSWORD=abc123."

O en un fichero externo, por ejemplo, en .env:

MYSQL_ROOT_PASSWORD=abc123.
MYSQL_USER=pepito

Y luego hacemos referencia a él desde docker-compose.yaml:

version: '3'
services:
  web:
    image: mysql
    container_name: mysql
    ports:
      - "3306:3306"   
    env_file: .env

Volúmenes

Volúmenes nombrados:

version: 3
services:
  web:
    image: nginx
    container_name: nginx
    ports:
      - "80:80"   
    volumes:
      - "mi-volumen:/usr/share/nginx/html"
volumes:
  mi-volumen:

Para definir un volumen de host:

version: 3
services:
  web:
    image: nginx
    container_name: nginx
    ports:
      - "80:80"   
    volumes:
      - "/mi/ruta/:/usr/share/nginx/html"

Políticas de reinicio

version: '3'
services:
  servicio:
    ...
    restart: no

Por defecto, Docker Compose no reinicia los contenedores si se han detenido.

Otras opciones:

  • always: el contenedor siempre se reiniciará
  • on-failure: el contenedor se reinicia si hubo un fallo
  • unless-stopped: el contenedor se reinicia solo si no ha sido detenido

Administración

Docker root dir

El directorio raíz de Docker (Docker Root Dir) es por defecto /var/lib/docker. Podemos saberlo:

docker info | grep -i "root"

Antes de hacer ningún cambio, detenemos el servicio de Docker:

systemctl stop docker

Para indicar un nuevo directorio, vamos a /lib/systemd/system/docker.service:

ExecStart=/usr/bin/dockerd --data-root /nuevo/docker-root-dir

Recargamos la nueva configuración:

systemctl daemon-reload

Y reiniciamos el servicio de Docker:

systemctl restart docker
informatica/sistemas_operativos/virtualizacion/docker.txt · Última modificación: por tempwin