Docker Run to Compose - Convertir Comandos Docker a Compose YAML en Línea
Convierte comandos docker run a formato docker-compose.yml. Analiza puertos, volúmenes, variables de entorno y más de 30 flags de Docker al instante — 100% del lado del cliente, tus datos nunca salen de tu navegador.
Preguntas Frecuentes
¿Qué es un conversor de Docker Run a Compose?
Un conversor de Docker Run a Compose es una herramienta que transforma comandos CLI docker run en archivos de configuración YAML docker-compose.yml (Docker Compose). Cuando ejecutas un contenedor con un comando como docker run -d --name nginx -p 80:80 nginx:latest, el conversor genera el YAML equivalente de Compose con services, ports, volumes y otras directivas. Es útil porque los archivos Compose tienen control de versiones, son reproducibles y pueden gestionar aplicaciones multi-contenedor.
¿Cómo uso este conversor de Docker Run a Compose?
Pega tu comando docker run en el área de entrada (con o sin el prefijo docker run). La conversión ocurre automáticamente en tiempo real mientras escribes. Revisa el YAML docker-compose.yml generado en el área de salida. Ajusta las opciones si es necesario: selecciona la versión de Compose (Latest, v3.x o v2.x) y la indentación (2 o 4 espacios). Haz clic en Copiar para copiar el YAML al portapapeles, o en Descargar para guardarlo como archivo docker-compose.yml.
¿Están seguros mis datos? ¿Se envían a un servidor?
Tus datos están 100% seguros y nunca salen de tu navegador. Todo el análisis y conversión se realiza completamente en JavaScript del lado del cliente ejecutándose en tu dispositivo. Ningún comando Docker, variable de entorno, contraseña, clave API ni ningún otro dato se transmite a ningún servidor. Puedes verificarlo desconectándote de internet — la herramienta funciona completamente offline después de la carga inicial de la página.
¿Qué flags de docker run son compatibles?
Este conversor soporta más de 30 flags comunes de Docker run incluyendo: mapeo de puertos (-p), volúmenes (-v, --mount), variables de entorno (-e, --env-file), nombre del contenedor (--name), política de reinicio (--restart), red (--network), directorio de trabajo (-w), usuario (-u), hostname (-h), entrypoint (--entrypoint), etiquetas (-l), capabilities (--cap-add, --cap-drop), modo privilegiado (--privileged), dispositivos (--device), logging (--log-driver, --log-opt), límites de recursos (--memory, --cpus), health checks (--health-cmd, --health-interval), DNS (--dns), hosts extra (--add-host), tmpfs (--tmpfs) y más.
¿Cuál es la diferencia entre las versiones de Docker Compose (v2, v3, latest)?
Docker Compose ha evolucionado a través de varias versiones de especificación. La versión 2.x introdujo services, networks y volumes como claves de nivel superior, usando claves como mem_limit para restricciones de recursos. La versión 3.x fue diseñada para compatibilidad con Docker Swarm y mueve los límites de recursos bajo deploy.resources. Latest (Common Specification) es el formato moderno que omite el campo version y usa la sintaxis más actualizada. Para la mayoría de proyectos nuevos, usa Latest.
¿Puedo pegar comandos docker run multilínea con barras invertidas?
Sí, el conversor soporta completamente comandos multilínea con continuación de línea usando barra invertida (\), que es común al copiar comandos de scripts de shell, documentación o archivos README. La herramienta normaliza automáticamente estos en un solo comando antes de la conversión. Simplemente pega el comando multilínea tal cual.
¿Por qué mi salida convertida se ve diferente de lo esperado?
Razones comunes incluyen: (1) Orden de flags — Compose YAML tiene un orden estándar de claves que puede diferir del orden de flags en tu comando. (2) Valores predeterminados implícitos — Algunos flags como -d (detached) son el predeterminado en Compose y pueden no aparecer explícitamente. (3) Diferencias de versión — Los límites de recursos (--memory, --cpus) se representan de forma diferente en formato Compose v2 vs v3. (4) Flags no soportados — Algunos flags como --rm no tienen equivalente directo en Compose y se muestran con advertencia.
Ejemplos de Código
// Docker Run to Docker Compose converter
// Parses docker run command and generates docker-compose.yml YAML
function parseDockerRun(command) {
const normalized = command.replace(/\\\s*\n/g, ' ').trim();
const stripped = normalized.replace(/^docker\s+run\s+/, '');
const tokens = tokenize(stripped);
const options = {
image: '', name: '', ports: [], volumes: [],
envVars: [], network: '', restart: '',
workdir: '', hostname: '', command: [],
detach: false, privileged: false,
};
let i = 0;
while (i < tokens.length) {
const token = tokens[i];
if (token === '-p' || token === '--publish') {
const val = tokens[++i];
const parts = val.split(':');
options.ports.push({ host: parts[0], container: parts.slice(1).join(':') });
} else if (token === '-v' || token === '--volume') {
const val = tokens[++i];
const parts = val.split(':');
options.volumes.push({ host: parts[0], container: parts[1], mode: parts[2] || '' });
} else if (token === '-e' || token === '--env') {
const val = tokens[++i];
const eq = val.indexOf('=');
options.envVars.push({ key: val.substring(0, eq), value: val.substring(eq + 1) });
} else if (token === '--name') { options.name = tokens[++i]; }
else if (token === '--restart') { options.restart = tokens[++i]; }
else if (token === '--network') { options.network = tokens[++i]; }
else if (token === '-d') { options.detach = true; }
else if (!token.startsWith('-')) {
options.image = token;
options.command = tokens.slice(i + 1);
break;
}
i++;
}
return options;
}
function tokenize(input) {
const tokens = [];
let current = '', inSQ = false, inDQ = false;
for (const char of input) {
if (char === "'" && !inDQ) { inSQ = !inSQ; }
else if (char === '"' && !inSQ) { inDQ = !inDQ; }
else if (char === ' ' && !inSQ && !inDQ) {
if (current) { tokens.push(current); current = ''; }
} else { current += char; }
}
if (current) tokens.push(current);
return tokens;
}
function generateComposeYaml(options, indent = 2) {
const pad = ' '.repeat(indent);
const p2 = pad.repeat(2), p3 = pad.repeat(3);
const name = options.name || options.image.split('/').pop().split(':')[0] || 'app';
let yaml = `services:\n${pad}${name}:\n${p2}image: ${options.image}\n`;
if (options.name) yaml += `${p2}container_name: ${options.name}\n`;
if (options.restart) yaml += `${p2}restart: ${options.restart}\n`;
if (options.ports.length > 0) {
yaml += `${p2}ports:\n`;
options.ports.forEach(p => yaml += `${p3}- "${p.host}:${p.container}"\n`);
}
if (options.volumes.length > 0) {
yaml += `${p2}volumes:\n`;
options.volumes.forEach(v => {
const mode = v.mode ? `:${v.mode}` : '';
yaml += `${p3}- ${v.host}:${v.container}${mode}\n`;
});
}
if (options.envVars.length > 0) {
yaml += `${p2}environment:\n`;
options.envVars.forEach(e => yaml += `${p3}- ${e.key}=${e.value}\n`);
}
if (options.network) {
yaml += `${p2}networks:\n${p3}- ${options.network}\n`;
}
return yaml;
}
// Example usage
const cmd = 'docker run -d --name nginx -p 80:80 -v ./html:/usr/share/nginx/html nginx:latest';
const opts = parseDockerRun(cmd);
console.log(generateComposeYaml(opts));