
Bones pràctiques per a escriure Dockerfiles: guia per a desenvolupadors
Consells per a desenvolupadors que escriuen Dockerfiles: WORKDIR, multi-stage, imatges base, ARG i ENV, ENTRYPOINT i CMD, descàrregues i .dockerignore.
Per Víctor Piles TemporalSRE i tècnic de sistemesPublicat el 5 min de lectura
Un Dockerfile és un fitxer de text amb les instruccions per a construir una imatge nova. Docker tracta cada instrucció que llegeix del fitxer com una capa diferent, que es pot compartir completament amb altres receptes.
En resum: treballeu sempre sobre un WORKDIR, separeu la compilació amb multi-stage builds perquè la imatge final porte només el necessari, creeu imatges base amb les vostres dependències, useu ARG i ENV perquè les receptes siguen reutilitzables, enteneu la diferència entre ENTRYPOINT i CMD, descarregueu els paquets externs amb curl en lloc d’ADD i excloeu amb .dockerignore tot el que no calga.
Desenvolupadors i Dockerfiles
Si sou desenvolupadors, conéixer bé Docker és imprescindible. Hui repasse diversos consells útils per a escriure Dockerfiles.
Qui ha de generar les imatges, els desenvolupadors o l’equip de DevOps?
En aquest debat ho tinc clar: al meu parer, els desenvolupadors. Són els qui coneixen les dependències i les necessitats del seu codi.
Com a DevOps/SRE m’agrada donar un cop de mà, i espere que amb aquests consells pugau generar imatges més estables i de més qualitat.
Bones pràctiques per a escriure Dockerfiles
Definiu el directori de treball i treballeu-hi
Docker treballa sobre el WORKDIR, així que no cal indicar rutes absolutes en copiar si no són estrictament necessàries.
FROM php:8.3-apache
WORKDIR /app
COPY . .
En aquest cas es copia tot el directori actual (PWD) a la ruta /app de la imatge.
Useu multi-stage builds per a copiar només les capes necessàries entre imatges
- Amb aquest mètode podeu treballar només amb Docker: no necessiteu cap dependència instal·lada al vostre equip. El multi-stage ho fa per vosaltres, i així és molt més fàcil provar diferents versions de les eines que useu.
- Declareu en passos xicotets tot el cicle de compilació del vostre codi: queda molt més declaratiu i funcional.
- En l’exemple següent es generen imatges intermèdies per a construir una última imatge amb els estàtics que se serviran.
FROM node:latest AS install
WORKDIR /app
COPY . .
RUN npm install
#-----------#
FROM install AS build
RUN npm run build
#-----------#
FROM nginx:alpine AS standalone
WORKDIR /usr/share/nginx/html
COPY --from=build --chown=nginx:nginx /app/build .
En aquest cas es generen dues imatges temporals on s’instal·la tot el necessari i es compila el codi, i l’última imatge serveix només els estàtics.
Compileu una imatge amb totes les dependències i useu-la com a base per a la resta d’aplicacions
Dockerfile-base (construïu-la amb una etiqueta com base-php):
FROM php:8.3-apache
COPY php.ini-production $PHP_INI_DIR/php.ini
RUN a2enmod alias
Dockerfile:
FROM base-php
WORKDIR /var/www/html
COPY . .
En aquest cas es genera una imatge base amb totes les dependències.
Useu arguments per a generar receptes reutilitzables
ARG BASE_IMAGE
FROM $BASE_IMAGE
ARG FILE
WORKDIR /app
COPY --chmod=600 $FILE .
Compileu-la amb l’ordre següent:
docker build --build-arg BASE_IMAGE=alpine \
--build-arg FILE=deploy.yml .
En aquest cas els arguments serveixen per a generar receptes que es poden compartir.
Instal·lació de paquets
Aquesta és una instrucció ben formada per a instal·lar tot el necessari:
FROM ubuntu:24.04
RUN apt-get update && apt-get install -y \
nodejs \
python3 \
python3-pip \
curl \
&& rm -rf /var/lib/apt/lists/*
En aquest cas s’instal·len totes les dependències d’una manera ben estructurada.
Definir variables dins de la recepta no és una mala pràctica
Useu les variables que la vostra aplicació necessita conéixer per a compilar correctament.
FROM node:latest
ARG PUBLIC_URL
ENV URL=$PUBLIC_URL
RUN npm run build
Per a compilar aquesta recepta, executeu l’ordre següent:
docker build --build-arg PUBLIC_URL=test-dev .
En aquest cas s’usen variables d’entorn per a compilar el codi.
Com usar ENTRYPOINT i CMD
Les dues instruccions serveixen per a executar ordres quan arrenca el contenidor:
- ENTRYPOINT: el que executa el contenidor en arrencar.
- CMD: arguments que s’afegeixen a l’
ENTRYPOINT, o una ordre puntual que s’executa al contenidor.
FROM alpine
ENTRYPOINT ["sleep"]
CMD ["10"]
FROM alpine
WORKDIR /usr/local/bin/
COPY docker-entrypoint.sh .
RUN chmod +x docker-entrypoint.sh
ENTRYPOINT [ "sh", "/usr/local/bin/docker-entrypoint.sh" ]
En aquests casos s’usen ENTRYPOINT i CMD per a executar ordres en arrencar els contenidors.
Deixeu que Docker descarregue els paquets externs necessaris
Potser heu usat abans la instrucció ADD per a això. Per a obtindre paquets des d’URL remotes està molt desaconsellada: si els descarregueu vosaltres en un RUN, podeu esborrar en el mateix pas els fitxers que ja no necessiteu.
FROM alpine
RUN apk add --no-cache curl \
&& curl -SL https://example.com/test.tar.gz | tar -xz
En aquest cas s’usa curl per a descarregar els paquets externs, sense la instrucció ADD que usa tothom.
Useu .dockerignore
Pugeu només el que necessiteu i excloeu tots els fitxers que no cal enviar. La lògica és la mateixa que la de .gitignore.
commands
node_modules
public
scripts
src*
.yml*
.yaml
.env*
.git*
.json
yarn.lock
...
Segona part
Aquests són els bàsics. En la segona part parle de comprovacions de salut (HEALTHCHECK), de la sintaxi heredoc i dels muntatges de BuildKit per a secrets i claus SSH.
Si voleu que aquestes pràctiques s’apliquen de manera automàtica en els vostres desplegaments, en infraestructura com a codi, GitOps i CI/CD explique com munte els pipelines que construeixen les imatges, i en gestió de vulnerabilitats com les escanege. Si necessiteu alguna cosa, escriviu-me des de contacte.
Publicat originalment en anglés a Medium.


