Docker desde la base comprensión de las imágenes

Los contenedores Docker están en aumento como una mejor práctica para implementar y administrar sistemas distribuidos nativos en la nube. Los contenedores son instancias de imágenes Docker. Resulta que hay mucho que saber y entender acerca de las imágenes.. 

En este tutorial de dos partes, cubriré las imágenes de Docker en profundidad. En esta parte, comenzaré con los principios básicos, y luego pasaré a la consideración del diseño e inspeccionar los aspectos internos de la imagen. En la segunda parte, me ocuparé de crear sus propias imágenes, solucionar problemas y trabajar con repositorios de imágenes.. 

Cuando salga al otro lado, tendrá una sólida comprensión de qué son exactamente las imágenes de Docker y cómo utilizarlas de manera efectiva en sus propias aplicaciones y sistemas..

Entendiendo capas

Docker administra las imágenes usando un controlador de almacenamiento de back-end. Hay varios controladores compatibles, como AUFS, BTRFS y superposiciones. Las imágenes están hechas de capas ordenadas. Puede pensar en una capa como un conjunto de cambios en el sistema de archivos. Cuando toma todas las capas y las apila, obtiene una nueva imagen que contiene todos los cambios acumulados.. 

La parte ordenada es importante. Si agrega un archivo en una capa y lo elimina en otra capa, es mejor que lo haga en el orden correcto. Docker realiza un seguimiento de cada capa. Una imagen puede estar compuesta por docenas de capas (el límite actual es 127). Cada capa es muy ligera. El beneficio de las capas es que las imágenes pueden compartir capas.. 

Si tiene muchas imágenes basadas en capas similares, como el sistema operativo base o paquetes comunes, entonces todas estas capas comunes se almacenarán solo una vez, y la sobrecarga por imagen será solo las capas únicas de esa imagen..

Copiar en escrito

Cuando se crea un nuevo contenedor a partir de una imagen, todas las capas de imagen son de solo lectura y se agrega una capa delgada de lectura-escritura en la parte superior. Todos los cambios realizados en el contenedor específico se almacenan en esa capa. 

Ahora, no significa que el contenedor no pueda modificar los archivos de su capa de imagen. Definitivamente se puede. Pero creará una copia en su capa superior y, a partir de ese momento, cualquier persona que intente acceder al archivo obtendrá la copia de la capa superior. Cuando los archivos o directorios se eliminan de las capas inferiores, se ocultan. Las capas de imagen originales se identifican mediante un hash basado en contenido criptográfico. La capa de lectura-escritura del contenedor se identifica mediante un UUID.

Esto permite una estrategia de copia en escritura para imágenes y contenedores. Docker reutiliza los mismos elementos tanto como sea posible. Solo cuando se modifica un elemento, Docker creará una nueva copia..

Consideraciones de diseño para imágenes Docker

La organización única en capas y la estrategia de copia en escritura promueven algunas mejores prácticas para crear y componer imágenes de Docker.

Imágenes mínimas: menos es más

Las imágenes Docker obtienen enormes beneficios desde el punto de vista de estabilidad, seguridad y tiempo de carga, cuanto más pequeños son. Puedes crear imágenes realmente pequeñas para propósitos de producción. Si necesita solucionar problemas, siempre puede instalar herramientas en un contenedor. 

Si escribe sus datos, registros y todo lo demás solo en volúmenes montados, puede usar todo su arsenal de herramientas de resolución de problemas y solución de problemas en el host. Pronto veremos cómo controlar con mucho cuidado qué archivos entran en su imagen Docker.

Combinar capas

Las capas son excelentes, pero hay un límite, y hay una sobrecarga asociada con las capas. Demasiadas capas podrían dañar el acceso al sistema de archivos dentro del contenedor (ya que cada capa puede haber agregado o eliminado un archivo o directorio), y simplemente saturan su propio sistema de archivos..

Por ejemplo, si instala un montón de paquetes, puede tener una capa para cada paquete, instalando cada paquete en un comando RUN separado en su Dockerfile:

RUN apt-get update RUN apt-get -y install package_1 RUN apt-get -y install package_2 RUN apt-get -y install package_3

O puede combinarlos en una capa con un solo comando RUN.

EJECUTAR apt-get update && \ apt-get -y install package_1 && \ apt-get -y install package_2 && \ apt-get -y install package_3 

Elegir una imagen base

Su imagen base (prácticamente nadie construye imágenes desde cero) es a menudo una decisión importante. Puede contener muchas capas y agregar muchas capacidades, pero también mucho peso. La calidad de la imagen y el autor también son críticos. No querrás basar tus imágenes en una imagen escamosa en la que no estás seguro de qué hay exactamente y si puedes confiar en el autor..

Hay imágenes oficiales para muchas distribuciones, lenguajes de programación, bases de datos y entornos de ejecución. A veces las opciones son abrumadoras. Tómate tu tiempo y haz una sabia elección.

Inspeccionando imagenes

Veamos algunas imágenes. Aquí hay una lista de las imágenes actualmente disponibles en mi máquina:

REPOSITORIO ETIQUETA ID DE LA IMAGEN TAMAÑO CREADO python última 775dae9b960e hace 12 días 687 MB d4w / nsenter última 9e4f13a0901e Hace 4 meses 83.8 kB ubuntu-with-ssh la última instancia de la información de los últimos de los últimos 5 días. Hace meses 1.85 kB alpino último 4e38e38c8ce0 Hace 7 meses 4.8 MB nsqio / nsq último 2a82c70fe5e3 Hace 8 meses 70.7 MB

El repositorio y la etiqueta identifican la imagen para los humanos. Si solo intenta ejecutar o arrastrar utilizando un nombre de repositorio sin especificar la etiqueta, entonces la etiqueta "más reciente" se usa de forma predeterminada. La identificación de la imagen es un identificador único.

Vamos a sumergirnos e inspeccionar la imagen de hello-world:

> docker inspecciona hello-world ["Id": "sha256: c54a2cc56cbb2f… e7e2720f70976c4b75237dc", "RepoTags": "" "" "" "" "" "" "" "" "" "" "" Cosas a la luz de las "" "" ], "Parent": "", "Comment": "", "Created": "2016-07-01T19: 39: 27.532838486Z", "Container": "562cadb4d17bbf30b58a… bf637f1d2d7f8afbef666", "ContainerConfig": "namename] ":" c65bc554a4b7 "," Domainname ":" "," User ":", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty": false, "OpenStdin": false, "StdinOnce": falso, "Env": ["PATH = / usr / bin: / usr / sbin: / usr / bin: / sbin: / bin"], "Cmd": ["/ bin / sh", " -c "," # (nop) CMD [\ "/ hello \"] "]," Image ":" sha256: 0f9bb7da10de694… 5ab0fe537ce1cd831e "," Volumes ": null," WorkingDir ":", "Entrypoint": null, "OnBuild": null, "Labels": , "DockerVersion": "1.10.3", "Author": "", "Config": "Hostname": "c65bc554a4b7", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty": false, "Open Stdin ": false," StdinOnce ": false," Env ": [" PATH = / usr / sbin: / usr / bin: / sbin: / bin "]," Cmd ": [" / hello "]," Image ":" sha256: 0f9bb7da10de694b… b0fe537ce1cd831e "," Volumes ": null," WorkingDir ":", "Entrypoint": null, "OnBuild": null, "Labels": , "Architecture": "amd64" , "Os": "linux", "Tamaño": 1848, "VirtualSize": 1848, "GraphDriver": "Name": "aufs", "Data": null, "RootFS": "Type": "capas", "Capas": ["sha256: a02596fdd012f22b03a… 079c3e8cebceb4262d7"]]

Es interesante ver cuánta información se asocia con cada imagen. No repasaré cada artículo. Solo mencionaré un dato interesante que las entradas "contenedor" y "containerConfig" son para un contenedor temporal que Docker crea cuando construye la imagen. Aquí, quiero centrarme en la última sección de "RootFS". Puede obtener solo esta parte utilizando el soporte de plantillas Go del comando inspeccionar:

> docker inspect -f '.RootFS' hello-world layers [sha256: a02596fdd012f22b03af6a… 8357b079c3e8cebceb4262d7]

Funciona, pero perdimos el buen formato. Prefiero usar jq:

> docker inspecciona hello-world | jq. [0] .RootFS "Tipo": "capas", "Capas": ["sha256: a02596fdd012f22b03af6a… 7507558357b079c3e8cebceb4262d7"] 

Puedes ver que el tipo es "Capas", y solo hay una capa. 

Inspeccionemos las capas de la imagen de Python:

> docker inspeccionar python | JQ [0] .RootFS  "Tipo":. "capas", "capas": [ "sha256: a2ae92ffcd29f7ede ... e681696874932db7aee2c", "sha256: 0eb22bfb707db44a8 ... 8f04be511aba313bdc090", "sha256: 30339f20ced009fc3 ... 6b2a44b0d39098e2e2c40", "sha256: f55f65539fab084d4 ... 52932c7d4924c9bfa6c9e "," sha256: Vf130fa783aef35 ... v8503e06fc1975a47002d "," sha256 "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "

Guau. Siete capas. ¿Pero cuáles son esas capas? Podemos usar el comando de historial para resolverlo:

IMAGEN CREADA POR EL TAMAÑO 775dae9b960e Hace 12 días / bin / sh -c # (nop) CMD ["python3"] 0 B  Hace 12 días / bin / sh -c cd / usr / local / bin && … 48 B  Hace 12 días / bin / sh -c set -ex && buildDeps = '… 66.9 MB  Hace 12 días / bin / sh -c # (nop) ENV PYTHON_PIP_V… 0 B  Hace 12 días / bin / sh -c # (nop) ENV PYTHON_VERSI… 0 B  Hace 12 días / bin / sh -c # (nop) ENV GPG_KEY = 0D96… 0 B  Hace 12 días / bin / sh -c apt-get update && apt-ge… 7.75 MB  Hace 12 días / bin / sh -c # (nop) ENV LANG = C.UTF-8 0 B  Hace 12 días / bin / sh -c # (nop) ENV PATH = / usr / lo ... 0 B  Hace 13 días / bin / sh -c apt-get update && apt-ge… 323 MB  Hace 13 días / bin / sh -c apt-get update && apt-ge… 123 MB  Hace 13 días / bin / sh -c apt-get update && apt-ge… 44.3 MB  Hace 13 días / bin / sh -c # (nop) CMD ["/ bin / bash"… 0 B  Hace 13 días / bin / sh -c # (nop) AGREGAR archivo: 89ecb642… 123 MB

DE ACUERDO. No te alarmes. No falta nada. Esto es sólo una interfaz de usuario terrible. Las capas solían tener una ID de imagen antes de Docker 1.10, pero ya no. El ID de la capa superior no es realmente el ID de esa capa. Es el ID de la imagen de Python. El "CREADO POR" está truncado, pero puede ver el comando completo si pasa --no-trunc. Lo guardaré de la salida aquí debido a las limitaciones de ancho de página que requerirán un ajuste de línea extremo.

¿Cómo se obtienen las imágenes? Hay tres maneras:

  • Tirar / correr
  • Carga
  • Construir

Cuando ejecutas un contenedor, especificas su imagen. Si la imagen no existe en su sistema, se está extrayendo de un registro de Docker (de manera predeterminada, DockerHub). Alternativamente, puede tirar directamente sin ejecutar el contenedor.

También puede cargar una imagen que alguien le envió como un archivo tar. Docker lo soporta de forma nativa..

Finalmente, y lo más interesante, puedes crear tus propias imágenes, que es el tema de la segunda parte..

Conclusión

Las imágenes de Docker se basan en un sistema de archivos en capas que ofrece muchas ventajas y beneficios para los casos de uso para los que están diseñados los contenedores, como ser livianos y compartir partes comunes, por lo que muchos contenedores pueden implementarse y ejecutarse en la misma máquina de manera económica.. 

.