En la traducción de la tercera parte de la serie Docker, seguiremos inspirándonos en pasteles, a saber, bagels. Nuestro tema principal hoy será trabajar con Dockerfiles. Analizaremos las instrucciones que se utilizan en estos archivos.
→
Parte 1: lo básico→
Parte 2: términos y conceptos→
Parte 3: archivos Dockerfile→
Parte 4: reducir el tamaño de las imágenes y acelerar su ensamblaje→
Parte 5: equipos→
Parte 6: trabajar con datosBagels son instrucciones en un Dockerfile.Imágenes de Docker
Recuerde que un contenedor Docker es una imagen Docker que cobra vida. Este es un sistema operativo autónomo en el que solo hay el código de aplicación y el más necesario.
Las imágenes de Docker son el resultado del proceso de compilación, y los contenedores de Docker están ejecutando imágenes. En el corazón de Docker están los Dockerfiles. Archivos como este le dicen a Docker cómo ensamblar las imágenes a partir de las cuales se crean los contenedores.
Cada imagen de Docker tiene un archivo llamado Dockerfile. Su nombre está escrito de esa manera, sin extensión. Cuando ejecuta el
docker build
para crear una nueva imagen, se supone que el Dockerfile está en el directorio de trabajo actual. Si este archivo se encuentra en otro lugar, su ubicación se puede especificar utilizando el indicador
-f
.
Los contenedores, como descubrimos en el primer material de esta serie, consisten en capas. Cada capa, excepto la última, ubicada encima de todas las demás, es de solo lectura. Dockerfile le dice al sistema Docker qué capas y en qué orden agregar a la imagen.
Cada capa, de hecho, es solo un archivo que describe el cambio en el estado de la imagen en comparación con el estado en el que estaba después de agregar la capa anterior. En Unix, por cierto, casi cualquier cosa es un
archivo .
Una imagen básica es cuál es la capa (o capas) de origen de la imagen que se está creando. La imagen base también se llama imagen principal.
La imagen básica es donde comienza la imagen de Docker.Cuando una imagen se descarga desde un repositorio remoto a una computadora local, solo las capas que no están disponibles en esta computadora se descargan físicamente. Docker tiene como objetivo ahorrar espacio y tiempo reutilizando las capas existentes.
Archivos Dockerfile
Los archivos Docker contienen instrucciones para crear una imagen. En mayúsculas, comienzan las líneas de este archivo. Siguiendo las instrucciones están sus argumentos. Las instrucciones, al construir la imagen, se procesan de arriba a abajo. Así es como se ve:
FROM ubuntu:18.04 COPY . /app
Las capas de la imagen final se crean solo mediante las instrucciones
FROM
,
RUN
,
COPY
y
ADD
. Otras instrucciones configuran algo, describen metadatos o le dicen a Docker que necesita hacer algo durante la ejecución del contenedor, por ejemplo, abrir algún puerto o ejecutar algún comando.
Aquí procedemos de la suposición de que se utiliza una imagen de Docker basada en un sistema operativo tipo Unix. Por supuesto, aquí también puede usar una imagen basada en Windows, pero usar Windows es una práctica menos común, trabajar con esas imágenes es más difícil. Como resultado, si tiene la oportunidad, use Unix.
Para comenzar, aquí hay una lista de instrucciones de Dockerfile con breves comentarios.
Docena de instrucciones Dockerfile
FROM
: establece la imagen base (principal).LABEL
: describe los metadatos. Por ejemplo, información sobre quién creó y mantiene la imagen.ENV
: establece variables de entorno persistentes.RUN
: ejecuta un comando y crea una capa de imagen. Se utiliza para instalar paquetes en un contenedor.COPY
: copia archivos y carpetas en el contenedor.ADD
: copia archivos y carpetas en un contenedor, puede descomprimir archivos locales .tar.CMD
: describe un comando con argumentos que debe ejecutarse cuando se inicia el contenedor. Los argumentos pueden anularse cuando se inicia el contenedor. Un archivo puede contener solo una instrucción CMD
.WORKDIR
: establece el directorio de trabajo para la siguiente instrucción.ARG
: establece variables para pasar Docker durante la creación de la imagen.ENTRYPOINT
: proporciona un comando con argumentos para invocar durante la ejecución del contenedor. Los argumentos no se anulan.EXPOSE
: indica la necesidad de abrir el puerto.VOLUME
: crea un punto de montaje para trabajar con almacenamiento persistente.
Ahora hablemos de estas instrucciones.
Instrucciones y ejemplos de su uso.
▍Simple Dockerfile
Dockerfile puede ser extremadamente simple y corto. Por ejemplo, así:
FROM ubuntu:18.04
▍De la instrucción
El Dockerfile debe comenzar con una declaración
FROM
, o con una declaración
ARG
seguida de una declaración
FROM
.
La palabra clave
FROM le dice a Docker que use una imagen base que coincida con el nombre y la etiqueta proporcionados al crear la imagen. La imagen básica, además, también se llama
imagen principal .
En este ejemplo, la imagen base se almacena en el repositorio de
ubuntu . Ubuntu es el nombre del repositorio oficial de Docker, que proporciona la versión base de la popular familia de sistemas operativos Linux llamada Ubuntu.
Tenga en cuenta que el Dockerfile en cuestión incluye una etiqueta
18.04
que especifica qué imagen base necesitamos. Es esta imagen la que se cargará al construir nuestra imagen. Si la etiqueta no está incluida en las instrucciones, Docker parte de la suposición de que se requiere la última imagen del repositorio. Para expresar más claramente sus intenciones, se recomienda que el autor de Dockerfile indique qué imagen necesita.
Cuando el Dockerfile anterior se usa en la máquina local para construir la imagen por primera vez, Docker cargará las capas definidas por la imagen de
ubuntu
. Se pueden imaginar superpuestos entre sí. Cada capa siguiente es un archivo que describe las diferencias de la imagen en comparación con el estado en que se encontraba después de agregarle la capa anterior.
Cuando crea un contenedor, se agrega una capa en la que puede realizar cambios sobre todas las demás capas. Los datos en las capas restantes solo se pueden leer.
Estructura del contenedor (tomada de la documentación )Docker, en aras de la eficiencia, utiliza una estrategia de copia en escritura. Si la capa en la imagen existe en el nivel anterior y alguna capa necesita leer datos de ella, Docker usa el archivo existente. No necesitas descargar nada.
Cuando se ejecuta la imagen, si la capa necesita ser modificada por medio del contenedor, entonces el archivo correspondiente se copia en la capa superior mutable. Para obtener más información sobre la estrategia de copiar y escribir, eche un vistazo a
este material de la documentación de Docker.
Continuamos la discusión de las instrucciones utilizadas en el Dockerfile, dando un ejemplo de dicho archivo con una estructura más compleja.
▍Dockerfile más sofisticado
Aunque el Dockerfile que acabamos de revisar resultó ser ordenado y comprensible, es demasiado simple, solo utiliza una instrucción. Además, no hay instrucciones invocadas durante la ejecución del contenedor. Eche un vistazo a otro archivo que recopila una imagen pequeña. Tiene mecanismos que determinan los comandos que se invocan durante la ejecución del contenedor.
FROM python:3.7.2-alpine3.8 LABEL maintainer="jeffmshale@gmail.com" ENV ADMIN="jeff" RUN apk update && apk upgrade && apk add bash COPY . ./app ADD https://raw.githubusercontent.com/discdiver/pachy-vid/master/sample_vids/vid1.mp4 \ /my_app_directory RUN ["mkdir", "/a_directory"] CMD ["python", "./my_script.py"]
Quizás a primera vista este archivo puede parecer bastante complicado. Por lo tanto, tratemos con él.
La base de esta imagen es la imagen oficial de Python con la etiqueta 3.7.2-alpine3.8. Después de analizar
este código, puede ver que esta imagen básica incluye Linux, Python y, en general, se limita a su composición. Las imágenes de Alpine OS son muy populares en el mundo Docker. El hecho de que son de tamaño pequeño, alta velocidad y seguridad. Sin embargo, las imágenes Alpine no difieren en las amplias capacidades típicas de los sistemas operativos convencionales. Por lo tanto, para recopilar algo útil sobre la base de dicha imagen, el creador de la imagen necesita instalar los paquetes que necesita.
▍ ETIQUETA de instrucciones
EtiquetasLa
declaración LABEL (etiqueta) le permite agregar metadatos a la imagen. En el caso del archivo bajo consideración ahora, incluye la información de contacto del creador de la imagen. La declaración de etiquetas no ralentiza el proceso de ensamblaje de la imagen ni aumenta su tamaño. Solo contienen información útil sobre la imagen de Docker, por lo que se recomienda que se incluyan en el archivo. Los detalles sobre cómo trabajar con metadatos en el Dockerfile se pueden encontrar
aquí .
▍Inv instrucciones
Medio ambienteLa instrucción
ENV le permite establecer variables de entorno constantes que estarán disponibles en el contenedor durante su ejecución. En el ejemplo anterior, después de crear el contenedor, puede usar la variable
ADMIN
.
La instrucción
ENV
es adecuada para establecer constantes. Si usa un cierto valor en el Dockerfile varias veces, por ejemplo, cuando describe los comandos que se ejecutan en el contenedor, y sospecha que algún día tendrá que cambiarlo a otro, tiene sentido escribirlo en una constante similar.
Cabe señalar que en los archivos Dockerfile a menudo hay diferentes formas de resolver los mismos problemas. Lo que se debe utilizar exactamente es una pregunta, cuya decisión se ve afectada por el deseo de cumplir con los métodos de trabajo adoptados en el entorno de Docker, para garantizar la transparencia de la solución y su alto rendimiento. Por ejemplo, las
ENTRYPOINT
RUN
,
CMD
y
ENTRYPOINT
sirven para diferentes propósitos, pero todas se usan para ejecutar comandos.
▍ instrucción de EJECUTAR
Instrucción RUNLa instrucción
EJECUTAR le permite crear una capa durante la creación de la imagen. Después de su ejecución, se agrega una nueva capa a la imagen, su estado es fijo. La instrucción
RUN
se usa a menudo para instalar paquetes adicionales en imágenes. En el ejemplo anterior, la declaración
RUN apk update && apk upgrade
le dice a Docker que el sistema necesita actualizar los paquetes desde la imagen base. Después de estos dos comandos está el comando
&& apk add bash
, que indica que bash debe instalarse en la imagen.
Lo que parece
apk
en equipos es una abreviatura de
Alpine Linux package manager . Si está usando la imagen base de algún otro sistema operativo de la familia Linux, entonces, por ejemplo, cuando usa Ubuntu, es posible que necesite un comando del formulario
RUN apt-get
para instalar paquetes. Más adelante hablaremos sobre otras formas de instalar paquetes.
La instrucción
RUN
y otras instrucciones similares, como
CMD
y
ENTRYPOINT
, se pueden usar en forma ejecutiva o en forma de shell. El formulario exec utiliza una sintaxis que se parece a la descripción de una matriz JSON. Por ejemplo, podría verse así:
RUN ["my_executable", "my_first_param1", "my_second_param2"]
.
En el ejemplo anterior, utilizamos la forma de shell de la instrucción RUN de la siguiente manera:
RUN apk update && apk upgrade && apk add bash
.
Más adelante en nuestro Dockerfile, usamos la forma ejecutiva de la instrucción
RUN
, en forma de
RUN ["mkdir", "/a_directory"]
para crear un directorio. Al mismo tiempo, siguiendo las instrucciones de este formulario, debe recordar la necesidad de formatear cadenas con comillas dobles, como es habitual en el formato JSON.
▍Instrucción COPIA
Instrucción COPIALa instrucción
COPY se presenta en nuestro archivo así:
COPY . ./app
COPY . ./app
. Ella le dice a Docker que necesita tomar archivos y carpetas del contexto local del ensamblaje y agregarlos al directorio de trabajo actual de la imagen. Si el directorio de destino no existe, esta instrucción lo creará.
▍Instrucción ADD
La instrucción
ADD le permite resolver los mismos problemas que
COPY
, pero hay otros dos
COPY
uso asociados. Entonces, usando esta instrucción, puede agregar archivos descargados de fuentes remotas al contenedor, así como descomprimir archivos .tar locales.
En este ejemplo, la instrucción
ADD
se usó para copiar un archivo accesible por URL en el
my_app_directory
contenedor
my_app_directory
. Sin embargo, debe tenerse en cuenta que la
documentación de Docker no recomienda el uso de dichos archivos obtenidos por URL, ya que no pueden eliminarse y aumentan el tamaño de la imagen.
Además, la
documentación sugiere, siempre que sea posible, que utilice la instrucción
COPY
lugar de la instrucción
ADD
para que Dockerfile sea más fácil de entender. Creo que el equipo de desarrollo de Docker debe combinar
ADD
y
COPY
en una sola instrucción para que quienes crean las imágenes no tengan que recordar demasiadas instrucciones.
Tenga en cuenta que la instrucción
ADD
contiene el carácter de salto de línea -
\
. Dichos caracteres se utilizan para mejorar la legibilidad de los comandos largos al dividirlos en varias líneas.
▍ instrucción CMD
Instrucción CMDLa instrucción
CMD proporciona a Docker un comando para ejecutar cuando se inicia el contenedor. Los resultados de este comando no se agregan a la imagen durante su ensamblaje. En nuestro ejemplo, este comando inicia el script
my_script.py
en tiempo de ejecución.
Aquí hay algo más que necesita saber sobre la instrucción
CMD
:
- Solo una instrucción
CMD
puede estar presente en un Dockerfile. Si hay varias instrucciones de este tipo en el archivo, el sistema ignorará todo excepto el último. - Una instrucción
CMD
puede tener una forma ejecutiva. Si la instrucción no incluye la referencia al archivo ejecutable, entonces la instrucción ENTRYPOINT
debe estar presente en el archivo. En este caso, ambas instrucciones deben estar en JSON
. - Los argumentos de la línea de comandos pasados a
docker run
anulan los argumentos proporcionados por la instrucción CMD
en el Dockerfile.
▍Un Dockerfile aún más complejo
Considere otro Dockerfile, en el que se usarán algunos comandos nuevos.
FROM python:3.7.2-alpine3.8 LABEL maintainer="jeffmshale@gmail.com" # RUN apk add --update git # WORKDIR /usr/src/my_app_directory # COPY . . # ARG my_var=my_default_value # , ENTRYPOINT ["python", "./app/my_script.py", "my_var"] # EXPOSE 8000 # VOLUME /my_volume
En este ejemplo, entre otras cosas, puede ver comentarios que comienzan con el carácter
#
.
Una de las cosas principales que hace Dockerfile es instalar paquetes. Como ya se mencionó, hay varias formas de instalar paquetes utilizando la instrucción
RUN
.
Los paquetes en la imagen Alpine Docker se pueden instalar usando
apk
. Para esto, como ya dijimos,
RUN apk update && apk upgrade && apk add bash
un comando del formulario
RUN apk update && apk upgrade && apk add bash
.
Además, los paquetes de Python en la imagen se pueden instalar usando
pip ,
wheel y
conda . Si no estamos hablando de Python, sino de otros lenguajes de programación, se pueden usar otros administradores de paquetes para preparar las imágenes correspondientes.
Al mismo tiempo, para que la instalación sea posible, la capa subyacente debe proporcionar al administrador de paquetes un administrador de paquetes adecuado. Por lo tanto, si tiene problemas para instalar paquetes, asegúrese de que el administrador de paquetes esté instalado antes de intentar usarlo.
Por ejemplo, puede usar la instrucción
RUN
en un Dockerfile para instalar una lista de paquetes usando
pip
. Si hace esto, combine todos los comandos en una sola instrucción y sepárelos con caracteres de salto de línea usando el carácter
\
. Gracias a este enfoque, los archivos se verán limpios y esto llevará a agregar menos capas a la imagen de las que se agregarían usando varias instrucciones de
RUN
.
Además, puede hacer diferentes cosas para instalar varios paquetes. Puede enumerarlos en un archivo y transferir este archivo al administrador de paquetes usando
RUN
. Por lo general, estos archivos se denominan
requirements.txt
.
▍ Instrucción WORKDIR
Directorios de trabajoLa instrucción
WORKDIR le permite cambiar el directorio de trabajo del contenedor. Las
ENTRYPOINT
COPY
,
ADD
,
RUN
,
CMD
y
ENTRYPOINT
que siguen a
WORKDIR
funcionan con este directorio. Estas son algunas características relacionadas con esta instrucción:
- Es mejor establecer rutas absolutas a las carpetas con
WORKDIR
lugar de navegar por el sistema de archivos utilizando los comandos de cd
en el Dockerfile. - La instrucción
WORKDIR
crea automáticamente un directorio si no existe. - Puede usar varias instrucciones de
WORKDIR
. Si se proporcionan instrucciones relativas a dichas instrucciones, cada una de ellas cambia el directorio de trabajo actual.
▍Guide ARG
La instrucción
ARG le permite establecer una variable cuyo valor se puede pasar de la línea de comando a la imagen durante su ensamblaje. El valor de la variable predeterminada se puede representar en el Dockerfile. Por ejemplo:
ARG my_var=my_default_value
.
A diferencia de las variables
ENV
, las variables
ARG
no están disponibles en tiempo de ejecución. Sin embargo, las variables
ARG
se pueden usar para establecer valores predeterminados para las variables
ENV
desde la línea de comandos durante la creación de imágenes. Y las variables
ENV
ya estarán disponibles en el contenedor durante su ejecución. Los detalles sobre esta técnica de trabajar con variables se pueden encontrar
aquí .
▍PUNTO DE ENTRADA DE INSTRUCCIÓN
Punto de transición a algún lugar.La
instrucción ENTRYPOINT le permite especificar un comando con argumentos que deben ejecutarse cuando se inicia el contenedor. Es similar al comando
CMD
, pero los parámetros especificados en
ENTRYPOINT
no se sobrescriben si el contenedor se inicia con parámetros de línea de comando.
En cambio, los argumentos de línea de comando pasados en las construcciones de la
docker run my_image_name
formulario
docker run my_image_name
se agregan a los argumentos especificados por la
ENTRYPOINT
. Por ejemplo, después de ejecutar un comando del formulario
docker run my_image bash
argumento
docker run my_image bash
se agregará al final de la lista de argumentos especificada por
ENTRYPOINT
. Cuando prepare su Dockerfile, no olvide las
ENTRYPOINT
CMD
o
ENTRYPOINT
.
Hay varias recomendaciones en la documentación para Docker con respecto a qué instrucción,
CMD
o
ENTRYPOINT
, se debe elegir como herramienta para ejecutar comandos cuando se inicia el contenedor:
- Si necesita ejecutar el mismo comando cada vez que inicia el contenedor, use
ENTRYPOINT
. - Si el contenedor se usará como una aplicación, use
ENTRYPOINT
. - Si sabe que cuando inicia el contenedor, debe pasarle argumentos que puedan sobrescribir los argumentos especificados en el Dockerfile, use
CMD
.
En nuestro ejemplo, el uso de la instrucción
ENTRYPOINT ["python", "my_script.py", "my_var"]
hace que el contenedor, cuando se inicia, ejecute el script Python
my_script.py
con el argumento
my_var
. El valor representado por
my_var
se puede usar en el script usando
argparse . , Dockerfile
my_var
, ,
ARG
. , , .
Docker exec-
ENTRYPOINT
:
ENTRYPOINT ["executable", "param1", "param2"]
.
▍ EXPOSE
EXPOSEEXPOSE , , . . , , , , , , .
( ) ,
docker run
-p
.
-P
(
P
), ,
EXPOSE
.
▍ VOLUME
VOLUMEVOLUME , . .
Resumen
, Dockerfile. . , ,
USER
,
ONBUILD
,
STOPSIGNAL
,
SHELL
HEALTHCHECK
.
Dockerfile.
, Dockerfile — Docker, , . , .
Estimados lectores! Docker , , Docker-.
