[Docker SecDevOps] Capítulo 2 : Dockerfile
#
comentarios o directivas
INSTRUCCIÓN argumentos
: por convención, instrucción en mayúsculas
primera instrucción: FROM (o ARG)
build
directivas
antes de la instrucción FROM
no repeticiones
formato concreto: # directiva=valor
(respetando espacios) → si no, es tratado como un comentario
directivas soportadas actualmente:
ENV
variables de entorno
ENV var=valor
ENV var=valor var2=valor2 var3=$var2
← produce una única capa de caché
ENV var valor
se referencian con el signo $ o ${}
funcionalidades tipo bash:
${var:-texto} : si var tiene valor propio (está inicializada) lo devuelve, si no, devuelve texto
${var:+texto} : si var tiene valor propio, devuelve la cadena texto, si no, devuelve vacío
se pueden usar en:
ADD
COPY
ENV
EXPOSE
FROM
ONBUILD
LABEL
STOPSIGNAL
USER
VOLUME
WORKDIR
son de tipo global (afecta a todas las imágenes que desciendan donde fueron definidas)
también llegan al contenedor
se pueden sobrescribir con el parámetro –env en docker run
.dockerignore
se procesa al mismo tiempo que se procesa el contexto en el build de una imagen
ignora todos los archivos / directorios que estén especificados
uso de comodines: *, ?, !
comentarios: #
importancia del orden de criterio de exclusión:
*.md
!README.md
*.md
!README*.md
README-secret.md
*.md
README-secret.md
!README*.md
el primer ejemplo excluye todos los ficheros .MD excepto el README.md
el segundo excluye todos los ficheros .MD excepto los README*.md, aunque el README-secret.md también quedaría excluido
el tercer ejemplo es una mala construcción por el orden de las instrucciones, ya que el fichero README-secret.md quedaría incluido, cuando lo que pretendemos es excluirlo
se puede excluir Dockerfile también, pero solo se ignorará en las instrucciones COPY y ADD
FROM
multistage
uso de más de una imagen Docker para realizar la tarea
uso de 2 o más FROM en el Dockerfile
la imagen del último FROM es la que prevalece, todas las anteriores son descartadas
es posible «traspasar» ficheros de un fase a otra con un parámetro en el comando COPY
RUN
ejecución de comandos en la imagen que estamos construyendo
RUN <comando>
→ comando es pasado como parámetro a la shell del sistema:
linux: /bin/sh -c
windows: cmd /s /c
RUN [«ejecutable»,«parámetro1»,«parámetro2»]
cada RUN genera una layer(capa)
uso de | (pipe) para redirigir la salida de un ejecutable a otro
tener en cuenta que si falla la ejecución del primero, pero no del segundo, la ejecución se dará por buena
se puede usar set -o pipefail
para evitar este comportamiento (aunque no todos los shell lo soportan)
RUN [«/bin/bash», «-c»,«set -o pipefail && wget …»]
CMD
ejecución en tiempo de creación del container
proveer de valores por defecto
los parámetros se pasarían a ENTRYPOINT
entre esos valores se puede incluir un ejecutable
3 formas:
CMD [«ejecutable»,«param1»,«param2»]
CMD [«param1»,«param2»,«param3»]
← parámetros añadidos a ENTRYPOINT (también debe estar expresado como vector JSON)
CMD comando param1 param2
← el comando se ejecuta a través de la shell
para asegurarse la ejecución de un programa hay que combinar ENTRYPOINT con CMD
si se pasan parámetros en el docker run, estos sobreescriben los especifiados en el CMD
ENTRYPOINT
es el comando recomendable para definir el comando principal de una imagen
LABEL
añade metadatos a una imagen
LABEL key=value [key2=value2]
se pueden crear varias etiquetas o una única separando valores
etiquetas con el mismo nombre, prevalece la última
EXPOSE
indica puertos y protocolos donde escuchará el contenedor
ADD
copia ficheros, directorios o ficheros remotos al directorio de destino en la imagen docker
ADD <src>… <dest>
ADD [«<src>»,… «<dest>»]
: obligatorio en el caso de que algún elemento contenga espacios
origen puede ser absoluto o relativo al contexto
destino puede ser absoluto o relativo al WORKDIR
origen permite caracteres comodín usando las reglas de filepath.Match del lenguaje Go: *, ?
si origen está en un formato de compresión reconocido (gzip,bzip,xz) se descomprime automáticamente en destino
si origen es una
URL a un archivo comprimido, no se descomprime, solo se copia.
si se especifican múltiples orígenes o comodines, destino ha de ser directorio (y acabar en /)
si destino no existe, se creará, con los directorios intermedios necesarios
todos los ficheros y directorios serán creados con UID/GID 0
en caso de URLs a ficheros remotos, los permisos se establecen a 600
COPY
copiar ficheros y directorios
VOLUME
crea un punto de montaje con el nombre dado
VOLUME <path> [<path>…]
VOLUME [«<path>» [, «<path>»]]
Los volúmenes se montan en tiempo de ejecución del contenedor
en ese momento se le puede indicar a Docker donde montarlo:
con el parámetro -v
o –volume
o –mount
especificando un directorio local
sin parámetro, ubica el volumen en /var/lib/docker/volumes/<nombre_volumen>/_data
USER
establece el usuario (UID) y grupo (GID) del usuario que ejecuta los comandos de las instrucciones RUN, CMD, ENTRYPOINT
USER <user>
USER <UID>
USER <UID>[:<GID>]
por defecto se ejecutan como root
se puede usar más de una vez en el mismo Dockerfile, aunque se recomienda minimizar su uso por su repercusión en las capas de la imagen
también se puede usar sudo, aunque se desaconseja su uso (por temas relacionados con el envío de señales y la emulación de termianles) → recomendado gosu
también se puede especificar el usuario en el momento de ejecución del contenedor con el parámetro -u
o –user
WORKDIR
establece el directorio de trabajo para los comandos RUN, CMD, ENTRYPOINT, COPY, ADD
WORKDIR <path>
← sin / final
el directorio es creado inmediatemente
pueden ser absolutos (recomendado) o relativos (al último WORKDIR)
ARG
variables que el usuario puede usar durante el build de la imagen
BUILD var=valor
también se pueden pasar como parámetro en docker build con –build-arg var=valor
solo sobreviven en la fase en las que son definidas
ENV tiene preferencia sobre ARG
existe un conjunto de variables definidas:
ONBUILD
trigger que se ejecuta cuando la imagen es usada como base para otra imagen
ONBUILD <instrucción>
no se pueden anidar 2 ONBUILD
se pueden poner varios ONBUILD y serán ejecutados en el mismo orden
se aplica en el primer nivel «de herencia»
reutilización de una imagen «base»
STOPSIGNAL
define la señal que se enviará al contenedor cuando este se pare
HEALTHCHECK
comunicar el estado de un contenedor en tiempo de ejecución
HEALTHCHECK NONE
: deshabilita healthcheck heredados
HEALTHCHECK [OPCIONES] CMD comando
opciones:
–interval=ns
: segundos con los que se ejecuta el comando de chequeo. 30s por defecto
–timeout=ns
: tiempo de espera para la ejecución del chequeo. 30s por defecto.
–start-period=ns
: tiempo que necesita el contenedor para arrancar. Los chequeos en este período no se consideran erróneos
–retries=N
: número de reintentos antes de considerar el contenedor como fallido
comando:
comando de terminal o array JSON (como en CMD/ENTRYPOINT)
el código de salida indica el estado del contenedor:
0 - success
1 - unhealthy
2 - reserved (no usar)
la salida del comando - en fase de depuración - se puede consultar a través de docker container inspect
(4096 bytes)
solo puede haber 1 HEALTCHECK en el fichero Dockerfile, así que el último prevalece (permitiendo sobreescribir alguno heradado)
SHELL
indica que shell será usada por defecto
SHELL [«ejecutable»,«parámetros»]
por defecto:
LINUX: SHELL [«/bin/sh»,«-c»]
WINDOWS: SHELL [«cmd»,«/S»,«/C»]
se puede usar varias veces en el Dockerfile y las instrucciones que precisen de un shell usarán el establecido en ese momento
afecta a CMD, ENTRYPOINT, RUN