La compilación de Docker no llega a una dependencia privada: revise esto
Un paquete privado que el host sí descarga puede fallar dentro de la compilación. Nombre el builder, demuestre la ruta y monte luego el token como secreto de compilación.
Un paquete privado que en su máquina se resuelve sin problemas puede fallar dentro de la compilación con un 404 o con un tiempo de espera agotado, y el Dockerfile casi nunca es la causa. El paso de compilación se ejecuta en otro espacio de nombres de red, con otra vista del DNS y otro almacén de credenciales que la shell en la que hizo las pruebas. Recorra estas comprobaciones en orden y deténgase en la primera que falle, porque cada comprobación posterior da por hecho que la anterior pasó. Cada paso nombra el comando que resuelve el asunto.
Empiece por nombrar el builder, no el Dockerfile
BuildKit puede ser local, estar en un contenedor o correr en otra máquina, y cada uno tiene su propia red por defecto. Ejecute docker buildx ls y lea el nodo marcado con un asterisco antes de cambiar nada. Un docker-container controlador o un builder en la nube no comparte la ruta privada de su portátil solo porque escribió allí el comando. Si el builder activo es remoto, cada comprobación restante debe ejecutarse contra ese host y no contra su estación de trabajo.
El builder también lleva su propia configuración del resolutor y sus variables de proxy. Ambas se leen en el momento de la compilación y no se heredan de la terminal que la inició.
Demuestre la ruta de red desde dentro de un paso de compilación
Escriba una etapa desechable que resuelva el host de la dependencia y abra una conexión con él. Es la única prueba que responde a la pregunta por el builder y no por su shell.
FROM alpine:3.20
RUN apk add --no-cache curl bind-tools && getent hosts registry.example.internal && curl -sS -o /dev/null -w "%{http_code}
" https://registry.example.internal/simple/
Compile ese archivo con el mismo builder, modo de red y montajes de secretos que usa su compilación real: docker buildx build --builder remote0 -f Dockerfile.probe --progress=plain .. Si getent no imprime nada, el fallo es de resolución de nombres y ninguna credencial lo arreglará. Si el nombre se resuelve pero curl informa de un tiempo de espera agotado, el obstáculo es la ruta o la política de salida delante del registro.
Borre la sonda en cuanto responda. Es una etapa de diagnóstico y nunca debería etiquetarse ni publicarse.
Monte la credencial en lugar de copiarla
Cuando la ruta funcione, la autenticación es el siguiente fallo de la lista. Un montaje de secreto de BuildKit expone un archivo a un solo paso RUN sin escribirlo en una capa, que es lo que necesita la herramienta de dependencias y lo que la imagen no debe conservar.
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc npm ci --omit=dev
El secreto debe suministrarse desde fuera del Dockerfile: docker buildx build --secret id=npmrc,src=/home/me/.npmrc .. El archivo se queda en el cliente y nunca entra en el historial de la imagen. Un ARG o un ENV con el mismo token no hacen este trabajo, porque ambos quedan registrados en la configuración de la imagen.
Una imagen sin root necesita su propia ruta de destino, como /home/app/.npmrc o el archivo equivalente para pip, Maven o Cargo. El destino del montaje debe coincidir con el usuario que ejecuta el comando, o la herramienta informará de un archivo de configuración ausente que en realidad está ahí.
Audite qué deja la herramienta de dependencias en la imagen
Un montaje temporal mantiene la credencial fuera de una capa, pero no impide que la herramienta escriba otra cosa. Los gestores de paquetes dejan archivos de bloqueo, directorios de caché y a veces la URL del registro ya resuelta.
Lea el sistema de archivos terminado en lugar de confiar en el Dockerfile. docker history --no-trunc image:tag enumera cada comando de capa, y docker run --rm image:tag sh -c "ls -a /root" muestra qué sobrevivió al contenedor en ejecución. Incluso cuando el archivo solo se montó, un token escrito en una línea de registro durante npm ci sigue siendo una fuga.
Lea también el registro de compilación, porque --progress=plain imprime la salida de los comandos tal cual. Si el token aparece ahí, rótelo antes que nada y páselo por un archivo que la herramienta lea en silencio.
Verifique que la imagen de ejecución ya no necesita la ruta privada
La compilación y la aplicación en marcha son dos consumidores distintos de la misma dependencia, y solo el primero necesita la ruta privada. Una imagen terminada debería arrancar, resolver sus dependencias de ejecución y servir tráfico sin la credencial de compilación.
Pruébelo donde el registro privado no sea accesible, o simplemente inicie el contenedor con --network none y confirme que arranca sin el secreto montado. Un contenedor que solo arranca cuando el secreto de compilación está presente sigue acoplado al entorno de compilación.
Si el contenedor realmente necesita el registro en tiempo de ejecución, es una decisión de acceso aparte, y corresponde al almacén de secretos del orquestador y no a la compilación. Documente las dos rutas por separado para que nadie intente reparar una descarga en ejecución con una bandera de compilación. Cuando las cinco comprobaciones pasan, el síntoma original tiene una causa nombrada en cada capa en lugar de una conjetura sobre la red de Docker.