Docker Run to Compose - Convert Docker Commands to Compose YAML Online
Convert docker run commands to docker-compose.yml format. Parse ports, volumes, environment variables, and 30+ Docker flags instantly — 100% client-side, your data never leaves your browser.
Frequently Asked Questions
What is a Docker Run to Compose converter?
A Docker Run to Compose converter is a tool that transforms docker run CLI commands into docker-compose.yml (Docker Compose) YAML configuration files. When you run a container with a command like docker run -d --name nginx -p 80:80 -v ./html:/usr/share/nginx/html nginx:latest, the converter generates the equivalent Compose YAML with services, ports, volumes, and other directives. This is useful because Compose files are version-controlled, reproducible, and can manage multi-container applications, whereas docker run commands are often used ad-hoc and can be long and error-prone.
How do I use this Docker Run to Compose converter?
Paste your docker run command into the input area (with or without the docker run prefix). The conversion happens automatically in real-time as you type. Review the generated docker-compose.yml YAML in the output area. Adjust options if needed: select the Compose version (Latest, v3.x, or v2.x) and indentation (2 or 4 spaces). Click the Copy button to copy the YAML to your clipboard, or Download to save it as a docker-compose.yml file. If you are new to Docker, try the Example buttons (Basic, Intermediate, Advanced) to see how different flags are converted.
Is my data safe? Does it get sent to a server?
Your data is 100% safe and never leaves your browser. All parsing and conversion happens entirely in client-side JavaScript running on your device. No Docker commands, environment variables, passwords, API keys, or any other data is transmitted to any server, stored in any database, or logged anywhere. You can verify this by disconnecting from the internet — the tool works fully offline after the initial page load. This is especially important for DevOps workflows where docker run commands often contain sensitive credentials in environment variables.
Which docker run flags are supported?
This converter supports 30+ commonly used Docker run flags including: port mapping (-p), volumes (-v, --mount), environment variables (-e, --env-file), container name (--name), restart policy (--restart), network (--network), working directory (-w), user (-u), hostname (-h), entrypoint (--entrypoint), labels (-l), capabilities (--cap-add, --cap-drop), privileged mode (--privileged), devices (--device), logging (--log-driver, --log-opt), resource limits (--memory, --cpus), health checks (--health-cmd, --health-interval, --health-timeout, --health-retries), DNS (--dns), extra hosts (--add-host), tmpfs (--tmpfs), and more. Flags without a direct Compose equivalent (like --rm) will generate a warning note.
What is the difference between Docker Compose versions (v2, v3, latest)?
Docker Compose has evolved through several specification versions. Version 2.x introduced services, networks, and volumes as top-level keys, and uses keys like mem_limit for resource constraints. Version 3.x was designed for Docker Swarm compatibility and moves resource limits under deploy.resources. Latest (Common Specification) is the modern format that omits the version field entirely and uses the most up-to-date syntax. For most new projects, use Latest unless you have specific compatibility requirements.
Can I paste multi-line docker run commands with backslashes?
Yes, the converter fully supports multi-line commands with backslash (\) line continuation, which is common when copying commands from shell scripts, documentation, or README files. The tool automatically normalizes these into a single command before conversion. Simply paste the entire multi-line command as-is.
Why does my converted output look different from what I expected?
Common reasons include: (1) Flag order — Compose YAML has a standard key ordering that may differ from your flag order in the command. (2) Implicit defaults — Some flags like -d (detached) are the default in Compose and may not appear explicitly. (3) Version differences — Resource limits (--memory, --cpus) are represented differently in v2 vs v3 Compose format. (4) Complex flags — Flags like --mount with multiple sub-options may be expanded into the long-form volume syntax. (5) Unsupported flags — Some Docker run flags like --rm have no direct Compose equivalent and will be noted with a warning rather than converted.
Code Examples
// 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));