Contenido
Tutorial de docker init: genera Dockerfile y compose.yaml automáticamente
Para quienes empiezan, lo más difícil de escribir un Dockerfile es «no saber por dónde empezar». docker init detecta el lenguaje del proyecto, te hace unas preguntas y genera un conjunto de archivos de Docker listos para usar. En esta sección probamos todo el proceso con un proyecto Express de Node.js y revisamos línea por línea lo que genera.
docker inites un complemento incluido en Docker Desktop. Los hosts Linux que solo tienen Docker Engine no incluyen este comando, pero los archivos generados se pueden usar en cualquier entorno.
Prepara el proyecto
La carpeta init-demo solo contiene tres archivos y todavía no tiene ningún archivo relacionado con Docker:
init-demo/
├── package.json
├── package-lock.json
└── server.js
server.js es una aplicación Express que escucha en el puerto 3000. Su contenido es el mismo que el de la aplicación de Node.js.
Ejecuta docker init
Ejecuta el comando en la carpeta del proyecto:
$ docker init
Welcome to the Docker Init CLI!
This utility will walk you through creating the following files with sensible defaults for your project:
- .dockerignore
- Dockerfile
- compose.yaml
- README.Docker.md
Let's get started!
? What application platform does your project use? [Use arrows to move, type to filter]
> Node - (detected) suitable for a Node server application
Go - suitable for a Go server application
Python - suitable for a Python server application
Rust - suitable for a Rust server application
ASP.NET Core - suitable for an ASP.NET Core application
PHP with Apache - suitable for a PHP web application
Java - suitable for a Java application that uses Maven and packages as an uber jar
Other - general purpose starting point for containerizing your application
Don't see something you need? Let us know!
Quit
docker init detectó package.json, marcó Node como (detected) y lo seleccionó automáticamente. Usa las teclas de dirección para elegir y pulsa Enter para confirmar. A continuación, te preguntará lo siguiente, en orden:
? What application platform does your project use? Node
? What version of Node do you want to use? 24
? Which package manager do you want to use? npm
? What command do you want to use to start the app? npm start
? What port does your server listen on? 3000
✔ Created → .dockerignore
✔ Created → Dockerfile
✔ Created → compose.yaml
✔ Created → README.Docker.md
→ Your Docker files are ready!
Review your Docker files and tailor them to your application.
Consult README.Docker.md for information about using the generated files.
What's next?
Start your application by running → docker compose up --build
Your application will be available at http://localhost:3000
| Pregunta | Respuesta en este ejemplo | Descripción |
|---|---|---|
| application platform | Node | Se detectó package.json; pulsa Enter directamente |
| version of Node | 24 | No hay valor predeterminado, debes introducirlo; de lo contrario, aparece Value is required |
| package manager | npm | Se detectó package-lock.json; npm es el valor predeterminado |
| command to start the app | npm start | El valor predeterminado se toma de scripts.start en package.json |
| port | 3000 | El puerto en el que escucha la aplicación; no hay valor predeterminado |
Si pulsas Enter sin introducir la versión de Node, verás lo siguiente:
? What application platform does your project use? Node
X Sorry, your reply was invalid: Value is required
? What version of Node do you want to use?
Si el proyecto contiene
.nvmrcoengines.nodeenpackage.json,docker initlos usará como valores predeterminados.
Al final se generan cuatro archivos: .dockerignore, Dockerfile, compose.yaml y README.Docker.md.
El Dockerfile generado
Este es el contenido sin los comentarios explicativos (el archivo original incluye comentarios en inglés en cada sección):
# syntax=docker/dockerfile:1
ARG NODE_VERSION=24
FROM node:${NODE_VERSION}-alpine
# Use production node environment by default.
ENV NODE_ENV production
WORKDIR /usr/src/app
RUN --mount=type=bind,source=package.json,target=package.json \
--mount=type=bind,source=package-lock.json,target=package-lock.json \
--mount=type=cache,target=/root/.npm \
npm ci --omit=dev
USER node
COPY . .
EXPOSE 3000
CMD npm start
| Sintaxis | Función |
|---|---|
# syntax=docker/dockerfile:1 | Usa la versión más reciente de la sintaxis de Dockerfile (durante la compilación primero descarga docker/dockerfile:1) |
ARG NODE_VERSION=24 | La versión se define en una variable; puedes cambiarla con --build-arg NODE_VERSION=22 |
--mount=type=bind,source=package.json | En vez de usar COPY, monta directamente package.json durante la compilación y evita una capa de imagen |
--mount=type=cache,target=/root/.npm | Comparte la caché de descargas de npm entre compilaciones, sin incluirla en la imagen |
npm ci --omit=dev | Instala solo los paquetes de producción |
USER node | Ejecuta la aplicación como usuario no root |
En general, ya cumple las buenas prácticas que se presentan en la aplicación de Node.js.
Comprueba con docker build --check
docker build --check solo comprueba la sintaxis del Dockerfile; no lo construye realmente. Ejecútalo sobre el Dockerfile generado:
$ docker build --check .
#0 building with "default" instance using docker driver
#1 [internal] load build definition from Dockerfile
#1 transferring dockerfile: 1.20kB done
#1 DONE 0.0s
#2 resolve image config for docker-image://docker.io/docker/dockerfile:1
#2 DONE 0.2s
#3 docker-image://docker.io/docker/dockerfile:1@sha256:4edf897a3ffa55b89f906fc8cc78afdb3f1834cc9c7083565e611a8a7d5fe99e
#3 resolve docker.io/docker/dockerfile:1@sha256:4edf897a3ffa55b89f906fc8cc78afdb3f1834cc9c7083565e611a8a7d5fe99e done
#3 CACHED
#4 [internal] load metadata for docker.io/library/node:24-alpine
#4 DONE 0.2s
#5 [internal] load .dockerignore
#5 transferring context: 663B done
#5 DONE 0.0s
Check complete, 2 warnings have been found!
WARNING: LegacyKeyValueFormat - https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/
"ENV key=value" should be used instead of legacy "ENV key value" format
Dockerfile:14
--------------------
12 |
13 | # Use production node environment by default.
14 | >>> ENV NODE_ENV production
15 |
16 |
--------------------
WARNING: JSONArgsRecommended - https://docs.docker.com/go/dockerfile/rule/json-args-recommended/
JSON arguments recommended for CMD to prevent unintended behavior related to OS signals
Dockerfile:38
--------------------
36 |
37 | # Run the application.
38 | >>> CMD npm start
39 |
--------------------
La plantilla tiene dos advertencias:
- LegacyKeyValueFormat:
ENV NODE_ENV productiones la sintaxis antigua; se recomienda usarENV NODE_ENV=production. - JSONArgsRecommended:
CMD npm startusa el formato shell; se recomienda usar el formato de matriz JSON, ya que de lo contrario puede afectar la transmisión de señales de detención. Consulta Instrucciones de Dockerfile.
Cambia estas dos líneas:
ENV NODE_ENV=production
CMD ["node", "server.js"]
Además, CMD ejecuta directamente node y elimina un proceso de npm. Para conocer el motivo, consulta las pruebas de Aplicaciones Node.js. docker build --check es muy útil para añadirlo al flujo de CI y detectar sintaxis problemática antes de la compilación.
El compose.yaml generado
Sin los comentarios, solo quedan unas pocas líneas:
services:
server:
build:
context: .
environment:
NODE_ENV: production
ports:
- 3000:3000
La mitad inferior del archivo original contiene un ejemplo de PostgreSQL completamente comentado. Si quieres descomentar y usarlo, ten en cuenta dos problemas:
# db:
# image: postgres
# ...
# volumes:
# - db-data:/var/lib/postgresql/data
# ...
# healthcheck:
# test: [ "CMD", "pg_isready" ]
image: postgresno especifica una versión, así que ahora se descarga la versión 18. El Volume de la versión 18 debe montarse en/var/lib/postgresql; si se monta en/var/lib/postgresql/data, el inicio falla. Consulta PostgreSQL.- A
pg_isreadyle falta-h 127.0.0.1; se marcará como healthy antes de que termine la inicialización de la base de datos.
.dockerignore y README.Docker.md
El .dockerignore generado excluye archivos comunes que no se necesitan, como **/node_modules, **/.env, **/.git, **/Dockerfile* y **/compose.y*ml. Es más completo que la versión escrita a mano anteriormente en este tutorial y puedes usarlo directamente.
README.Docker.md contiene una breve explicación en inglés sobre cómo iniciar con docker compose up --build y un recordatorio sobre la compilación para distintas arquitecturas de CPU (consulta Imágenes multiplataforma).
Inicio
Sigue las indicaciones y ejecuta docker compose up --build. Aquí añadimos -d para ejecutarlo en segundo plano y comprobamos el resultado:
$ docker compose up -d --build
[+] Building 15.1s (13/13) FINISHED
=> [internal] load local bake definitions 0.0s
=> => reading from stdin 486B 0.0s
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 1.20kB 0.0s
=> resolve image config for docker-image://docker.io/docker/dockerfile:1 1.1s
=> docker-image://docker.io/docker/dockerfile:1@sha256:4edf897a3ffa55b89f906fc8cc78afdb3f1834cc9c7083565e611a8a7d5fe99e 3.9s
=> => resolve docker.io/docker/dockerfile:1@sha256:4edf897a3ffa55b89f906fc8cc78afdb3f1834cc9c7083565e611a8a7d5fe99e 0.0s
=> => sha256:9d2b4f57f9e20f33279375ce25c6ff14f30f64270ed5c7b613b2b30256754f62 14.28MB / 14.28MB 3.5s
=> => extracting sha256:9d2b4f57f9e20f33279375ce25c6ff14f30f64270ed5c7b613b2b30256754f62 0.4s
=> [internal] load metadata for docker.io/library/node:24-alpine 0.9s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 663B 0.0s
=> [stage-0 1/4] FROM docker.io/library/node:24-alpine@sha256:ebfe2f90462722a7a4de65e91990e97fe0d401c70e0e762c5b53302f905ec1c1 3.2s
=> => resolve docker.io/library/node:24-alpine@sha256:ebfe2f90462722a7a4de65e91990e97fe0d401c70e0e762c5b53302f905ec1c1 0.0s
=> => extracting sha256:e2de96513ba9eb53b431787ec8a65cdde380ac4772a3e4c4b714dcfde2a102b5 0.2s
=> => sha256:02f40d53b06f6b91fec0cd6a6719656da99270bff8ee54ed8dcdf4c157763fc1 1.26MB / 1.26MB 0.8s
=> => sha256:7ce7dcbafb7f750cf0c6be3c30e34372b06dd1182fa67f6ae30782c8150c5444 444B / 444B 0.2s
=> => sha256:3c504d5a797be28f9de43147d49cd8ecb2eea46dfaf7beb8715db695d5f0a7f0 56.52MB / 56.52MB 1.1s
=> => extracting sha256:3c504d5a797be28f9de43147d49cd8ecb2eea46dfaf7beb8715db695d5f0a7f0 1.9s
=> => extracting sha256:02f40d53b06f6b91fec0cd6a6719656da99270bff8ee54ed8dcdf4c157763fc1 0.1s
=> => extracting sha256:7ce7dcbafb7f750cf0c6be3c30e34372b06dd1182fa67f6ae30782c8150c5444 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 31.23kB 0.0s
=> [stage-0 2/4] WORKDIR /usr/src/app 0.1s
=> [stage-0 3/4] RUN --mount=type=bind,source=package.json,target=package.json --mount=type=bind,source=package-lock.json,target=package-l 2.6s
=> [stage-0 4/4] COPY . . 0.0s
=> exporting to image 2.7s
=> => exporting layers 0.3s
=> => exporting manifest sha256:1278071dc9c5842ea834d9abc8c01262b999118ef6903ed4998b8cc8ccc5aaba 0.0s
=> => exporting config sha256:879a23594d9f079707b7b35c022fb427cebaaa18db9701eb78b1fbaf82efed06 0.0s
=> => exporting attestation manifest sha256:012342031ad01079856bb6ebf257f096c2d8f9ff12d448ed86a58a645d64bb5d 0.0s
=> => exporting manifest list sha256:19aee69cf5d970c251d176f2f533bb918f9e72edf675b109b569ae2ff25cb4f3 0.0s
=> => naming to docker.io/library/init-demo-server:latest 0.0s
=> => unpacking to docker.io/library/init-demo-server:latest 2.3s
=> resolving provenance for metadata file 0.0s
[+] up 3/3
✔ Image init-demo-server Built 15.2s
✔ Network init-demo_default Created 0.0s
✔ Container init-demo-server-1 Started 0.4s
$ curl -s http://localhost:3000
{"message":"Hello from Express","node":"v24.21.0"}
$ docker compose exec server ps
PID USER TIME COMMAND
1 node 0:00 npm start
18 node 0:00 {MainThread} node server.js
25 node 0:00 ps
$ time docker compose stop
Container init-demo-server-1 Stopping
Container init-demo-server-1 Stopped
real 0m 0.21s
user 0m 0.04s
sys 0m 0.02s
$ docker compose logs server
server-1 |
server-1 | > express-app@1.0.0 start
server-1 | > node server.js
server-1 |
server-1 | Listening on port 3000
server-1 | SIGTERM received, closing server
server-1 | npm notice
server-1 | npm notice New major version of npm available! 11.19.0 -> 12.2.0
server-1 | npm notice Changelog: https://github.com/npm/cli/releases/tag/v12.2.0
server-1 | npm notice To update run: npm install -g npm@12.2.0
server-1 | npm notice
- El primer paso de la compilación es descargar
docker/dockerfile:1; esto es lo que hace la línea# syntax=. - El servicio se llama
servery el sitio web responde correctamente. psmuestra que el PID 1 esnpm starty que node es su proceso hijo;docker compose stoptermina en 0.21 segundos, así que npm transmite la señal de detención a node.
Cuándo usar docker init
- Proyecto nuevo, no conoces Dockerfile: úsalo para generar un punto de partida y luego compara con este tutorial para entender y modificar cada línea.
- Proyecto con un Dockerfile existente: puedes generar uno en otra carpeta y tomarlo como referencia (por ejemplo, para el uso de montajes de caché).
- Lo que no hace: no se encarga de migraciones de bases de datos, variables de entorno, HTTPS ni los detalles de las compilaciones multi etapa. Los archivos generados son solo un punto de partida.
Resumen
docker initdetecta el lenguaje del proyecto, hace algunas preguntas y generaDockerfile,compose.yaml,.dockerignoreyREADME.Docker.md.- La versión de Node y el puerto no tienen valores predeterminados; debes introducirlos.
- El Dockerfile generado usa los montajes bind y cache de BuildKit. Está bien escrito, pero aún muestra advertencias por sintaxis obsoleta.
- Usa
docker build --checkpara comprobar cualquier Dockerfile. - El ejemplo de PostgreSQL comentado en la plantilla necesita cambios para funcionar con
postgres:18.
Ejercicios
Ejercicio 1: ejecuta docker build --check . en un Dockerfile que hayas escrito (por ejemplo, el de Introducción a Dockerfile) y comprueba si hay advertencias.
Pista
Si no hay ningún problema, se muestra Check complete, no warnings found.. Las advertencias más comunes son JSONArgsRecommended (CMD y ENTRYPOINT usan el formato shell) y LegacyKeyValueFormat (ENV no usa =).
Ejercicio 2: cambia la versión de Node a 22 en el Dockerfile generado sin modificar el contenido del archivo.
Respuesta
NODE_VERSION es un ARG; basta con pasarlo durante la compilación:
docker build --build-arg NODE_VERSION=22 -t init-demo:node22 .
En Compose, escríbelo en build.args:
services:
server:
build:
context: .
args:
NODE_VERSION: "22"
Ejercicio 3: corrige las dos líneas ENV y CMD según las instrucciones de este capítulo. Luego vuelve a ejecutar docker build --check . y confirma que desaparezcan las advertencias.
Preguntas frecuentes
¿Se puede usar docker init en Docker Engine para Linux?
docker init es un complemento de CLI incluido en Docker Desktop (disponible en Docker Desktop para Windows, macOS y Linux). Los hosts Linux que solo tienen Docker Engine no incluyen este comando de forma predeterminada; al ejecutarlo aparece docker: unknown command: docker init.
¿Se puede ejecutar docker init en un proyecto que ya tiene un Dockerfile?
Sí, pero te preguntará si quieres sobrescribir los archivos existentes. Te recomendamos confirmar primero los cambios en Git o probarlo en otra carpeta, comparar el contenido generado y después decidir si lo adoptas.
¿Qué lenguajes admite docker init?
En la versión v1.4.0 probada, el menú incluye Node, Go, Python, Rust, ASP.NET Core, PHP with Apache, Java y Other, como opción de propósito general. Detecta archivos del proyecto (por ejemplo, package.json) y elige automáticamente los valores predeterminados.
¿Se pueden usar los archivos generados directamente en producción?
Pueden servir como punto de partida, pero debes revisarlos. Por ejemplo, la plantilla probada en este capítulo usa la sintaxis obsoleta ENV key value y el formato shell de CMD; docker build --check muestra advertencias. El ejemplo de PostgreSQL comentado en la plantilla tampoco es válido para postgres:18.
Actualizado 13 de octubre de 2026