50 Most-Used Docker Commands
π³ 50 Most-Used Docker Commands with Interactive Emulator
Docker helps you build, share, and run applications in containers. This WordPress-ready guide combines a practical command table, an emulator, guided challenges, a visual canvas, and Dockerfile + Docker Compose practice without connecting to a real Docker daemon.
π Responsive Docker Emulator
Type a command, choose a suggestion, or click βUse in Emulatorβ from the table. The emulator shows simulated output, guided feedback, and visual movement across images, containers, volumes, networks, Dockerfile, and Compose services.
docker version to start your Docker session.Docker CLI
FREE challenges are available now. LITE, PRO, and PRO Plus will be available soon with more guided labs and deeper scoring.
docker versionThis challenge focuses on Docker CLI operations. Dockerfile and Compose examples appear in the last three FREE challenges.
compose.yaml: This challenge focuses on Docker CLI operations. Dockerfile and Compose examples appear in the last three FREE challenges.
waiting$ Waiting for a Docker command... Run a command to see simulated Docker output here.
$ Docker Emulator Ready Tip: choose a command from the table and click "Use in Emulator".
On small screens, the table automatically becomes cards so content is not cut off.
| # | Command / Parameter | Description | Example | Actions |
|---|---|---|---|---|
| 1 | docker version |
Show Docker client and server version information. | docker version |
|
| 2 | docker info |
Display system-wide Docker information. | docker info |
|
| 3 | docker login |
Authenticate to a container registry. | docker login |
|
| 4 | docker logout |
Log out from a container registry. | docker logout |
|
| 5 | docker search |
Search Docker Hub for images. | docker search nginx |
|
| 6 | docker pull |
Download an image from a registry. | docker pull nginx:latest |
|
| 7 | docker images |
List local images. | docker images |
|
| 8 | docker image inspect |
Inspect image metadata. | docker image inspect nginx:latest |
|
| 9 | docker image history |
Show the layer history of an image. | docker image history nginx:latest |
|
| 10 | docker tag |
Create a new tag for an image. | docker tag nginx:latest local-nginx:v1 |
|
| 11 | docker build |
Build an image from a Dockerfile. | docker build -t demo-app:1.0 . |
|
| 12 | docker build --no-cache |
Build an image without using cache. | docker build --no-cache -t demo-app:clean . |
|
| 13 | docker run |
Create and run a container from an image. | docker run hello-world |
|
| 14 | docker run -d |
Run a container in detached mode. | docker run -d --name web -p 8080:80 nginx:latest |
|
| 15 | docker ps |
List running containers. | docker ps |
|
| 16 | docker ps -a |
List all containers, including stopped ones. | docker ps -a |
|
| 17 | docker logs |
Show container logs. | docker logs web |
|
| 18 | docker logs -f |
Follow container logs in real time. | docker logs -f web |
|
| 19 | docker exec |
Run a command inside a running container. | docker exec -it web sh |
|
| 20 | docker stop |
Stop a running container. | docker stop web |
|
| 21 | docker start |
Start a stopped container. | docker start web |
|
| 22 | docker restart |
Restart a container. | docker restart web |
|
| 23 | docker rm |
Remove a stopped container. | docker rm web |
|
| 24 | docker rmi |
Remove a local image. | docker rmi local-nginx:v1 |
|
| 25 | docker container prune |
Remove stopped containers. | docker container prune -f |
|
| 26 | docker image prune -a |
Remove unused images. | docker image prune -a -f |
|
| 27 | docker volume create |
Create a named volume. | docker volume create app-data |
|
| 28 | docker volume ls |
List Docker volumes. | docker volume ls |
|
| 29 | docker volume inspect |
Inspect a volume. | docker volume inspect app-data |
|
| 30 | docker volume rm |
Remove a Docker volume. | docker volume rm app-data |
|
| 31 | docker network create |
Create a Docker network. | docker network create app-net |
|
| 32 | docker network ls |
List Docker networks. | docker network ls |
|
| 33 | docker network inspect |
Inspect a Docker network. | docker network inspect app-net |
|
| 34 | docker network connect |
Connect a container to a network. | docker network connect app-net web |
|
| 35 | docker network rm |
Remove a Docker network. | docker network rm app-net |
|
| 36 | docker cp |
Copy files between host and container. | docker cp index.html web:/usr/share/nginx/html/index.html |
|
| 37 | docker stats |
Show live resource usage statistics. | docker stats --no-stream |
|
| 38 | docker top |
Display running processes inside a container. | docker top web |
|
| 39 | docker inspect |
Return low-level Docker object information. | docker inspect web |
|
| 40 | docker events |
Monitor Docker daemon events. | docker events --since 10m |
|
| 41 | docker compose version |
Show Docker Compose version. | docker compose version |
|
| 42 | docker compose up |
Create and start services from compose.yaml. | docker compose up -d |
|
| 43 | docker compose ps |
List containers managed by Compose. | docker compose ps |
|
| 44 | docker compose logs |
Show service logs from Compose. | docker compose logs -f |
|
| 45 | docker compose exec |
Run a command inside a Compose service container. | docker compose exec web sh |
|
| 46 | docker compose restart |
Restart Compose services. | docker compose restart |
|
| 47 | docker compose down |
Stop and remove Compose containers and networks. | docker compose down |
|
| 48 | docker compose down -v |
Stop Compose services and remove named volumes too. | docker compose down -v |
|
| 49 | docker compose build |
Build or rebuild Compose services. | docker compose build --no-cache |
|
| 50 | docker compose pull |
Pull service images defined in compose.yaml. | docker compose pull |
π§ Conclusion
This Docker emulator is ready. The FREE pack contains the active challenges now, while LITE, PRO, and PRO Plus are visible as upcoming expansion tiers for deeper labs, scoring, downloadable runbooks, and advanced Docker Compose scenarios.
(function(){
function initDockerBlog(){
const dockerData = [{"id": 1, "cmd": "docker version", "desc": "Show Docker client and server version information.", "ex": "docker version", "out": "Client: Docker Engine - Community\n Version: 27.x\nServer: Docker Engine - Community\n Engine: running"}, {"id": 2, "cmd": "docker info", "desc": "Display system-wide Docker information.", "ex": "docker info", "out": "Containers: 3\n Images: 7\n Server Version: 27.x\n Storage Driver: overlay2"}, {"id": 3, "cmd": "docker login", "desc": "Authenticate to a container registry.", "ex": "docker login", "out": "Username: demo-user\nPassword: ********\nLogin Succeeded"}, {"id": 4, "cmd": "docker logout", "desc": "Log out from a container registry.", "ex": "docker logout", "out": "Removing login credentials for https://index.docker.io/v1/"}, {"id": 5, "cmd": "docker search", "desc": "Search Docker Hub for images.", "ex": "docker search nginx", "out": "NAME DESCRIPTION STARS\nnginx Official build of Nginx 20000+"}, {"id": 6, "cmd": "docker pull", "desc": "Download an image from a registry.", "ex": "docker pull nginx:latest", "out": "latest: Pulling from library/nginx\nDigest: sha256:demo\nStatus: Downloaded newer image for nginx:latest"}, {"id": 7, "cmd": "docker images", "desc": "List local images.", "ex": "docker images", "out": "REPOSITORY TAG IMAGE ID SIZE\nnginx latest 605c77e624dd 187MB\nhello-world latest d2c94e258dcb 13kB"}, {"id": 8, "cmd": "docker image inspect", "desc": "Inspect image metadata.", "ex": "docker image inspect nginx:latest", "out": "[{\n \"RepoTags\": [\"nginx:latest\"],\n \"Architecture\": \"amd64\",\n \"Os\": \"linux\"\n}]"}, {"id": 9, "cmd": "docker image history", "desc": "Show the layer history of an image.", "ex": "docker image history nginx:latest", "out": "IMAGE CREATED BY SIZE\n605c77e624dd CMD [\"nginx\" \"-g\" ...] 0B\ndocker version to start your Docker session.", "workspace": "DOCKER WORKSPACE", "pack": "Pack", "free": "Free", "lite": "Lite", "pro": "Pro", "proPlus": "Pro Plus", "coming_suffix": "Coming soon", "scope": "RESOURCE SCOPE", "output": "WORKSPACE OUTPUT", "waiting": "waiting", "copy_table": "Copy Full Table (CSV)", "headers": ["#", "Command / Parameter", "Description", "Example", "Actions"], "copy_cmd": "Copy Command", "copy_ex": "Copy Example", "use": "Use in Emulator", "copied": "Copied!", "conclusion_title": "π§ Conclusion", "conclusion": "This Docker emulator is ready. The FREE pack contains the active challenges now, while LITE, PRO, and PRO Plus are visible as upcoming expansion tiers for deeper labs, scoring, downloadable runbooks, and advanced Docker Compose scenarios.", "modal_title": "Expected output (simulated)", "copy_output": "Copy Output", "close": "Close", "ready": "$ Docker Emulator Ready\nTip: choose a command from the table and click \"Use in Emulator\".", "empty": "Type or select a Docker command first.", "no_command": "Type a Docker command first.", "not_found": "Command not included in the emulator dataset. Try: docker version, docker ps, docker run hello-world, docker compose up -d, or docker build -t demo-app:1.0 .", "idle": "No changes yet: run a command to move simulated Docker resources.", "loaded": "Loaded scope:", "next_step": "Current step:", "already": "This challenge is already complete. Try another challenge.", "wrong_order": "That command belongs to a later step. First run:", "expected": "Expected runbook commands", "feedback_start": "Run the next command to receive guided feedback.", "coming": "Coming soon", "free_challenges": "FREE challenges are available now. LITE, PRO, and PRO Plus will be available soon with more guided labs and deeper scoring.", "active_tab": "docker-runbook.md", "table_note": "On small screens, the table automatically becomes cards so content is not cut off.", "visual_title": "Docker Visual Canvas", "visual_idle": "No visual action yet.", "last_action": "Last action:", "explain_title": "What is happening?", "explain_idle": "Run a Docker command to see the emulator explain how images, containers, volumes, networks, Dockerfile, and Compose change.", "dockerfile_title": "Dockerfile used in this challenge", "compose_title": "compose.yaml used in this challenge", "compose_explain_title": "How Docker Compose uses it", "no_dockerfile": "This challenge focuses on Docker CLI operations. Dockerfile and Compose examples appear in the last three FREE challenges.", "pkg_message": "This package is prepared for future expansion. FREE is active now; LITE, PRO, and PRO Plus will be enabled soon.", "score_suffix": "challenges"};
const byId = (id) => document.getElementById(id);
const table = byId('docker-table');
const datalist = byId('docker-command-suggestions');
const terminal = byId('docker-terminal');
const input = byId('docker-command-input');
const challengeEl = byId('docker-challenge');
const promptModal = byId('docker-prompt-modal');
const promptText = byId('docker-prompt-text');
const promptCopyBtn = byId('docker-prompt-copy-btn');
const promptCloseBtn = byId('docker-prompt-close-btn');
const tierSelect = byId('docker-tier-select');
const challengeList = byId('docker-challenge-list');
const resourceTree = byId('docker-resource-tree');
const resourceCanvas = byId('docker-resource-canvas');
const resourceCount = byId('docker-resource-count');
const scoreEl = byId('docker-score');
const activeTab = byId('docker-active-tab');
const challengeTitleEl = byId('docker-challenge-title');
const challengeTaskEl = byId('docker-challenge-task');
const challengeExpectedEl = byId('docker-challenge-expected');
const challengeHintEl = byId('docker-challenge-hint');
const feedbackEl = byId('docker-feedback');
const outputCommandEl = byId('docker-output-command');
const inlineOutputEl = byId('docker-inline-output');
const visualMeta = byId('docker-visual-meta');
const activityLog = byId('docker-activity-log');
const explainTitle = byId('docker-explain-title');
const explainText = byId('docker-explain-text');
const dockerfileText = byId('dockerfile-text');
const composeText = byId('compose-text');
const composeExplain = byId('compose-explain-text');
if(!table || !terminal || !input || !datalist){ return; }
let activeTier = 'free';
let activeChallengeIndex = 0;
const completedChallenges = new Set();
const challengeProgress = new Map();
let dockerResources = [];
let activeResourceId = 'host';
let visualAction = 'query';
let visualActivity = [t.idle];
dockerData.forEach((row) => { [row.cmd, row.ex].forEach((value) => { const option = document.createElement('option'); option.value = value; datalist.appendChild(option); }); });
table.addEventListener('click', (ev) => { const button = ev.target.closest('button[data-id]'); if(!button){ return; } const row = dockerData.find((item) => String(item.id) === String(button.dataset.id)); if(!row){ return; } if(button.classList.contains('copy-command-btn')){ copyText(row.cmd, button); return; } if(button.classList.contains('copy-example-btn')){ copyText(row.ex, button); return; } if(button.classList.contains('use-cmd-btn')){ input.value = row.ex; input.focus(); input.scrollIntoView({behavior:'smooth', block:'center'}); } });
byId('docker-run-btn')?.addEventListener('click', () => runCommand(input.value)); byId('docker-prompt-btn')?.addEventListener('click', () => { const value = input.value.trim(); if(!value){ window.alert(t.empty); return; } const result = resolveOutput(value); setWorkspaceOutput(value, result); showPromptLikeOutput(result); }); byId('docker-random-btn')?.addEventListener('click', () => { selectNextChallenge(); input.value = ''; input.focus(); }); byId('docker-clear-btn')?.addEventListener('click', () => { terminal.textContent = t.ready; resetWorkspaceOutput(); resetDockerVisual(); }); input.addEventListener('keydown', (ev) => { if(ev.key === 'Enter'){ ev.preventDefault(); runCommand(input.value); } }); byId('copy-docker-table')?.addEventListener('click', copyTableCsv); tierSelect?.addEventListener('change', () => { activeTier = tierSelect.value; activeChallengeIndex = 0; renderChallengeTrainer(); }); promptCopyBtn?.addEventListener('click', () => copyText(promptText?.textContent || '', promptCopyBtn)); promptCloseBtn?.addEventListener('click', hidePromptLikeOutput); promptModal?.addEventListener('click', (ev) => { if(ev.target === promptModal){ hidePromptLikeOutput(); } }); document.addEventListener('keydown', (ev) => { if(ev.key === 'Escape'){ hidePromptLikeOutput(); } });
initDockerWorkspace();
function runCommand(raw){
const cmd = (raw || '').trim();
if(!cmd){ appendToTerminal('$ (no command)\n' + t.no_command); setWorkspaceOutput('no command', t.no_command); return; }
const result = resolveOutput(cmd);
appendToTerminal('$ ' + cmd + '\n' + result);
setWorkspaceOutput(cmd, result);
evaluateActiveChallenge(cmd);
updateDockerVisual(cmd);
}
function initDockerWorkspace(){ resetDockerVisual(); renderChallengeTrainer(); resetWorkspaceOutput(); }
function getActiveChallenges(){ return challengePacks[activeTier] || []; }
function getActiveChallenge(){ const list = getActiveChallenges(); return list[activeChallengeIndex] || null; }
function getSteps(challenge){ return Array.isArray(challenge?.steps) ? challenge.steps : []; }
function getProgress(challenge){ return Math.min(challengeProgress.get(challenge.id) || 0, getSteps(challenge).length); }
function renderChallengeTrainer(){
const list = getActiveChallenges();
if(scoreEl){ scoreEl.textContent = list.length ? list.filter((c) => completedChallenges.has(c.id)).length + '/' + list.length : t.coming; }
if(!list.length){
if(challengeList){ challengeList.innerHTML = ''; }
if(challengeEl){ challengeEl.innerHTML = '' + escapeHtml(t.coming) + ' β ' + escapeHtml(t.pkg_message); }
if(challengeTitleEl){ challengeTitleEl.textContent = t.coming; }
if(challengeTaskEl){ challengeTaskEl.textContent = t.pkg_message; }
if(challengeExpectedEl){ challengeExpectedEl.textContent = t.coming; }
if(challengeHintEl){ challengeHintEl.textContent = t.free_challenges; }
setFeedback('neutral', t.pkg_message);
renderDockerfilePanel(null);
return;
}
activeChallengeIndex = Math.min(activeChallengeIndex, list.length - 1);
if(challengeList){
challengeList.innerHTML = list.map((challenge, idx) => {
const steps = getSteps(challenge); const progress = getProgress(challenge); const next = steps[Math.min(progress, Math.max(steps.length - 1, 0))]; const done = completedChallenges.has(challenge.id);
return '';
}).join('');
challengeList.querySelectorAll('.docker-challenge-item[data-index]').forEach((btn) => btn.addEventListener('click', () => { activeChallengeIndex = Number(btn.dataset.index || 0); renderChallengeTrainer(); }));
}
renderActiveChallenge();
}
function renderActiveChallenge(){
const challenge = getActiveChallenge(); if(!challenge){ return; }
const steps = getSteps(challenge); const progress = getProgress(challenge); const next = steps[Math.min(progress, Math.max(steps.length - 1, 0))];
if(challengeEl){ challengeEl.innerHTML = 'Challenge ' + (activeChallengeIndex + 1) + ': ' + escapeHtml(challenge.title) + ' Step ' + Math.min(progress + 1, steps.length) + '/' + steps.length + ''; }
if(activeTab){ activeTab.textContent = challenge.visualTab || t.active_tab; }
if(challengeTitleEl){ challengeTitleEl.textContent = challenge.title; }
if(challengeTaskEl){ challengeTaskEl.textContent = challenge.task; }
if(challengeExpectedEl){ challengeExpectedEl.textContent = steps.map((s, idx) => (idx + 1) + '. ' + s.command).join('\n'); }
if(challengeHintEl){ challengeHintEl.textContent = (completedChallenges.has(challenge.id) ? challenge.hint : t.next_step + ' ' + (next ? next.command : 'complete') + '. ' + (next?.failure || challenge.hint)); }
setFeedback(completedChallenges.has(challenge.id) ? 'correct' : 'neutral', completedChallenges.has(challenge.id) ? challenge.success : t.feedback_start);
renderDockerfilePanel(challenge);
seedVisualResources(challenge); renderDockerVisual();
}
function renderDockerfilePanel(challenge){
if(dockerfileText){ dockerfileText.textContent = challenge?.dockerfile || t.no_dockerfile; }
if(composeText){ composeText.textContent = challenge?.compose || 'compose.yaml: ' + t.no_dockerfile; }
if(composeExplain){ composeExplain.textContent = challenge?.composeExplain || t.no_dockerfile; }
}
function evaluateActiveChallenge(cmd){
const challenge = getActiveChallenge(); if(!challenge){ return; }
const steps = getSteps(challenge); const index = getProgress(challenge); if(index >= steps.length){ setFeedback('correct', t.already); return; }
const step = steps[index]; const normalizedCmd = normalize(cmd); const patterns = step.accepts?.length ? step.accepts : [step.command];
const matched = patterns.some((pattern) => matches(normalizedCmd, pattern));
if(matched){ const nextIndex = index + 1; challengeProgress.set(challenge.id, nextIndex); if(nextIndex >= steps.length){ completedChallenges.add(challenge.id); renderChallengeTrainer(); setFeedback('correct', step.success + ' ' + challenge.success); return; } renderChallengeTrainer(); setFeedback('correct', step.success + ' ' + t.next_step + ' ' + steps[nextIndex].command); return; }
const future = steps.findIndex((s, idx) => idx > index && (s.accepts?.length ? s.accepts : [s.command]).some((pattern) => matches(normalizedCmd, pattern)));
setFeedback('wrong', future >= 0 ? t.wrong_order + ' ' + step.command : step.failure + ' Expected: ' + step.command);
}
function setFeedback(kind, text){ if(feedbackEl){ feedbackEl.className = 'docker-feedback ' + (kind || 'neutral'); feedbackEl.textContent = text; } }
function matches(normalizedCmd, pattern){ const p = normalize(pattern); return p.endsWith('*') ? normalizedCmd.startsWith(p.slice(0, -1).trim()) : normalizedCmd === p; }
function seedVisualResources(challenge){
const base = [{id:'host', type:'Docker Host', name:'Local Docker Engine', state:'Ready'}];
dockerResources = [...base, ...(challenge.resources || [])].filter((item, idx, arr) => arr.findIndex((x) => x.id === item.id) === idx);
activeResourceId = dockerResources[0]?.id || 'host'; visualAction = 'query'; visualActivity = [t.loaded + ' ' + challenge.title];
}
function resetDockerVisual(){ dockerResources = [{id:'host', type:'Docker Host', name:'Local Docker Engine', state:'Ready'}]; activeResourceId = 'host'; visualAction = 'query'; visualActivity = [t.idle]; setExplanation(t.explain_title, t.explain_idle); renderDockerVisual(); }
function updateDockerVisual(cmd){
const n = normalize(cmd); let touched = 'host'; let action = 'query'; let title = t.explain_title; let explanation = t.explain_idle;
if(n.includes('docker login') || n.includes('docker logout') || n.includes('docker search')){ touched = 'registry'; action = 'query'; upsert({id:'registry', type:'Registry', name:'Docker Hub / Registry', state:n.includes('logout') ? 'Logged out' : 'Connected'}); title = 'Registry'; explanation = 'Docker is interacting with a registry to authenticate, search, or manage access to images.'; }
else if(n.includes('docker pull')){ touched = 'nginx'; action = 'created'; upsert({id:'nginx', type:'Image', name:'nginx:latest', state:'Pulled'}); title = 'Image pulled'; explanation = 'The image is downloaded into the local image cache. Containers can now be created from this image.'; }
else if(n.includes('docker build')){ touched = n.includes('python-api') ? 'python-api' : (n.includes('static-site') ? 'static-site' : (n.includes('node-demo') ? 'node-demo' : 'demo-app')); action = 'created'; upsert({id:'dockerfile', type:'Dockerfile', name:'Dockerfile', state:'Build recipe'}); upsert({id:touched, type:'Image', name:touched, state:'Built'}); title = 'Dockerfile build'; explanation = 'Docker reads the Dockerfile instructions, creates image layers, and tags the resulting image for reuse.'; }
else if(n.includes('docker images') || n.includes('image inspect') || n.includes('image history') || n.includes('docker tag')){ touched = 'image-cache'; action = 'query'; upsert({id:'image-cache', type:'Image Cache', name:'Local images', state:'Visible'}); title = 'Image cache'; explanation = 'Docker is reading or tagging image metadata in the local cache.'; }
else if(n.includes('docker rmi') || n.includes('image prune')){ touched = 'image-cache'; action = 'deleted'; upsert({id:'image-cache', type:'Image Cache', name:'Unused images', state:'Pruned'}); title = 'Image cleanup'; explanation = 'Docker removes unused image tags and layers to reclaim local disk space.'; }
else if(n.includes('docker run')){ touched = n.includes('hello-world') ? 'hello-world' : 'web'; action = 'running'; upsert({id:'nginx', type:'Image', name:'nginx:latest', state:'Available'}); upsert({id:touched, type:'Container', name:touched, state:'Running'}); title = 'Container created'; explanation = 'Docker creates a writable container layer from the image and starts the configured process.'; }
else if(n.includes('docker ps') || n.includes('docker logs') || n.includes('docker exec') || n.includes('docker stats') || n.includes('docker top') || n.includes('docker inspect') || n.includes('docker events') || n.includes('docker cp')){ touched = n.includes('cp') ? 'index' : 'web'; action = n.includes('cp') ? 'created' : 'query'; if(n.includes('cp')){ upsert({id:'index', type:'File', name:'index.html', state:'Copied'}); } upsert({id:'web', type:'Container', name:'web', state:'Running'}); title = 'Container operation'; explanation = 'Docker is reading logs, executing commands, copying files, inspecting metadata, or observing runtime behavior.'; }
else if(n.includes('docker stop')){ touched = 'web'; action = 'stopped'; upsert({id:'web', type:'Container', name:'web', state:'Stopped'}); title = 'Container stopped'; explanation = 'Docker sends a stop signal and the container process exits while the container object remains available.'; }
else if(n.includes('docker start') || n.includes('docker restart')){ touched = 'web'; action = 'running'; upsert({id:'web', type:'Container', name:'web', state:'Running'}); title = 'Container running'; explanation = 'Docker starts or restarts the container process from its existing configuration.'; }
else if(n.includes('docker rm') || n.includes('container prune')){ touched = 'web'; action = 'deleted'; upsert({id:'web', type:'Container', name:'web', state:'Removed'}); title = 'Container cleanup'; explanation = 'Docker removes stopped container objects and releases their writable layers.'; }
else if(n.includes('docker volume create') || n.includes('docker volume ls') || n.includes('docker volume inspect')){ touched = 'app-data'; action = n.includes('create') ? 'created' : 'query'; upsert({id:'app-data', type:'Volume', name:'app-data', state:'Persistent'}); title = 'Persistent storage'; explanation = 'Volumes store data outside the container lifecycle so data can survive container recreation.'; }
else if(n.includes('docker volume rm')){ touched = 'app-data'; action = 'deleted'; upsert({id:'app-data', type:'Volume', name:'app-data', state:'Removed'}); title = 'Volume removed'; explanation = 'Docker deletes the named volume and its persisted data in this simulated lab.'; }
else if(n.includes('docker network')){ touched = 'app-net'; action = n.includes(' rm') ? 'deleted' : (n.includes('create') || n.includes('connect') ? 'created' : 'query'); upsert({id:'app-net', type:'Network', name:'app-net', state:n.includes(' rm') ? 'Removed' : 'Connected'}); if(n.includes('connect')){ upsert({id:'web', type:'Container', name:'web', state:'Connected'}); } title = 'Network operation'; explanation = 'Docker networks provide service discovery and isolated communication between containers.'; }
else if(n.includes('docker compose')){ touched = 'compose'; action = n.includes('down') ? 'deleted' : (n.includes('up') || n.includes('build') || n.includes('pull') ? 'created' : 'query'); upsert({id:'compose', type:'Compose Project', name:'demo', state:n.includes('down') ? 'Stopped' : 'Running'}); if(!n.includes('down')){ upsert({id:'demo-web', type:'Service', name:'web', state:'Running'}); upsert({id:'demo-db', type:'Service', name:'db/api', state:'Running'}); upsert({id:'compose-network', type:'Network', name:'demo_default', state:'Created'}); } if(n.includes('down -v')){ upsert({id:'compose-volume', type:'Volume', name:'demo_db-data', state:'Removed'}); } title = 'Docker Compose'; explanation = 'Compose reads compose.yaml and coordinates services, containers, networks, volumes, builds, ports, and environment variables as one project.'; }
activeResourceId = touched; visualAction = action; visualActivity.unshift('$ ' + cmd + ' -> ' + action + ' ' + touched); visualActivity = visualActivity.slice(0, 6); setExplanation(title, explanation); renderDockerVisual();
}
function setExplanation(title, text){ if(explainTitle){ explainTitle.textContent = title; } if(explainText){ explainText.textContent = text; } }
function upsert(resource){ const idx = dockerResources.findIndex((item) => item.id === resource.id); if(idx >= 0){ dockerResources[idx] = {...dockerResources[idx], ...resource}; } else { dockerResources.push(resource); } }
function renderDockerVisual(){
if(resourceCount){ resourceCount.textContent = String(dockerResources.length); }
if(visualMeta){ visualMeta.textContent = t.last_action + ' ' + visualAction + ' β’ ' + activeResourceId; }
if(resourceTree){ resourceTree.innerHTML = dockerResources.map((r) => '
' + escapeHtml(r.type) + '
').join(''); } if(resourceCanvas){ resourceCanvas.innerHTML = dockerResources.map((r) => '
' + escapeHtml(r.state) + '
').join(''); } if(activityLog){ activityLog.innerHTML = visualActivity.map((line) => '
').join(''); } } function stateClass(resource){ const s = normalize(resource.state); if(s.includes('running') || s.includes('ready') || s.includes('listo') || s.includes('built') || s.includes('construida') || s.includes('persistent') || s.includes('created') || s.includes('cread') || s.includes('connected')){ return 'running'; } if(s.includes('stop') || s.includes('pruned') || s.includes('limpi')){ return 'stopped'; } if(s.includes('remove') || s.includes('elimin') || s.includes('deleted')){ return 'deleted'; } return 'created'; } function resolveOutput(inputCmd){ const n = normalize(inputCmd); const exact = dockerData.find((x) => normalize(x.cmd) === n || normalize(x.ex) === n); if(exact){ return exact.out; } const prefix = dockerData.find((x) => n.startsWith(normalize(x.cmd) + ' ') || normalize(x.cmd).startsWith(n)); if(prefix){ return prefix.out; } if(n.startsWith('docker ') && n.includes(' --help')){ return 'Docker help (simulated)\nUsage, examples, options, and subcommands displayed.'; } return t.not_found; } function setWorkspaceOutput(command, text){ if(outputCommandEl){ outputCommandEl.textContent = String(command || t.waiting); } if(inlineOutputEl){ inlineOutputEl.textContent = String(text || '').trim() || '(No simulated output)'; inlineOutputEl.scrollTop = 0; } } function resetWorkspaceOutput(){ setWorkspaceOutput(t.waiting, '$ Waiting for a Docker command...\nRun a command to see simulated Docker output here.'); } function appendToTerminal(text){ terminal.textContent += '\n\n' + text; terminal.scrollTop = terminal.scrollHeight; } function showPromptLikeOutput(text){ const printable = String(text || '').trim() || '(No simulated output)'; if(promptModal && promptText){ promptText.textContent = printable; promptModal.classList.add('is-open'); promptModal.style.setProperty('display','flex','important'); promptModal.setAttribute('aria-hidden','false'); promptText.focus(); return; } window.alert(printable); } function hidePromptLikeOutput(){ if(promptModal){ promptModal.classList.remove('is-open'); promptModal.style.setProperty('display','none','important'); promptModal.setAttribute('aria-hidden','true'); } } function copyTableCsv(){ const headers = t.headers; let csv = headers.map(csvCell).join(',') + '\n'; dockerData.forEach((row) => { csv += [row.id,row.cmd,row.desc,row.ex].map(csvCell).join(',') + '\n'; }); copyRaw(csv, byId('copy-docker-table')); } function copyText(text, button){ copyRaw(text, button); } function copyRaw(text, button){ const done = () => flash(button); if(navigator.clipboard && window.isSecureContext){ navigator.clipboard.writeText(String(text)).then(done).catch(() => fallbackCopy(text, done)); } else { fallbackCopy(text, done); } } function fallbackCopy(text, done){ const ta = document.createElement('textarea'); ta.value = String(text); ta.setAttribute('readonly',''); ta.style.position = 'fixed'; ta.style.left = '-9999px'; document.body.appendChild(ta); ta.select(); try{ document.execCommand('copy'); } catch(e){} document.body.removeChild(ta); done(); } function flash(button){ if(!button){ return; } const old = button.textContent; button.textContent = t.copied; button.classList.add('ok'); setTimeout(() => { button.textContent = old; button.classList.remove('ok'); }, 1200); } function selectNextChallenge(){ const list = getActiveChallenges(); if(!list.length){ renderChallengeTrainer(); return; } activeChallengeIndex = (activeChallengeIndex + 1) % list.length; renderChallengeTrainer(); } function csvCell(value){ return '"' + String(value).replace(/"/g,'""') + '"'; } function normalize(value){ return String(value || '').toLowerCase().replace(/\s+/g,' ').trim(); } function escapeHtml(value){ return String(value).replace(/&/g,'&').replace(//g,'>').replace(/"/g,'"').replace(/'/g,'''); } } if(document.readyState === 'loading'){ document.addEventListener('DOMContentLoaded', initDockerBlog); } else { initDockerBlog(); } })();