Es un fichero de texto que contiene una serie de instrucciones para crear una imagen .
Este fichero tiene un formato concreto y necesita al menos la instrucción FROM para especificar la imagen base a partir de la cual construiremos nuestra imagen personalizada.
Dichas instrucciones van a personalizar la imagen según nuestras necesidades
Dichas instrucciones van a personalizar la imagen según nuestras necesidades
Objetivo del fichero DockerFile
Partiendo de una imagen, con las instrucciones que especifiquemos, vamos a personalizar la imagen quequeremos crear,
Después, a partir de esta imagen, levantaremos el contenedor)

Para ejecutar las instrucciones del Dockerfile, utilizamos el comando < color > docker build < /color >:
docker build [OPTIONS] PATH | URL | -Por ejemplo:
docker build -t web:v1 .El . es el contexto (archivos que Docker puede copiar). Build buscará en su contexto un fichero llamado Dockerfile, en este caso, buscaría en el directorio actual.
Con la opción < color > PATH < /color > se puede especificar la ubicación del Dockerfile.
< color > Si el fichero tiene otro nombre < /color > lo indicamos con la opción < color > -f < /color >.
Las imágenes de docker se construyen por capas
Cada instrucción genera una capa. Si cambias una, se invalidan las de debajo: Colocaremos las primeras instrucciones aquellas instalaciones que menos cambian
Instrucciones de clase
| Instrucción | Para qué |
|---|---|
| FROM | Imagen base. Primera instrucción real. |
RUN | Ejecuta comandos en el build, (en la construcción de la imagen) (instalar paquetes). |
COPY | Copiar del contexto a la imagen. Prefiérelo a ADD. |
ENV | Variables en build (en la construcción) y en el contenedor. |
ARG | Variables solo durante el build. |
EXPOSE | Documenta puertos; no los publica. (Instrucción declarativa) |
VOLUME | Documenta volúmenos; no los crea. (Instrucción declarativa) |
CMD / ENTRYPOINT | Proceso principal al arrancar (PID 1).Es el comando predeterminado del contenedor |
WORKDIR | Directorio de trabajo. |
El proceso principal del contenedor: PID 1
Un contenedor siempre tiene un proceso principal que se identifica con el PID1.
Es el sentido de su existencia, cuando ese proceso termina, el contenedor pasa a estado Exited
El contenedor, salvo que se especifique explíctamente, va a tener como PID1 el proceso que se indicado mediante las instrucciones CMD / ENTRYPOINT y, como hemos comentado determina su ciclo de vida:Un contenedor existe para ejecutar un proceso principal
Recuerda
Mientras el proceso principal está ejecutándose → el contenedor está Running.
Cuando el proceso principal termina → el contenedor pasa a Exited.
Para lanzar En el caso de Apache se lanza en primer plano, no con service apache2 start ya que eso haría que el contenedor no nos sirviese para nuestro objetivo:
CMD ["apache2ctl", "-D", "FOREGROUND"]En php:8.3-apache eso ya viene resuelto. Si construyes desde ubuntu, lo tienes que poner tú.
RUN y apt
apt-get update y el install en la misma capa, y al final rm -rf /var/lib/apt/lists/*, para no dejar caché inútil en la imagen.
Siguiente paso: no lanzar esto a mano cada vez, sino un Compose que haga build, puertos y volumen.
FROM
FROM ubuntu:latestEsta instrucción es obligatoria y debe ser la primera, salvo comentarios o ARG.
Especifica la imagen base de la que partimos
TIP
Intenta evitar usar versiones latest
RUN: Ejecución de comandos
Esta instrucción especifica una acción que se va a ejectuar dentro de la imagen que estamos construyendo
Es de las instrucciones más utilizada, y sirve para añadir paquetes a nuestra imagen
Instalación de paquetes
Lo primero que debemos hacer es ejecutar apt-get update, lo que actualiza la información de los repositorios para garantizar que conocemos las versiones de los paquetes disponibles.
Observa que se utiliza la opción -y para confirmar automáticamente las instalaciones, evitando la necesidad de interacción manual (dicha interacción no es posible, pues detendría la construcción de la imagen) durante la construcción de la imagen.
RUN apt-get update && apt-get install -y apache2
RUN apt-get install -y php git zipCada instrucción RUN genera una capa.
Modificar una capa afecta a las siguientes, por lo que conviene agrupar comandos relacionados para optimizar la construcción de la imagen.
Ejecución de scripts
También es posible ejecutar un script dentro de la imagen
RUN bash script.shDeclaración de variables: ENV y ARG
ENV
FROM ubuntu:latest
ENV USER=developer
RUN echo "Usuario actual: $USER"ARG
ARG VERSION=latest
FROM ubuntu:$VERSIONConstrucción con argumentos personalizados:
docker build --build-arg VERSION=20.04 -t mi_imagen .Ejemplo: Personalización con RUN
Podemos ejecutar comandos de administración, instalación y scripts predefinidos:
RUN mkdir -p /var/www/app && chown -R www-data:www-data /var/www/app
RUN apt-get update && apt-get install -y composer
RUN composer install --no-scripts --no-autoloaderPráctica sugerida: Crear un Dockerfile
- Partir de la imagen base
ubuntu:latest. - Instalar los paquetes necesarios:
apache2vimgitzip
FROM ubuntu:latest
RUN apt-get update && apt-get install -y apache2 vim git zipDeclaración de variables: ENV vs ARG

Diferencias clave:
ENV: define variables de entorno que quedan disponibles en la imagen y, por defecto, en los contenedores creados a partir de ella.ARG: define argumentos disponibles durante la construcción de la imagen.
Ejemplo de uso: ARG
ARG VERSION=latest
FROM ubuntu:$VERSIONConstrucción personalizada:
docker build --build-arg VERSION=18.10 -t web:v1 .Ejemplo de uso: ENV
FROM ubuntu:latest
ENV USER=manuel
RUN echo "Usuario configurado: $USER"Solución de problemas: Instalación de PHP
Problema
Al instalar determinados paquetes puede solicitarse información de forma interactiva, como la configuración de la zona horaria. Esto puede interrumpir la construcción de la imagen.

Solución
Configurar el entorno en modo no interactivo:
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y php libapache2-mod-phpConfigurar la zona horaria:
RUN ln -snf /usr/share/zoneinfo/Europe/Madrid /etc/localtime && \
echo "Europe/Madrid" > /etc/timezoneEtiquetas (LABEL)
Podemos agregar metadatos útiles a la imagen:
FROM ubuntu:latest
LABEL maintainer="example@example.com"
LABEL version="1.0"
LABEL description="Imagen personalizada para aplicaciones web"Podemos consultar las etiquetas mediante:
docker inspect --format '{{.Config.Labels}}' container_nameGestión de archivos: COPY y ADD
Ejemplo: Crear usuarios desde un script
Archivos necesarios:
usuarios.txt:
maria
nives
luis
lourdes
manuelcrea_usuarios.sh:
while IFS= read -r line
do
useradd -m "$line"
done < usuarios.txtDockerfile:
FROM ubuntu:latest
COPY crea_usuarios.sh /
COPY usuarios.txt /
RUN bash /crea_usuarios.shPara copiar archivos locales utilizaremos normalmente
COPY.ADDtiene funcionalidades adicionales y no es necesario para este ejemplo.
Comandos: CMD y ENTRYPOINT
Ambas instrucciones están relacionadas con el comando que se ejecutará cuando se cree y arranque un contenedor a partir de la imagen.
CMD
CMD establece el comando por defecto.
CMD ["apache2ctl", "-D", "FOREGROUND"]Al ejecutar:
docker run mi_imagense ejecutará:
apache2ctl -D FOREGROUNDEl comando definido mediante CMD puede sustituirse fácilmente al crear el contenedor:
docker run mi_imagen bashEn este caso se ejecutará bash en lugar del CMD definido en la imagen.
ENTRYPOINT
ENTRYPOINT establece el ejecutable principal del contenedor.
ENTRYPOINT ["apache2ctl", "-D", "FOREGROUND"]Los parámetros que escribamos después del nombre de la imagen en docker run no sustituyen automáticamente el ENTRYPOINT, sino que se añaden como argumentos.
Para sustituir explícitamente el ENTRYPOINT podemos utilizar:
docker run --entrypoint bash mi_imagenUtilizar ENTRYPOINT y CMD conjuntamente
Podemos utilizar ambas instrucciones:
ENTRYPOINT ["apache2ctl"]
CMD ["-D", "FOREGROUND"]En este caso:
ENTRYPOINTestablece el ejecutable principal:apache2ctl.CMDestablece sus argumentos por defecto:-D FOREGROUND.
Por defecto:
docker run mi_imagenejecutará:
apache2ctl -D FOREGROUNDIdea clave:CMDestablece valores por defecto fácilmente sustituibles, mientras queENTRYPOINTfija el ejecutable principal del contenedor.
Volúmenes (VOLUME)
VOLUME declara un directorio de la imagen como punto destinado a almacenar datos fuera de la capa escribible del contenedor.
FROM ubuntu:latest
VOLUME ["/data"]También podemos utilizar una variable de entorno:
ENV WEB_DIR=/var/www/html
VOLUME $WEB_DIRImportante:VOLUMEno especifica qué directorio del host queremos montar. Los bind mounts, por ejemplo./app:/var/www/html, se especifican al crear el contenedor o mediante Docker Compose.
Directorio de trabajo (WORKDIR)
WORKDIR establece el directorio de trabajo para las instrucciones posteriores del Dockerfile y para el proceso que se ejecute al iniciar el contenedor.
FROM ubuntu:latest
WORKDIR /var/www/html
COPY script.sh .
CMD ["bash", "script.sh"]A partir de WORKDIR, las rutas relativas se interpretan respecto a /var/www/html.
Exponer puertos (EXPOSE)
EXPOSE documenta los puertos en los que la aplicación del contenedor espera recibir conexiones.
FROM ubuntu:latest
ENV WEB_PORT=80
EXPOSE $WEB_PORTImportante:EXPOSEno publica el puerto en el host. Para publicarlo utilizaremos, por ejemplo,docker run -p 8080:80 ...o la secciónportsde Docker Compose.
Conclusión
- Sabemos crear imágenes personalizadas mediante un
Dockerfile. - Sabemos utilizar instrucciones como
FROM,RUN,COPY,ENV,ARGyWORKDIR. - Entendemos la diferencia entre
CMDyENTRYPOINT. - Sabemos para qué sirve
VOLUMEy su diferencia respecto a un bind mount. - Entendemos que
EXPOSEdocumenta un puerto, pero no lo publica. - Entendemos que el proceso principal determina el ciclo de vida del contenedor.