Introducción
Organizar correctamente los proyectos Docker significa conseguir que cada aplicación pueda localizarse, entenderse, desplegarse, mantenerse y retirarse sin depender de recordar dónde quedó cada archivo o de reconstruir decisiones a partir de un servidor en funcionamiento. Docker facilita mucho la creación de contenedores, pero esa facilidad también puede producir desorden: varios archivos Compose en directorios distintos, nombres improvisados, variables mezcladas, scripts auxiliares sin ubicación fija, copias locales, configuraciones antiguas y proyectos que nadie sabe si siguen activos.
Mientras existen dos o tres servicios, casi cualquier estructura parece suficiente. El problema aparece cuando la plataforma crece. Un proyecto se instala en /opt, otro dentro del directorio personal del administrador, otro en /srv y un cuarto se copia desde una prueba anterior. Algunos utilizan nombres descriptivos; otros conservan los nombres predeterminados. Unos tienen documentación; otros solo un archivo Compose. La infraestructura puede seguir funcionando, pero cada cambio exige más investigación.
La solución no consiste en imponer una jerarquía gigantesca. Una pequeña empresa necesita algo mucho más útil: pocas convenciones, claras y repetibles. Cada proyecto debe tener una ubicación reconocible, un nombre estable, una estructura que distinga definición, configuración y elementos auxiliares, y un procedimiento de mantenimiento que permita saber qué está vigente y qué puede eliminarse.
Este artículo explica cómo organizar proyectos Docker desde esa perspectiva operativa. El foco está en la estructura de carpetas, la nomenclatura, los archivos que conviene mantener junto al proyecto, la separación entre elementos versionables y locales, los permisos, los entornos, los scripts, las copias de configuración, la retirada de versiones antiguas y las revisiones necesarias para que el servidor no se convierta con el tiempo en una colección de despliegues difíciles de interpretar.
La arquitectura general de la plataforma se desarrolla en cómo diseñar una plataforma Docker para una pequeña empresa. Aquí partimos de una cuestión más concreta: una vez decidida la plataforma, ¿cómo debe organizarse cada proyecto para que siga siendo mantenible?
Índice
- Qué debe entenderse por proyecto Docker
- Por qué los proyectos Docker se desordenan con tanta facilidad
- Principios de organización que conviene fijar desde el principio
- Elegir una ubicación común para los proyectos
- Diseñar una estructura de carpetas previsible
- Dónde situar el archivo Compose
- Separar configuración general y configuración local
- Organizar variables de entorno sin crear confusión
- Mantener secretos fuera de la estructura distribuible
- No mezclar la estructura del proyecto con los datos persistentes
- Organizar scripts y tareas auxiliares
- Documentación mínima dentro de cada proyecto
- Crear una nomenclatura estable
- Nombrar servicios y contenedores con criterio
- Nombres de redes y volúmenes
- Organizar producción, pruebas y desarrollo
- Qué conviene guardar en control de versiones
- Propietarios y permisos de los proyectos
- Mantener un procedimiento de despliegue repetible
- Mantenimiento periódico de los proyectos
- Limpiar archivos y recursos antiguos sin borrar lo necesario
- Cómo retirar correctamente un proyecto
- Cómo auditar un servidor Docker ya desordenado
- Ejemplo de estructura para varios proyectos
- Errores frecuentes
- Lista de comprobación
- Preguntas frecuentes
- Conclusión
Qué debe entenderse por proyecto Docker
Un proyecto Docker es la unidad lógica que agrupa los elementos necesarios para desplegar y operar una aplicación o un conjunto de servicios relacionados. No tiene por qué equivaler a un único contenedor.
Por ejemplo, una aplicación puede necesitar:
- un servicio web;
- un proceso de aplicación;
- una base de datos;
- una caché;
- una tarea programada;
- una red interna;
- volúmenes persistentes;
- variables de configuración.
Todos esos componentes pueden pertenecer al mismo proyecto porque comparten finalidad y ciclo operativo. El proyecto es, por tanto, una frontera de administración: debe poder identificarse qué archivos lo describen, qué servicios ejecuta, qué recursos utiliza y qué pasos permiten ponerlo en funcionamiento.
Esta distinción es importante porque evita organizar el servidor por contenedores aislados. Si cada contenedor se administra como una pieza independiente, resulta más difícil comprender qué elementos forman una aplicación completa.
Proyecto no es lo mismo que plataforma
La plataforma Docker es el entorno general donde se ejecutan varios proyectos. Un proyecto es una carga concreta dentro de esa plataforma. Conviene mantener esta separación conceptual porque sus ciclos de vida son diferentes.
El motor Docker puede actualizarse sin cambiar una aplicación. Un proyecto puede retirarse sin eliminar la plataforma. Una nueva aplicación puede añadirse siguiendo las mismas convenciones sin rediseñar el servidor.
Por qué los proyectos Docker se desordenan con tanta facilidad
Docker reduce la fricción para desplegar. Esa misma ventaja permite crear servicios antes de haber decidido cómo se organizarán a largo plazo.
Las pruebas se convierten en producción
Se descarga un ejemplo, se modifica un archivo Compose y el servicio empieza a utilizarse. Como funciona, nadie reorganiza el directorio ni documenta qué se cambió. Meses después, el proyecto sigue dependiendo de la estructura de una prueba.
Cada aplicación trae su propia convención
Los proyectos de terceros pueden utilizar nombres y carpetas diferentes. Si se conservan todas las estructuras sin un criterio común, el servidor acaba reflejando las decisiones de muchos autores distintos.
La comodidad crea archivos auxiliares
Aparecen copias como compose-old.yml, .env.bak, prueba.txt, scripts temporales y notas del administrador. Si no existe una política de limpieza, esos elementos terminan pareciendo parte oficial del despliegue.
Los nombres dejan de tener significado
Un primer proyecto puede llamarse app. El segundo, app2. Después aparecen web-nueva, produccion-final y prueba-buena. Los nombres describen un momento de la historia, no la función del sistema.
Los datos y la definición se mezclan
Un directorio que contiene a la vez archivos Compose, bases de datos, uploads, logs, copias y scripts se vuelve difícil de respaldar y de trasladar. Nadie sabe qué puede reconstruirse y qué debe conservarse.
No existe retirada
Los proyectos antiguos se paran, pero no se eliminan. Permanecen carpetas, volúmenes, redes, imágenes y credenciales “por si acaso”. Cada año resulta más difícil distinguir lo vigente de lo abandonado.
Este patrón es similar al deterioro que aparece en servidores tradicionales. El artículo cómo organizar un servidor Linux para que siga siendo mantenible dentro de cinco años desarrolla esa problemática a nivel general. En Docker, la solución vuelve a depender de convenciones estables y una disciplina de ciclo de vida.
Principios de organización que conviene fijar desde el principio
Una ubicación debe tener un significado
El directorio donde reside un proyecto debe indicar que contiene la definición operativa de una aplicación. No debe depender de qué usuario estaba conectado cuando se desplegó.
Un proyecto debe tener una raíz reconocible
Los archivos relacionados deben poder localizarse partiendo de una carpeta principal. Eso reduce búsquedas por todo el sistema.
La estructura debe separar responsabilidades
Definiciones, configuración, scripts, documentación y datos no tienen el mismo ciclo de vida. Pueden relacionarse, pero conviene que no formen un bloque indistinguible.
Los nombres deben sobrevivir al tiempo
Un nombre correcto sigue teniendo sentido después de cambiar de proveedor, de versión o de administrador. Debe describir función, no una circunstancia temporal.
La fuente oficial debe estar clara
Si existe una copia en Git, otra en el servidor y otra en el ordenador del administrador, debe saberse cuál es la fuente desde la que se despliega. Varias copias editables crean divergencias.
Lo temporal necesita fecha de retirada
Una copia creada antes de un cambio puede ser útil. Una copia que permanece durante dos años sin contexto se convierte en ruido.
La estructura debe ser proporcional
No hace falta crear veinte subdirectorios vacíos para una aplicación sencilla. La organización debe aportar claridad, no burocracia.
Elegir una ubicación común para los proyectos
El primer criterio práctico consiste en decidir dónde viven los proyectos Docker del servidor.
No existe una única ruta válida. Lo importante es elegir una convención coherente con la organización general del sistema y aplicarla de manera constante.
Una estructura posible puede partir de una raíz como:
/srv/docker/
Y organizar debajo cada proyecto:
/srv/docker/
├── proxy/
├── monitorizacion/
├── inventario/
├── aplicacion-comercial/
└── automatizacion-interna/
También puede adoptarse otra ruta si existe un criterio documentado. La elección concreta es menos importante que evitar proyectos repartidos entre:
/root;- directorios personales;
- carpetas temporales;
- distintas ubicaciones elegidas según cada tutorial;
- árboles que contienen también archivos sin relación.
Por qué evitar directorios personales
Una aplicación situada en /home/nombre-persona queda asociada al ciclo de vida de esa cuenta. Si el usuario se elimina, cambia de permisos o deja de administrar el servidor, la ubicación deja de representar una estructura empresarial.
No mezclar proyectos y backups
La raíz de proyectos no debería convertirse en destino de copias completas. Una copia pertenece al sistema de recuperación y necesita su propia política de retención.
El criterio general de ubicaciones en Linux puede ampliarse en cómo diseñar una estructura de directorios propia para aplicaciones empresariales.
Diseñar una estructura de carpetas previsible
Una estructura base ayuda a que todos los proyectos se interpreten de forma parecida. No es necesario que todas las aplicaciones tengan exactamente los mismos directorios, pero sí conviene mantener un patrón.
Un proyecto sencillo podría organizarse así:
/srv/docker/mi-proyecto/
├── compose.yml
├── .env
├── .env.example
├── config/
├── scripts/
├── docs/
└── README.md
Esta estructura separa varias responsabilidades:
compose.yml: definición principal del despliegue;.env: valores locales necesarios para ese entorno;.env.example: plantilla sin secretos;config/: archivos de configuración montados en servicios;scripts/: tareas auxiliares controladas;docs/: información operativa cuando supera lo razonable para el README;README.md: punto de entrada para comprender el proyecto.
No crees carpetas por obligación
Si una aplicación no necesita scripts, no hace falta crear scripts/. Si toda la documentación cabe en el README, docs/ puede omitirse. El patrón debe servir como marco, no como plantilla rígida.
Evita árboles demasiado profundos
Una jerarquía con muchas capas obliga a recordar rutas y complica scripts y copias. La profundidad debe aparecer por necesidad funcional.
Separa claramente lo generado
Archivos temporales, cachés o salidas producidas durante la ejecución no deberían mezclarse con la definición que se revisa y versiona.
Dónde situar el archivo Compose
El archivo Compose principal debería encontrarse en la raíz del proyecto o en una ubicación inmediata y previsible. De esta forma, entrar en el directorio permite identificar rápidamente cómo se despliega la aplicación.
Una raíz clara facilita operaciones como:
- consultar la definición;
- comprobar servicios;
- levantar o detener el proyecto;
- revisar cambios;
- localizar variables y configuraciones asociadas;
- documentar el procedimiento.
Evita múltiples archivos sin explicación
Puede ser válido tener archivos adicionales para entornos o funciones distintas, pero sus nombres y relación deben estar documentados. Una carpeta con:
docker-compose.yml
docker-compose2.yml
docker-compose-old.yml
docker-compose-final.yml
docker-compose-prueba.yml
no muestra una estrategia de versiones; muestra un historial informal.
El historial pertenece al control de versiones
Cuando existe un repositorio, las versiones anteriores del archivo no necesitan conservarse como copias sucesivas en la misma carpeta. El servidor debe reflejar el estado desplegado y la fuente oficial debe conservar la historia.
No edites una copia distinta a la desplegada
Un error especialmente peligroso aparece cuando se modifica un archivo pensando que es el activo, pero el proyecto se levanta desde otro directorio. El README o procedimiento debe indicar de forma inequívoca qué archivo y qué ruta se utilizan.
Separar configuración general y configuración local
La configuración debe distinguir lo que forma parte del proyecto de aquello que cambia según el entorno.
Puede haber configuraciones que conviene versionar porque son comunes:
- plantillas de un proxy interno;
- parámetros no sensibles de una aplicación;
- archivos de inicialización;
- configuraciones de logging;
- reglas funcionales que deben ser iguales en todos los despliegues.
Y valores que pueden variar por máquina o entorno:
- dominios;
- puertos externos;
- rutas del host;
- límites de recursos;
- direcciones de servicios externos;
- identificadores propios del entorno.
Separar ambos tipos permite reutilizar la definición sin editar archivos comunes cada vez que cambia un servidor.
Evita configuraciones invisibles
Si un proyecto depende de un archivo situado fuera de su árbol, debe quedar referenciado claramente. Una configuración escondida en otra ruta convierte la carpeta del proyecto en una representación incompleta.
Una fuente de verdad por configuración
Si un archivo se mantiene en un repositorio, no debería existir una segunda copia que se modifica manualmente de forma independiente. El procedimiento debe definir cómo llega la configuración al servidor.
Organizar variables de entorno sin crear confusión
Las variables de entorno permiten separar valores de la definición principal, pero pueden convertirse en otra fuente de desorden si se reparten entre archivos y mecanismos diferentes.
Agrupa valores por proyecto
Un archivo local asociado a la raíz del proyecto facilita saber qué valores utiliza el despliegue. Debe tener permisos adecuados y quedar excluido del control de versiones cuando contenga información sensible.
Utiliza una plantilla
Un archivo como .env.example puede mostrar los nombres de las variables necesarias sin incluir credenciales reales:
APP_DOMAIN=
APP_PORT=
DB_HOST=
DB_NAME=
DB_USER=
DB_PASSWORD=
Esto ayuda a reconstruir el proyecto porque permite saber qué valores deben suministrarse.
No dupliques la misma variable en varios lugares
Si un valor aparece en el archivo Compose, en .env y en un script de arranque, puede resultar difícil saber cuál prevalece. Conviene mantener un único origen cuando sea posible.
Distingue configuración de secreto
Un puerto o un nombre de dominio no requieren el mismo tratamiento que una contraseña. Aunque ambos puedan suministrarse como variables, su protección y su ciclo de vida son distintos.
Mantener secretos fuera de la estructura distribuible
Contraseñas, tokens y claves no deberían quedar incrustados en archivos que se comparten, versionan o copian sin control.
El repositorio no es un almacén de secretos
Una credencial introducida en el historial puede seguir existiendo aunque se elimine de la versión actual. Por ello, las plantillas deben contener nombres de variables, no valores reales.
La documentación debe indicar dónde obtenerlos
El README puede explicar qué secreto necesita el proyecto y dónde está custodiado de forma autorizada, sin reproducirlo.
Evita archivos de copia con credenciales
Un .env.bak creado antes de un cambio puede quedar olvidado con una contraseña antigua o todavía válida. Las copias temporales de archivos sensibles deben eliminarse o protegerse según su función.
Prepara la rotación
El proyecto debe permitir identificar qué servicios consumen cada credencial y qué proceso debe seguirse para sustituirla. La organización del directorio debe facilitar esa tarea, no obligar a buscar referencias por todo el servidor.
No mezclar la estructura del proyecto con los datos persistentes
La carpeta del proyecto representa principalmente cómo se despliega y administra la aplicación. Los datos persistentes tienen un ciclo de vida diferente y deben tratarse como estado que debe sobrevivir al reemplazo de contenedores.
Este principio permite responder con claridad a dos preguntas:
- ¿qué necesito para reconstruir el despliegue?
- ¿qué necesito restaurar para recuperar la información?
Si ambas respuestas son “copiar toda la carpeta”, probablemente la separación no está bien definida.
Datos identificables
Para cada proyecto debe conocerse qué elementos contienen:
- bases de datos;
- archivos subidos;
- documentos generados;
- estado de aplicaciones;
- colas persistentes;
- información que no puede regenerarse.
Datos regenerables
Logs, cachés y temporales pueden necesitar persistencia operativa, pero no deben confundirse automáticamente con datos empresariales. Sus políticas de copia y retención pueden ser distintas.
La separación general entre estas capas se desarrolla en cómo separar correctamente aplicaciones, datos y configuración. Un artículo específico del clúster abordará con más profundidad la gestión de volúmenes Docker; aquí el objetivo es mantener limpia la frontera entre proyecto y estado persistente.
Organizar scripts y tareas auxiliares
Los proyectos Docker suelen acumular pequeños scripts para copias, comprobaciones, importaciones, limpieza o despliegues. Si se dejan dispersos, terminan siendo dependencias invisibles.
Una ubicación común
Los scripts específicos del proyecto pueden mantenerse en:
/srv/docker/mi-proyecto/scripts/
Esto permite distinguirlos de las utilidades administrativas generales del servidor.
Un script debe explicar su finalidad
Los nombres deben describir acciones:
backup-datos.sh
comprobar-servicio.sh
exportar-configuracion.sh
preparar-actualizacion.sh
Son preferibles a:
script1.sh
nuevo.sh
prueba.sh
arreglar.sh
Evita incluir secretos directamente
Los scripts deben obtener configuración mediante mecanismos definidos. Una contraseña escrita dentro de un script puede terminar versionada, copiada o mostrada accidentalmente.
Documenta entradas y efectos
Un script que elimina recursos, restaura datos o modifica configuración debe indicar qué espera, qué cambia y cómo se comprueba el resultado.
Cuando los scripts tienen alcance general sobre el servidor, conviene aplicar los criterios explicados en cómo organizar scripts de administración en Linux sin perder el control.
Documentación mínima dentro de cada proyecto
La documentación de una infraestructura Docker completa puede ser amplia, pero cada proyecto necesita al menos un punto de entrada local que permita saber qué es y cómo se administra.
Un README.md puede incluir:
- nombre y finalidad del proyecto;
- servicios que contiene;
- entorno al que pertenece;
- archivo Compose utilizado;
- dependencias externas;
- dominios o puertos relevantes;
- ubicación lógica de los datos persistentes;
- variables necesarias;
- referencia de los secretos;
- procedimiento de arranque y parada;
- comprobación básica de funcionamiento;
- procedimiento o referencia de copia;
- responsable;
- enlace a documentación más amplia cuando exista.
No conviertas el README en un manual infinito
Debe servir para orientarse rápidamente. Los procedimientos largos pueden mantenerse en docs/ o en un repositorio documental central.
Documenta particularidades, no Docker entero
No es necesario explicar qué significa cada comando estándar. Lo importante es describir qué tiene de particular ese proyecto: rutas, dependencias, excepciones y decisiones que otra persona no podría deducir fácilmente.
El enfoque general puede complementarse con cómo documentar correctamente un servidor Linux. El clúster Docker contará además con un artículo específico dedicado a documentar la infraestructura completa, por lo que este bloque se limita a la documentación mínima por proyecto.
Crear una nomenclatura estable
Los nombres son una de las herramientas más baratas para reducir complejidad. Una convención coherente permite reconocer proyectos, servicios y recursos sin abrir sus archivos.
Características de un buen nombre
- describe la función;
- es suficientemente corto;
- evita nombres personales;
- no depende del proveedor;
- no utiliza palabras temporales como
nuevoofinal; - permite distinguir entornos cuando es necesario;
- funciona bien en terminales y scripts;
- se mantiene estable aunque cambie la versión de la aplicación.
Ejemplos razonables
proxy
monitorizacion
gestor-documental
automatizacion-interna
inventario
web-interna
Ejemplos problemáticos
docker1
app-final
cosa-nueva
prueba-buena
proyecto-jose
servidor2
El nombre del directorio debería relacionarse con el nombre lógico del proyecto y con la documentación. No es necesario repetir la misma cadena en todos los recursos si Docker ya añade contexto, pero sí mantener coherencia.
Nombrar servicios y contenedores con criterio
Dentro de un proyecto, los nombres de servicio deberían describir la responsabilidad técnica, no el producto completo repetido una y otra vez.
Por ejemplo:
services:
web:
app:
db:
cache:
worker:
Estos nombres permiten entender la relación entre componentes. Si el proyecto ya se llama gestor-documental, no es necesario que cada servicio repita todo el nombre salvo que exista una razón operativa.
Evita nombres basados solo en versiones
php82 puede describir la implementación actual, pero quizá el servicio siga cumpliendo la misma función cuando cambie de versión. El nombre funcional suele ser más estable.
Evita fijar manualmente nombres de contenedor sin necesidad
Las herramientas de composición pueden generar nombres derivados del proyecto y del servicio. Forzar nombres globales en todos los casos puede crear colisiones entre entornos y dificulta reutilizar la misma definición.
Distingue servicio de instancia
El servicio representa una función. La instancia concreta puede recrearse. Esta diferencia ayuda a no tratar un contenedor específico como si fuera un servidor permanente.
Nombres de redes y volúmenes
Redes y volúmenes también forman parte de la organización, aunque su diseño técnico se trate en otras piezas del clúster.
Preferir contexto automático cuando sea suficiente
Si una red o un volumen pertenece exclusivamente a un proyecto, los nombres derivados del proyecto suelen aportar suficiente contexto y reducen colisiones.
Nombrar explícitamente recursos compartidos
Una red utilizada por varios proyectos o un recurso externo necesita un nombre que explique su función, por ejemplo:
red-entrada
red-monitorizacion
No reutilizar un volumen porque “ya existe”
Un volumen debe pertenecer a una función conocida. Reutilizar recursos antiguos sin conocer su contenido puede mezclar datos o introducir dependencias inesperadas.
Relacionar el nombre con el inventario
Al revisar los recursos del servidor debería ser posible determinar a qué proyecto pertenecen o por qué son compartidos. Los nombres huérfanos son una señal de deuda operativa.
Organizar producción, pruebas y desarrollo
El mismo proyecto puede existir en varios entornos, pero debe evitarse que sus recursos se confundan.
Separación por host
Cuando producción y pruebas están en servidores distintos, la frontera es clara. Aun así, conviene mantener nombres y documentación coherentes.
Separación dentro del mismo host
Si varios entornos comparten máquina, puede utilizarse una estructura como:
/srv/docker/
├── produccion/
│ ├── aplicacion-a/
│ └── aplicacion-b/
└── pruebas/
├── aplicacion-a/
└── aplicacion-b/
Otra opción es mantener todos los proyectos en una misma raíz y diferenciar el entorno mediante nombres. La elección depende del número de aplicaciones y del método de operación.
Lo esencial es evitar ambigüedad:
- los datos no deben compartirse accidentalmente;
- las credenciales deben corresponder al entorno;
- los dominios y puertos deben estar diferenciados;
- los nombres de proyecto no deben colisionar;
- un comando ejecutado en pruebas no debe afectar a producción.
No utilices “prod” y “test” sin comprobar dónde estás
Los sufijos ayudan, pero la operación debe incluir comprobaciones. El prompt del shell, el nombre de host y la documentación pueden reforzar la identificación del entorno.
Qué conviene guardar en control de versiones
El control de versiones ayuda a convertir la estructura del proyecto en una fuente reproducible y trazable.
Elementos habitualmente versionables
- archivo Compose;
- Dockerfile cuando exista;
- configuraciones no secretas;
- plantillas de variables;
- scripts;
- README;
- documentación técnica;
- archivos de inicialización que formen parte del despliegue.
Elementos que normalmente no deberían versionarse
- contraseñas y tokens;
- archivos
.envcon secretos; - bases de datos;
- uploads;
- logs;
- cachés;
- temporales;
- copias completas de datos;
- artefactos que pueden generarse automáticamente.
El servidor no debe ser el único repositorio
Si la única copia de la definición está en producción, un fallo del host afecta tanto al servicio como a la información necesaria para reconstruirlo.
Evita cambios solo en producción
Una modificación urgente puede realizarse localmente, pero después debe incorporarse a la fuente oficial. De lo contrario, la siguiente reconstrucción recuperará una versión diferente de la que realmente funcionaba.
Propietarios y permisos de los proyectos
La organización del directorio debe acompañarse de un modelo de permisos. No todos los usuarios del servidor necesitan modificar los proyectos.
Evita que todo pertenezca a root por comodidad
Algunas operaciones administrativas requieren privilegios, pero los archivos de proyecto pueden gestionarse mediante un propietario y grupo adecuados. El objetivo es que únicamente las personas o procesos autorizados puedan modificarlos.
El proceso de aplicación no necesita escribir la definición
Los contenedores deben acceder a los datos o configuraciones necesarios, no a toda la carpeta del proyecto con permisos amplios sin motivo.
Protege archivos sensibles
Los archivos locales que contengan credenciales necesitan permisos más restrictivos que un README o una plantilla pública.
Revisa permisos después de copiar proyectos
Copiar directorios como root, restaurar desde una copia o moverlos entre servidores puede cambiar propietario, grupo o modos. El procedimiento de reconstrucción debe contemplarlo.
Mantener un procedimiento de despliegue repetible
La estructura de carpetas tiene sentido cuando facilita un despliegue que otra persona puede repetir.
Un procedimiento básico puede seguir esta secuencia:
- Obtener la versión del proyecto desde su fuente oficial.
- Situarla en la ruta acordada.
- Preparar archivos de configuración local.
- Recuperar las credenciales desde su ubicación segura.
- Crear o vincular los datos persistentes necesarios.
- Validar la definición.
- Obtener o construir las imágenes.
- Iniciar los servicios.
- Comprobar logs y estado.
- Realizar una prueba funcional.
- Registrar la versión desplegada.
El valor de este procedimiento es demostrar que el proyecto no depende de una instancia concreta. Si puede reconstruirse desde fuentes conocidas, la estructura cumple su función.
Evita procedimientos basados en memoria
“Arrancar como siempre” no es una instrucción. El documento debe indicar qué archivo se utiliza, qué requisitos existen y cómo se confirma que el resultado es correcto.
Separa despliegue de restauración
Desplegar la aplicación crea la parte reproducible. Restaurar incorpora el estado persistente. Son operaciones relacionadas, pero no idénticas.
Mantenimiento periódico de los proyectos
Organizar bien una carpeta el primer día no garantiza que siga limpia. El mantenimiento debe evitar que reaparezcan copias improvisadas, recursos huérfanos y configuraciones divergentes.
Después de cada cambio
- actualizar la fuente oficial;
- eliminar archivos temporales creados para la intervención;
- registrar la versión desplegada;
- actualizar documentación si cambia el procedimiento;
- revisar permisos;
- confirmar que no quedaron contenedores o recursos de prueba.
Mensualmente
- revisar proyectos activos;
- detectar contenedores parados que no deberían existir;
- comprobar crecimiento de logs;
- revisar errores repetidos;
- confirmar que las copias se ejecutan;
- identificar carpetas temporales o backups locales pendientes de limpiar.
Trimestralmente
- comparar el servidor con el inventario;
- revisar proyectos sin responsable;
- buscar configuraciones que difieren de la fuente oficial;
- eliminar recursos retirados tras validar que no son necesarios;
- revisar credenciales y accesos;
- confirmar que la documentación permite reconstruir los proyectos principales.
Antes de una actualización importante
Conviene revisar estructura, datos, copia, versión actual y reversión. La estrategia específica de actualización de contenedores merece un tratamiento propio y no debe confundirse con el mantenimiento organizativo de la carpeta.
Limpiar archivos y recursos antiguos sin borrar lo necesario
Docker genera recursos con rapidez y el miedo a eliminarlos puede convertir el servidor en un archivo histórico permanente. La limpieza debe basarse en inventario y responsabilidad, no en comandos destructivos ejecutados a ciegas.
Archivos de proyecto
Revisa especialmente:
- copias
.bak; - archivos Compose antiguos;
- exportaciones temporales;
- scripts de una intervención pasada;
- documentación duplicada;
- credenciales antiguas;
- directorios de pruebas ya finalizadas.
Recursos Docker
Puede haber:
- contenedores parados;
- imágenes antiguas;
- redes sin uso;
- volúmenes huérfanos;
- capas y cachés de construcción.
No todos son basura. Una imagen anterior puede formar parte de una reversión temporal; un volumen sin contenedor puede contener datos que deben conservarse. Antes de eliminar un recurso debe conocerse su función.
Utiliza cuarentena cuando haya duda
Si un archivo o proyecto no puede eliminarse con seguridad, puede marcarse como pendiente de retirada y asignarle una fecha de revisión. Lo importante es evitar que “por si acaso” se convierta en un estado permanente.
Cómo retirar correctamente un proyecto
La baja de un proyecto es parte de su ciclo de vida. Parar los contenedores no es suficiente.
- Confirmar que el servicio ya no se utiliza.
- Identificar usuarios, aplicaciones o automatizaciones que dependan de él.
- Decidir qué datos deben conservarse.
- Crear una copia o exportación final cuando corresponda.
- Detener el proyecto durante un periodo controlado si existe duda sobre dependencias.
- Retirar dominios, rutas de proxy y puertos asociados.
- Revocar credenciales y tokens.
- Eliminar tareas programadas y scripts exclusivos.
- Eliminar contenedores cuando ya no sean necesarios.
- Revisar redes y volúmenes relacionados.
- Retirar la carpeta del servidor.
- Actualizar inventario y documentación.
Conserva historia donde corresponda
La definición anterior puede seguir existiendo en el repositorio y el registro de cambios. No hace falta mantener una copia completa en producción para recordar que el servicio existió.
No elimines datos por asociación automática
Retirar una aplicación no implica necesariamente borrar inmediatamente sus datos. La política de retención debe decidirlo de forma separada.
Cómo auditar un servidor Docker ya desordenado
Si la plataforma ya contiene proyectos distribuidos por distintas rutas, conviene ordenar por fases en lugar de moverlo todo de una vez.
1. Inventariar proyectos en ejecución
Relaciona contenedores, nombres de proyecto, imágenes, redes, volúmenes y puertos. El objetivo es saber qué está realmente activo.
2. Localizar las definiciones
Para cada servicio, identifica desde qué archivo y directorio se despliega. No asumas que la carpeta más evidente es la activa.
3. Identificar datos persistentes
Antes de mover o eliminar carpetas, determina dónde viven bases de datos, uploads y otros datos que no pueden perderse.
4. Encontrar archivos sensibles
Busca variables, credenciales, claves y certificados asociados. Documenta su referencia sin copiarlos a nuevos lugares innecesariamente.
5. Clasificar cada proyecto
- activo y mantenido;
- activo pero sin documentación;
- prueba;
- obsoleto pendiente de retirada;
- desconocido y pendiente de investigación.
6. Definir la convención objetivo
Decide raíz, nombres, estructura y fuente de verdad antes de empezar a migrar.
7. Normalizar uno a uno
Empieza por un proyecto de bajo riesgo. Crea una copia, documenta el estado, mueve o reconstruye su definición y valida que funciona antes de continuar.
8. No reorganizar datos críticos solo por estética
Si una ruta de datos funciona y está correctamente protegida, cambiarla puede introducir riesgo sin aportar un beneficio equivalente. La reorganización debe mejorar operación, no perseguir una simetría perfecta.
9. Actualizar el inventario
La auditoría no termina cuando las carpetas parecen ordenadas. Debe quedar una relación fiable de proyectos y recursos.
Para descubrir servicios de forma más amplia puede resultar útil cómo inventariar servicios instalados en un servidor Linux, que incluye también contenedores, tareas programadas y software fuera de los mecanismos tradicionales.
Ejemplo de estructura para varios proyectos
Una plataforma pequeña podría utilizar una organización como esta:
/srv/docker/
├── proxy/
│ ├── compose.yml
│ ├── .env
│ ├── .env.example
│ ├── config/
│ ├── scripts/
│ └── README.md
│
├── monitorizacion/
│ ├── compose.yml
│ ├── .env
│ ├── .env.example
│ ├── config/
│ └── README.md
│
├── gestor-documental/
│ ├── compose.yml
│ ├── .env
│ ├── .env.example
│ ├── config/
│ ├── scripts/
│ ├── docs/
│ └── README.md
│
└── automatizacion-interna/
├── compose.yml
├── .env
├── .env.example
├── config/
└── README.md
La estructura no muestra necesariamente los datos persistentes porque estos pueden residir en volúmenes gestionados por Docker o en rutas definidas según la política de almacenamiento.
Qué se consigue con este patrón
- un administrador sabe dónde buscar;
- cada proyecto tiene una raíz reconocible;
- los archivos Compose están en una ubicación previsible;
- la configuración específica puede distinguirse de la plantilla;
- los scripts no quedan repartidos por el servidor;
- la documentación está cerca del componente;
- los proyectos pueden versionarse de forma independiente;
- la retirada puede realizarse proyecto a proyecto.
Qué no resuelve esta estructura
Una carpeta ordenada no sustituye:
- una política de backups;
- un diseño correcto de redes;
- gestión de secretos;
- control de imágenes;
- actualizaciones planificadas;
- monitorización;
- documentación general de la plataforma.
La organización de proyectos es una capa del sistema, no toda la arquitectura.
Errores frecuentes
Guardar proyectos dentro de /root
Funciona técnicamente, pero convierte una ubicación administrativa personal en la raíz de aplicaciones de producción.
Usar una carpeta distinta para cada tutorial
Los ejemplos externos están pensados para enseñar o demostrar una aplicación. La plataforma necesita adaptar el despliegue a su propia convención.
Crear nombres como final, nuevo o bueno
Describen una comparación temporal, no la función. Dentro de unos meses pierden significado.
Conservar versiones mediante copias de archivos
compose-old.yml, compose-old2.yml y compose-final.yml no sustituyen un historial de versiones.
Versionar el archivo .env con credenciales
Puede exponer secretos y conservarlos en el historial incluso después de borrarlos de la versión actual.
No disponer de .env.example
La estructura puede funcionar en el servidor actual, pero otra persona no sabe qué variables son necesarias para reconstruirla.
Mezclar datos con la definición
Dificulta copias, migraciones y control de versiones. Los datos tienen un ciclo de vida diferente.
Crear una estructura demasiado compleja
Una pequeña aplicación no necesita una jerarquía de nivel corporativo. La estructura debe reducir trabajo, no aumentarlo.
Forzar nombres globales para todos los contenedores
Puede dificultar reutilizar la misma definición en distintos entornos y generar colisiones innecesarias.
No documentar dependencias externas
El directorio puede estar perfectamente organizado y aun así ser imposible reconstruir el servicio porque nadie recuerda qué DNS, API, certificado o almacenamiento necesita.
Dejar scripts en /tmp o en el home del administrador
Las tareas auxiliares se convierten en piezas invisibles fuera de la raíz del proyecto.
No distinguir prueba y producción
Dos carpetas casi iguales pueden provocar que un comando se ejecute sobre el entorno equivocado.
Borrar recursos huérfanos sin investigar
Un volumen sin contenedor puede contener datos importantes. La limpieza debe realizarse con inventario.
No retirar proyectos antiguos
Pararlos y olvidarlos acumula carpetas, redes, imágenes, volúmenes y credenciales que aumentan complejidad y superficie de riesgo.
Lista de comprobación
- ¿Existe una raíz común y documentada para los proyectos Docker?
- ¿Cada proyecto tiene un nombre estable y descriptivo?
- ¿La raíz del proyecto contiene la definición activa?
- ¿Puede identificarse qué archivo Compose se utiliza?
- ¿Las versiones antiguas están en control de versiones y no acumuladas como copias?
- ¿Existe una plantilla de variables sin secretos?
- ¿Los archivos locales sensibles están protegidos?
- ¿Los secretos están fuera del contenido distribuible?
- ¿Se distingue configuración común de configuración específica del entorno?
- ¿Los datos persistentes están identificados?
- ¿Los datos no están mezclados de forma indiscriminada con la definición?
- ¿Los scripts específicos están dentro de una ubicación conocida?
- ¿Los scripts tienen nombres y finalidad comprensibles?
- ¿Existe un README útil?
- ¿El README explica finalidad, dependencias y operación básica?
- ¿Los servicios utilizan nombres funcionales?
- ¿Las redes y volúmenes pueden relacionarse con un proyecto?
- ¿Los recursos compartidos están identificados explícitamente?
- ¿Producción y pruebas se distinguen sin ambigüedad?
- ¿La definición está almacenada fuera del propio servidor?
- ¿Los cambios urgentes se incorporan después a la fuente oficial?
- ¿Los permisos impiden modificaciones innecesarias?
- ¿Existe un procedimiento de despliegue repetible?
- ¿Puede reconstruirse el proyecto sin depender de memoria personal?
- ¿Se revisan periódicamente archivos temporales y copias locales?
- ¿Los proyectos sin uso tienen responsable y fecha de retirada?
- ¿La baja de un proyecto incluye redes, credenciales, scripts y documentación?
- ¿El inventario coincide con lo que realmente está desplegado?
Preguntas frecuentes
¿Existe una estructura oficial de carpetas para proyectos Docker?
No existe una única jerarquía obligatoria aplicable a todos los proyectos. Lo importante es adoptar una convención coherente, mantener una raíz reconocible por proyecto y separar definición, configuración, scripts, documentación y datos según sus ciclos de vida.
¿Es correcto guardar los proyectos Docker en /srv?
Puede ser una convención razonable para una infraestructura propia si encaja con la organización del servidor. También pueden utilizarse otras ubicaciones. La decisión debe ser consciente, documentada y constante, evitando repartir proyectos entre directorios personales y rutas improvisadas.
¿Debo crear una carpeta distinta para cada contenedor?
No. Lo normal es organizar por proyecto o aplicación. Un proyecto puede contener varios servicios relacionados, como aplicación, base de datos, caché y procesos auxiliares. Cada contenedor no necesita una raíz administrativa independiente.
¿Conviene tener un único archivo Compose para todos los servicios del servidor?
No suele ser la opción más mantenible cuando existen aplicaciones independientes. Agrupar toda la plataforma en una sola definición acopla ciclos de vida distintos. Es preferible que cada proyecto pueda desplegarse y retirarse con una frontera clara, manteniendo aparte los componentes compartidos.
¿Debe guardarse el archivo .env en Git?
Si contiene secretos o valores locales sensibles, no debería incorporarse al repositorio. Una plantilla como .env.example puede documentar las variables necesarias sin revelar valores reales.
¿Dónde deben guardarse los datos persistentes?
Depende del tipo de aplicación y del mecanismo de almacenamiento utilizado. Lo esencial es que estén identificados y separados del ciclo de vida del contenedor. Pueden residir en volúmenes Docker o en rutas controladas, pero no deben quedar mezclados accidentalmente con archivos reemplazables.
¿Es necesario usar Git para organizar proyectos Docker?
No es un requisito técnico para ejecutar Docker, pero el control de versiones aporta trazabilidad, recuperación de cambios y una fuente de verdad para archivos Compose, configuraciones no secretas, scripts y documentación. Resulta especialmente útil cuando el entorno debe poder reconstruirse.
¿Conviene fijar manualmente container_name?
No es necesario en todos los proyectos. Permitir que la herramienta de composición derive nombres a partir del proyecto y del servicio facilita reutilizar definiciones y reduce colisiones entre entornos. Un nombre fijo debe responder a una necesidad concreta.
¿Cómo puedo saber si una carpeta Docker antigua puede eliminarse?
Primero hay que comprobar si algún contenedor, volumen, red, tarea, proxy o procedimiento depende de ella y si contiene datos o credenciales que deban conservarse. Si existe duda, conviene desactivar de forma controlada, observar dependencias y asignar una fecha de revisión antes de eliminar.
¿Qué documentación mínima debería tener cada proyecto?
Como mínimo, finalidad, servicios incluidos, archivo de despliegue, dependencias, configuración necesaria, ubicación lógica de datos, procedimiento de arranque y parada, comprobación de funcionamiento, referencia de copias y responsable.
¿Tiene sentido separar producción y pruebas en carpetas diferentes?
Sí cuando comparten host, siempre que esa separación se acompañe de nombres, datos, credenciales, dominios y recursos claramente diferenciados. Una carpeta distinta ayuda, pero no sustituye el aislamiento operativo.
¿Cuándo una estructura Docker está demasiado complicada?
Cuando localizar la definición activa, entender qué se despliega o reconstruir un servicio exige recorrer muchas capas, herramientas o excepciones que no aportan una necesidad real. Una estructura útil reduce incertidumbre; si añade más reglas de las que resuelve, conviene simplificarla.
Conclusión
Organizar correctamente los proyectos Docker no exige una herramienta especial ni una jerarquía enorme. Exige decidir unas pocas reglas y aplicarlas de manera constante.
Cada proyecto debe tener una raíz reconocible, un nombre estable y una definición que pueda localizarse sin investigar todo el servidor. Configuración, variables, secretos, scripts, documentación y datos necesitan fronteras claras porque no comparten el mismo ciclo de vida.
La mejor estructura es aquella que permite entrar en un proyecto y comprender rápidamente qué es, cómo se despliega, qué necesita y qué debe conservarse. El resto de la historia debe estar en la fuente oficial, no repartida entre archivos llamados old, final o backup.
La nomenclatura también forma parte de la mantenibilidad. Nombres funcionales, proyectos independientes y recursos identificables permiten que el servidor siga siendo comprensible cuando aumenta el número de servicios o cambia la persona que los administra.
El mantenimiento debe completar la organización inicial: retirar copias temporales, comprobar que el servidor coincide con el repositorio, revisar proyectos sin responsable y eliminar de forma controlada aquello que ya no presta servicio.
Esta disciplina prepara además los siguientes niveles de aprendizaje: estructurar varios servicios independientes, planificar crecimiento, documentar la infraestructura, controlar imágenes, diseñar actualizaciones y gestionar volúmenes persistentes. Cuando la base organizativa es clara, esas tareas dejan de apoyarse en improvisación y pasan a formar parte de un sistema técnico reproducible y mantenible.
ESTUDIO METADATOS desarrolla programas de formación tecnológica orientados a comprender y aplicar estas prácticas en contextos profesionales reales. Puedes consultar sus programas de formación tecnológica para profundizar en Docker, Linux, administración de sistemas, infraestructura, seguridad y automatización.
