Saltar a contenido

Guía Completa de Dockerfile

Índice

Introducción

Un Dockerfile es un archivo de texto que contiene las instrucciones necesarias para construir una imagen de Docker. Cada instrucción en el Dockerfile crea una nueva capa en la imagen.

Sintaxis Básica

# Comentario
INSTRUCCIÓN argumentos
  • Las instrucciones no son sensibles a mayúsculas, pero por convención se escriben en mayúsculas
  • Cada instrucción crea una nueva capa en la imagen
  • Los comentarios comienzan con #

Instrucciones Principales

FROM

Define la imagen base.

1
2
3
FROM <imagen>:<tag>
FROM ubuntu:20.04
FROM node:14-alpine

LABEL

Agrega metadatos a la imagen.

1
2
3
LABEL version="1.0"
LABEL descripcion="Mi aplicación"
LABEL mantenedor="nombre@email.com"

ENV

Define variables de entorno.

ENV APP_HOME=/usr/src/app
ENV PORT=3000

ARG

Define variables para el proceso de construcción.

ARG VERSION=latest
ARG BUILD_DATE

WORKDIR

Establece el directorio de trabajo.

WORKDIR /app
WORKDIR $APP_HOME

COPY

Copia archivos desde el host a la imagen.

1
2
3
COPY archivo.txt /app/
COPY ["archivo con espacios.txt", "/app/"]
COPY . .

ADD

Similar a COPY, pero con funcionalidades adicionales.

ADD archivo.tar.gz /app/
ADD https://ejemplo.com/archivo.zip /app/

RUN

Ejecuta comandos durante la construcción.

1
2
3
RUN apt-get update && \
    apt-get install -y nginx
RUN ["npm", "install"]

CMD

Define el comando por defecto al ejecutar el contenedor.

1
2
3
CMD ["nginx", "-g", "daemon off;"]
CMD ["npm", "start"]
CMD /script.sh

ENTRYPOINT

Define el ejecutable principal del contenedor.

ENTRYPOINT ["nginx"]
ENTRYPOINT ["node", "app.js"]

EXPOSE

Documenta los puertos que escucha el contenedor.

1
2
3
EXPOSE 80
EXPOSE 3000/tcp
EXPOSE 53/udp

VOLUME

Define puntos de montaje para volúmenes.

VOLUME /data
VOLUME ["/data", "/logs"]

USER

Define el usuario para ejecutar comandos.

USER nginx
USER 1000:1000

HEALTHCHECK

Define comando para verificar la salud del contenedor.

HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost/ || exit 1

SHELL

Define el shell por defecto para comandos.

SHELL ["/bin/bash", "-c"]

STOPSIGNAL

Define la señal para detener el contenedor.

STOPSIGNAL SIGTERM

Variables y Arguments

Variables de Entorno

1
2
3
4
5
6
# Definición de variables
ENV APP_VERSION=1.0
ENV APP_PORT=3000

# Uso de variables
EXPOSE $APP_PORT

Build Arguments

1
2
3
4
5
6
# Definición de argumentos
ARG BUILD_VERSION
ARG ENVIRONMENT=production

# Uso de argumentos
LABEL version=${BUILD_VERSION}

Buenas Prácticas

1. Optimización de Capas

# Mal
RUN apt-get update
RUN apt-get install -y nginx
RUN apt-get clean

# Bien
RUN apt-get update && \
    apt-get install -y nginx && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

2. Multi-stage Builds

# Etapa de compilación
FROM node:14 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# Etapa de producción
FROM node:14-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
CMD ["node", "dist/main.js"]

3. Ordenamiento de Capas

# Ordenar de menos a más frecuentemente cambiante
FROM node:14-alpine

# 1. Instalar dependencias del sistema
RUN apk add --no-cache python3

# 2. Instalar dependencias de la aplicación
COPY package*.json ./
RUN npm install

# 3. Copiar código fuente
COPY . .

4. Uso de .dockerignore

1
2
3
4
5
6
# .dockerignore
node_modules
npm-debug.log
Dockerfile
.git
.gitignore

Ejemplos Prácticos

Aplicación Node.js

FROM node:14-alpine

# Metadatos
LABEL version="1.0.0"
LABEL description="Aplicación Node.js de ejemplo"

# Variables de entorno
ENV NODE_ENV=production
ENV PORT=3000

# Directorio de trabajo
WORKDIR /usr/src/app

# Instalación de dependencias
COPY package*.json ./
RUN npm ci --only=production

# Código fuente
COPY . .

# Puerto
EXPOSE $PORT

# Comando de inicio
CMD ["node", "server.js"]

Aplicación Python con Django

FROM python:3.9-slim

# Variables de entorno
ENV PYTHONUNBUFFERED=1
ENV DJANGO_SETTINGS_MODULE=myproject.settings

# Directorio de trabajo
WORKDIR /app

# Dependencias del sistema
RUN apt-get update && \
    apt-get install -y --no-install-recommends \
    gcc \
    postgresql-client \
    && rm -rf /var/lib/apt/lists/*

# Dependencias Python
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Código fuente
COPY . .

# Puerto
EXPOSE 8000

# Comando de inicio
CMD ["gunicorn", "myproject.wsgi:application", "--bind", "0.0.0.0:8000"]

Aplicación Java con Maven

# Etapa de compilación
FROM maven:3.8-openjdk-11 AS builder

WORKDIR /app
COPY pom.xml .
COPY src ./src

RUN mvn clean package -DskipTests

# Etapa de producción
FROM openjdk:11-jre-slim

WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar

EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

Variables Especiales

Variables Predefinidas

1
2
3
4
ARG
- ${}       # Referencia a variable
- $?        # Código de salida del último comando
- $$        # PID del shell actual

Variables en Tiempo de Construcción

1
2
3
4
5
6
7
ARG VERSION
ARG BUILD_DATE
ARG VCS_REF

LABEL org.label-schema.version=$VERSION
LABEL org.label-schema.build-date=$BUILD_DATE
LABEL org.label-schema.vcs-ref=$VCS_REF