Salta al contingut
Tècnic assegut davant de dos monitors amb codi i un terminal oberts

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.

Tornar al blog

Expliqueu-nos el vostre cas

En una trucada gratuïta de 20 minuts veiem on sou i per on començar. Sense compromís.

Reservar una trucada de 20 minuts
WhatsApp