[{"data":1,"prerenderedAt":1181},["ShallowReactive",2],{"notice":3,"$fN7aM-6P-EMpv9kCwsd8KwnmF8F3v6SCBrlYMDkkq0fY":30,"home-playlists":177,"home-recent-posts":220},{"id":4,"title":5,"body":6,"description":22,"extension":23,"meta":24,"navigation":25,"path":26,"seo":27,"stem":28,"__hash__":29},"page\u002Fnotice.md","Site relaunch",{"type":7,"value":8,"toc":18},"minimark",[9],[10,11,12,13,17],"p",{},"🎉 ",[14,15,16],"strong",{},"Welcome to the all-new Red ALT Key site",", rebuilt from scratch! Video Notes are back, as well as a proper accessibility panel in the header. Still polishing corners — thanks for bearing with us.",{"title":19,"searchDepth":20,"depth":20,"links":21},"",2,[],"🎉 Welcome to the all-new Red ALT Key site, rebuilt from scratch! Video Notes are back, as well as a proper accessibility panel in the header. Still polishing corners — thanks for bearing with us.","md",{},true,"\u002Fnotice",{"title":5,"description":22},"notice","VKMJnU1ySGlgFLHqcmtMB3LTbmKa7RxzFMeX2jhSEc4",[31,57,72,87,102,117,132,147,162],{"kind":32,"etag":33,"id":34,"snippet":37},"youtube#searchResult","8HJaLo75E7DUbEa2GBiIMXxPtro",{"kind":35,"videoId":36},"youtube#video","ZFk8avwtWRg",{"publishedAt":38,"channelId":39,"title":40,"description":41,"thumbnails":42,"channelTitle":55,"liveBroadcastContent":56,"publishTime":38},"2024-02-01T03:06:00Z","UCcoSPiKu5dp_lT1fWhJYw5g","Docker Course   Module 7   Docker Compose","Welcome to Module 7 of our Docker Fundamentals Course on RED ALT Key, hosted by Leslie! In this tutorial, we dive into the ...",{"default":43,"medium":47,"high":51},{"url":44,"width":45,"height":46},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002FZFk8avwtWRg\u002Fdefault.jpg",120,90,{"url":48,"width":49,"height":50},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002FZFk8avwtWRg\u002Fmqdefault.jpg",320,180,{"url":52,"width":53,"height":54},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002FZFk8avwtWRg\u002Fhqdefault.jpg",480,360,"RED ALT Key","none",{"kind":32,"etag":58,"id":59,"snippet":61},"kObbwEAGrWAalK4zRbq_oKIm6gY",{"kind":35,"videoId":60},"7pZ4NRHFJfY",{"publishedAt":62,"channelId":39,"title":63,"description":64,"thumbnails":65,"channelTitle":55,"liveBroadcastContent":56,"publishTime":62},"2024-01-25T15:00:08Z","Container Networking and Storage | Docker Fundamentals Course | Module 6","Welcome to Module 6 of our Docker course on RED ALT Key! In this module, we dive deep into 'Container Networking and ...",{"default":66,"medium":68,"high":70},{"url":67,"width":45,"height":46},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002F7pZ4NRHFJfY\u002Fdefault.jpg",{"url":69,"width":49,"height":50},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002F7pZ4NRHFJfY\u002Fmqdefault.jpg",{"url":71,"width":53,"height":54},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002F7pZ4NRHFJfY\u002Fhqdefault.jpg",{"kind":32,"etag":73,"id":74,"snippet":76},"5fdSWUfXSZmKQCuw9IB3y3FpQGg",{"kind":35,"videoId":75},"DUFkMtA9YFo",{"publishedAt":77,"channelId":39,"title":78,"description":79,"thumbnails":80,"channelTitle":55,"liveBroadcastContent":56,"publishTime":77},"2024-01-18T02:55:48Z","Managing Image Registries | Docker Fundamentals Course | Module 5","Dive into the world of Docker image management with Module 5! We explore the nuances of tagging and pushing images, ...",{"default":81,"medium":83,"high":85},{"url":82,"width":45,"height":46},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002FDUFkMtA9YFo\u002Fdefault.jpg",{"url":84,"width":49,"height":50},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002FDUFkMtA9YFo\u002Fmqdefault.jpg",{"url":86,"width":53,"height":54},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002FDUFkMtA9YFo\u002Fhqdefault.jpg",{"kind":32,"etag":88,"id":89,"snippet":91},"9-X58qGIwTcdwiDf3Rrgxv_AmwY",{"kind":35,"videoId":90},"p_WXK1LFt38",{"publishedAt":92,"channelId":39,"title":93,"description":94,"thumbnails":95,"channelTitle":55,"liveBroadcastContent":56,"publishTime":92},"2023-12-14T01:00:21Z","Building Custom Docker Images | Docker Fundamentals Course | Module 4","Welcome back to RED ALT Key! In Module 4 of our Docker journey, we're diving deep into the world of custom Docker images.",{"default":96,"medium":98,"high":100},{"url":97,"width":45,"height":46},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002Fp_WXK1LFt38\u002Fdefault.jpg",{"url":99,"width":49,"height":50},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002Fp_WXK1LFt38\u002Fmqdefault.jpg",{"url":101,"width":53,"height":54},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002Fp_WXK1LFt38\u002Fhqdefault.jpg",{"kind":32,"etag":103,"id":104,"snippet":106},"2HqYsR96Nf3s99gQwKu59FiqgRw",{"kind":35,"videoId":105},"w4vzdxUNdrk",{"publishedAt":107,"channelId":39,"title":108,"description":109,"thumbnails":110,"channelTitle":55,"liveBroadcastContent":56,"publishTime":107},"2023-12-07T02:26:52Z","Working with Containers | Docker Fundamentals Course | Module 3","Welcome back to RED ALT Key! In Module 3 of our Docker series, \"Working with Containers,\" we'll dive into essential ...",{"default":111,"medium":113,"high":115},{"url":112,"width":45,"height":46},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002Fw4vzdxUNdrk\u002Fdefault.jpg",{"url":114,"width":49,"height":50},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002Fw4vzdxUNdrk\u002Fmqdefault.jpg",{"url":116,"width":53,"height":54},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002Fw4vzdxUNdrk\u002Fhqdefault.jpg",{"kind":32,"etag":118,"id":119,"snippet":121},"HI62GgVeEmcJiAUtCQUPBNj2PP8",{"kind":35,"videoId":120},"AvhxTVYcSaE",{"publishedAt":122,"channelId":39,"title":123,"description":124,"thumbnails":125,"channelTitle":55,"liveBroadcastContent":56,"publishTime":122},"2023-11-16T01:00:05Z","Docker Architecture | Docker Fundamentals Course | Module 2","Welcome back to RED ALT Key! In this module, dive deep into the heart of Docker and uncover its architecture. Discover the ...",{"default":126,"medium":128,"high":130},{"url":127,"width":45,"height":46},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002FAvhxTVYcSaE\u002Fdefault.jpg",{"url":129,"width":49,"height":50},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002FAvhxTVYcSaE\u002Fmqdefault.jpg",{"url":131,"width":53,"height":54},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002FAvhxTVYcSaE\u002Fhqdefault.jpg",{"kind":32,"etag":133,"id":134,"snippet":136},"agGaT5D48lZJWzS-SGj9mZPCkRk",{"kind":35,"videoId":135},"l6D3IMKGpbw",{"publishedAt":137,"channelId":39,"title":138,"description":139,"thumbnails":140,"channelTitle":55,"liveBroadcastContent":56,"publishTime":137},"2023-11-09T01:00:18Z","Introduction to Docker | Docker Fundamentals Course | Module 1","Welcome to the beginning of your Docker adventure on RED ALT Key! In this opening module, we delve into Docker's ...",{"default":141,"medium":143,"high":145},{"url":142,"width":45,"height":46},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002Fl6D3IMKGpbw\u002Fdefault.jpg",{"url":144,"width":49,"height":50},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002Fl6D3IMKGpbw\u002Fmqdefault.jpg",{"url":146,"width":53,"height":54},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002Fl6D3IMKGpbw\u002Fhqdefault.jpg",{"kind":32,"etag":148,"id":149,"snippet":151},"ZgLx5wb6CNs4WkZ-Qw4OwxoHeeg",{"kind":35,"videoId":150},"gznEhg0xraY",{"publishedAt":152,"channelId":39,"title":153,"description":154,"thumbnails":155,"channelTitle":55,"liveBroadcastContent":56,"publishTime":152},"2023-11-02T00:00:21Z","Ubuntu Screen Resolution Problem in Hyper-V","In this video, we tackle the challenge of optimizing the display resolution for an Ubuntu Virtual Machine running on Hyper-V, ...",{"default":156,"medium":158,"high":160},{"url":157,"width":45,"height":46},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002FgznEhg0xraY\u002Fdefault.jpg",{"url":159,"width":49,"height":50},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002FgznEhg0xraY\u002Fmqdefault.jpg",{"url":161,"width":53,"height":54},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002FgznEhg0xraY\u002Fhqdefault.jpg",{"kind":32,"etag":163,"id":164,"snippet":166},"97QRsx-BqexmMNOF4P0c-usbDAs",{"kind":35,"videoId":165},"qWEExLpfDCw",{"publishedAt":167,"channelId":39,"title":168,"description":169,"thumbnails":170,"channelTitle":55,"liveBroadcastContent":56,"publishTime":167},"2023-10-26T00:00:20Z","Top 10 Linux Commands","In this video, we'll go over the \"Top 10 Essential Linux Commands.\" Whether you're new to Linux or an IT pro, these commands ...",{"default":171,"medium":173,"high":175},{"url":172,"width":45,"height":46},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002FqWEExLpfDCw\u002Fdefault.jpg",{"url":174,"width":49,"height":50},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002FqWEExLpfDCw\u002Fmqdefault.jpg",{"url":176,"width":53,"height":54},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002FqWEExLpfDCw\u002Fhqdefault.jpg",[178],{"title":179,"id":180,"url":181,"videos":182,"error":219},"Docker Fundamentals","PLgWxqsTe200nfXv4SThkzKFj6_4cwuBO9","https:\u002F\u002Fwww.youtube.com\u002Fplaylist?list=PLgWxqsTe200nfXv4SThkzKFj6_4cwuBO9",[183,197,208],{"id":184,"snippet":185},{"videoId":36},{"title":40,"thumbnails":186},{"default":187,"medium":188,"high":189,"standard":190,"maxres":193},{"url":44,"width":45,"height":46},{"url":48,"width":49,"height":50},{"url":52,"width":53,"height":54},{"url":191,"width":192,"height":53},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002FZFk8avwtWRg\u002Fsddefault.jpg",640,{"url":194,"width":195,"height":196},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002FZFk8avwtWRg\u002Fmaxresdefault.jpg",1280,720,{"id":198,"snippet":199},{"videoId":60},{"title":63,"thumbnails":200},{"default":201,"medium":202,"high":203,"standard":204,"maxres":206},{"url":67,"width":45,"height":46},{"url":69,"width":49,"height":50},{"url":71,"width":53,"height":54},{"url":205,"width":192,"height":53},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002F7pZ4NRHFJfY\u002Fsddefault.jpg",{"url":207,"width":195,"height":196},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002F7pZ4NRHFJfY\u002Fmaxresdefault.jpg",{"id":209,"snippet":210},{"videoId":75},{"title":78,"thumbnails":211},{"default":212,"medium":213,"high":214,"standard":215,"maxres":217},{"url":82,"width":45,"height":46},{"url":84,"width":49,"height":50},{"url":86,"width":53,"height":54},{"url":216,"width":192,"height":53},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002FDUFkMtA9YFo\u002Fsddefault.jpg",{"url":218,"width":195,"height":196},"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002FDUFkMtA9YFo\u002Fmaxresdefault.jpg",false,[221,723,1012],{"id":222,"title":223,"body":224,"date":711,"description":712,"extension":23,"image":713,"meta":714,"navigation":25,"path":715,"readingTime":716,"seo":717,"stem":718,"tags":719,"videoUrl":713,"__hash__":722},"posts\u002Fposts\u002Fdocker-containers-images-and-stacks-explained.md","Docker Deep Dive: Containers, Images, and Stacks Explained",{"type":7,"value":225,"toc":705},[226,229,234,246,278,299,340,355,359,366,433,440,447,474,478,493,633,671,682,686,692,701],[10,227,228],{},"\"Just Dockerize it\" gets thrown around a lot, but the mental model underneath — images, containers, and stacks — is where most beginners actually get stuck. Once it clicks, everything else about Docker gets easier.",[230,231,233],"h2",{"id":232},"images-the-blueprint","Images: The Blueprint",[10,235,236,237,240,241,245],{},"An ",[14,238,239],{},"image"," is a read-only template: a filesystem snapshot plus instructions for what to run when a container starts from it. You don't run an image directly — you run a container ",[242,243,244],"em",{},"from"," it.",[247,248,252],"pre",{"className":249,"code":250,"language":251,"meta":19,"style":19},"language-bash shiki shiki-themes github-light github-dark","docker pull nginx:latest\ndocker images\n","bash",[253,254,255,271],"code",{"__ignoreMap":19},[256,257,260,264,268],"span",{"class":258,"line":259},"line",1,[256,261,263],{"class":262},"sScJk","docker",[256,265,267],{"class":266},"sZZnC"," pull",[256,269,270],{"class":266}," nginx:latest\n",[256,272,273,275],{"class":258,"line":20},[256,274,263],{"class":262},[256,276,277],{"class":266}," images\n",[10,279,280,281,284,285,288,289,288,292,295,296,298],{},"Images are built in layers, and that's the whole reason Docker is fast. Each instruction in a ",[253,282,283],{},"Dockerfile"," (",[253,286,287],{},"FROM",", ",[253,290,291],{},"RUN",[253,293,294],{},"COPY",", ...) creates a new layer, and Docker caches layers that haven't changed. Change one line near the bottom of your ",[253,297,283],{}," and only that layer (and everything after it) needs to rebuild.",[247,300,304],{"className":301,"code":302,"language":303,"meta":19,"style":19},"language-dockerfile shiki shiki-themes github-light github-dark","FROM node:20-alpine\nWORKDIR \u002Fapp\nCOPY package*.json .\u002F\nRUN npm install\nCOPY . .\nCMD [\"node\", \"server.js\"]\n","dockerfile",[253,305,306,311,316,322,328,334],{"__ignoreMap":19},[256,307,308],{"class":258,"line":259},[256,309,310],{},"FROM node:20-alpine\n",[256,312,313],{"class":258,"line":20},[256,314,315],{},"WORKDIR \u002Fapp\n",[256,317,319],{"class":258,"line":318},3,[256,320,321],{},"COPY package*.json .\u002F\n",[256,323,325],{"class":258,"line":324},4,[256,326,327],{},"RUN npm install\n",[256,329,331],{"class":258,"line":330},5,[256,332,333],{},"COPY . .\n",[256,335,337],{"class":258,"line":336},6,[256,338,339],{},"CMD [\"node\", \"server.js\"]\n",[10,341,342,343,346,347,350,351,354],{},"Notice ",[253,344,345],{},"package*.json"," is copied and installed ",[242,348,349],{},"before"," the rest of the source code. That ordering means ",[253,352,353],{},"npm install"," only re-runs when your dependencies actually change, not on every code edit.",[230,356,358],{"id":357},"containers-the-running-instance","Containers: The Running Instance",[10,360,361,362,365],{},"A ",[14,363,364],{},"container"," is a running (or stopped) instance of an image — an isolated process with its own filesystem, network namespace, and resource limits, but sharing the host's kernel.",[247,367,369],{"className":249,"code":368,"language":251,"meta":19,"style":19},"docker run -d --name my-nginx -p 8080:80 nginx:latest\ndocker ps\ndocker logs my-nginx\ndocker stop my-nginx && docker rm my-nginx\n",[253,370,371,396,403,413],{"__ignoreMap":19},[256,372,373,375,378,382,385,388,391,394],{"class":258,"line":259},[256,374,263],{"class":262},[256,376,377],{"class":266}," run",[256,379,381],{"class":380},"sj4cs"," -d",[256,383,384],{"class":380}," --name",[256,386,387],{"class":266}," my-nginx",[256,389,390],{"class":380}," -p",[256,392,393],{"class":266}," 8080:80",[256,395,270],{"class":266},[256,397,398,400],{"class":258,"line":20},[256,399,263],{"class":262},[256,401,402],{"class":266}," ps\n",[256,404,405,407,410],{"class":258,"line":318},[256,406,263],{"class":262},[256,408,409],{"class":266}," logs",[256,411,412],{"class":266}," my-nginx\n",[256,414,415,417,420,422,426,428,431],{"class":258,"line":324},[256,416,263],{"class":262},[256,418,419],{"class":266}," stop",[256,421,387],{"class":266},[256,423,425],{"class":424},"sVt8B"," && ",[256,427,263],{"class":262},[256,429,430],{"class":266}," rm",[256,432,412],{"class":266},[10,434,435,436,439],{},"The relationship is one-to-many: one image, unlimited containers. Spin up five containers from the same ",[253,437,438],{},"nginx:latest"," image and you get five independent, isolated instances — this is the whole reason containers are cheap and disposable compared to VMs.",[10,441,442,443,446],{},"A container's writable layer disappears when the container is removed. If you need data to survive that, you need a ",[14,444,445],{},"volume",":",[247,448,450],{"className":249,"code":449,"language":251,"meta":19,"style":19},"docker run -d -v my-data:\u002Fvar\u002Flib\u002Fdata --name my-app my-image\n",[253,451,452],{"__ignoreMap":19},[256,453,454,456,458,460,463,466,468,471],{"class":258,"line":259},[256,455,263],{"class":262},[256,457,377],{"class":266},[256,459,381],{"class":380},[256,461,462],{"class":380}," -v",[256,464,465],{"class":266}," my-data:\u002Fvar\u002Flib\u002Fdata",[256,467,384],{"class":380},[256,469,470],{"class":266}," my-app",[256,472,473],{"class":266}," my-image\n",[230,475,477],{"id":476},"stacks-multiple-containers-one-definition","Stacks: Multiple Containers, One Definition",[10,479,480,481,484,485,488,489,492],{},"Almost nothing real runs as a single container. A typical self-hosted app is a web server, a database, and maybe a cache or reverse proxy — each is its own container, wired together. That's a ",[14,482,483],{},"stack",", and ",[253,486,487],{},"docker-compose.yml"," is how you define it declaratively instead of typing five long ",[253,490,491],{},"docker run"," commands from memory:",[247,494,498],{"className":495,"code":496,"language":497,"meta":19,"style":19},"language-yaml shiki shiki-themes github-light github-dark","services:\n  app:\n    build: .\n    ports:\n      - \"3000:3000\"\n    depends_on:\n      - db\n  db:\n    image: postgres:16\n    environment:\n      POSTGRES_PASSWORD: example\n    volumes:\n      - db-data:\u002Fvar\u002Flib\u002Fpostgresql\u002Fdata\n\nvolumes:\n  db-data:\n","yaml",[253,499,500,509,516,527,534,542,549,557,565,576,584,595,603,611,617,625],{"__ignoreMap":19},[256,501,502,506],{"class":258,"line":259},[256,503,505],{"class":504},"s9eBZ","services",[256,507,508],{"class":424},":\n",[256,510,511,514],{"class":258,"line":20},[256,512,513],{"class":504},"  app",[256,515,508],{"class":424},[256,517,518,521,524],{"class":258,"line":318},[256,519,520],{"class":504},"    build",[256,522,523],{"class":424},": ",[256,525,526],{"class":380},".\n",[256,528,529,532],{"class":258,"line":324},[256,530,531],{"class":504},"    ports",[256,533,508],{"class":424},[256,535,536,539],{"class":258,"line":330},[256,537,538],{"class":424},"      - ",[256,540,541],{"class":266},"\"3000:3000\"\n",[256,543,544,547],{"class":258,"line":336},[256,545,546],{"class":504},"    depends_on",[256,548,508],{"class":424},[256,550,552,554],{"class":258,"line":551},7,[256,553,538],{"class":424},[256,555,556],{"class":266},"db\n",[256,558,560,563],{"class":258,"line":559},8,[256,561,562],{"class":504},"  db",[256,564,508],{"class":424},[256,566,568,571,573],{"class":258,"line":567},9,[256,569,570],{"class":504},"    image",[256,572,523],{"class":424},[256,574,575],{"class":266},"postgres:16\n",[256,577,579,582],{"class":258,"line":578},10,[256,580,581],{"class":504},"    environment",[256,583,508],{"class":424},[256,585,587,590,592],{"class":258,"line":586},11,[256,588,589],{"class":504},"      POSTGRES_PASSWORD",[256,591,523],{"class":424},[256,593,594],{"class":266},"example\n",[256,596,598,601],{"class":258,"line":597},12,[256,599,600],{"class":504},"    volumes",[256,602,508],{"class":424},[256,604,606,608],{"class":258,"line":605},13,[256,607,538],{"class":424},[256,609,610],{"class":266},"db-data:\u002Fvar\u002Flib\u002Fpostgresql\u002Fdata\n",[256,612,614],{"class":258,"line":613},14,[256,615,616],{"emptyLinePlaceholder":25},"\n",[256,618,620,623],{"class":258,"line":619},15,[256,621,622],{"class":504},"volumes",[256,624,508],{"class":424},[256,626,628,631],{"class":258,"line":627},16,[256,629,630],{"class":504},"  db-data",[256,632,508],{"class":424},[247,634,636],{"className":249,"code":635,"language":251,"meta":19,"style":19},"docker compose up -d\ndocker compose logs -f\ndocker compose down\n",[253,637,638,651,662],{"__ignoreMap":19},[256,639,640,642,645,648],{"class":258,"line":259},[256,641,263],{"class":262},[256,643,644],{"class":266}," compose",[256,646,647],{"class":266}," up",[256,649,650],{"class":380}," -d\n",[256,652,653,655,657,659],{"class":258,"line":20},[256,654,263],{"class":262},[256,656,644],{"class":266},[256,658,409],{"class":266},[256,660,661],{"class":380}," -f\n",[256,663,664,666,668],{"class":258,"line":318},[256,665,263],{"class":262},[256,667,644],{"class":266},[256,669,670],{"class":266}," down\n",[10,672,673,674,677,678,681],{},"Compose also creates a private network for the stack automatically, so ",[253,675,676],{},"app"," can reach ",[253,679,680],{},"db"," by service name — no manual networking required.",[230,683,685],{"id":684},"putting-it-together","Putting It Together",[10,687,688,689,691],{},"Image → container → stack is the whole progression: you build or pull a blueprint, run one or more instances of it, and wire multiple instances together into something that behaves like a single application. Once that ordering is intuitive, reading someone else's ",[253,690,487],{}," stops being intimidating — it's just a list of images, how they run, and how they talk to each other.",[10,693,694,695,700],{},"If you haven't already, the ",[696,697,699],"a",{"href":698},"\u002Fposts\u002Fgetting-started-with-a-home-lab","home lab getting-started guide"," is a good next stop for where to actually run this stuff.",[702,703,704],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}",{"title":19,"searchDepth":20,"depth":20,"links":706},[707,708,709,710],{"id":232,"depth":20,"text":233},{"id":357,"depth":20,"text":358},{"id":476,"depth":20,"text":477},{"id":684,"depth":20,"text":685},"2026-09-06","The three Docker concepts that trip people up most, explained the way I wish someone had explained them to me: images, containers, and multi-service stacks.",null,{},"\u002Fposts\u002Fdocker-containers-images-and-stacks-explained","7 min read",{"title":223,"description":712},"posts\u002Fdocker-containers-images-and-stacks-explained",[720,721],"Docker","Home Lab","QMOTBn5CRq6BjT96TzBXdJk37CslwXadqB4rzs63G2I",{"id":724,"title":725,"body":726,"date":711,"description":1000,"extension":23,"image":713,"meta":1001,"navigation":25,"path":1002,"readingTime":1003,"seo":1004,"stem":1005,"tags":1006,"videoUrl":1010,"__hash__":1011},"posts\u002Fposts\u002Ffixing-ubuntu-screen-resolution-in-hyper-v.md","Fixing Ubuntu's Screen Resolution Problem in Hyper-V",{"type":7,"value":727,"toc":994},[728,731,735,750,760,764,767,785,791,856,862,866,876,967,977,981,988,991],[10,729,730],{},"Spin up a fresh Ubuntu VM in Hyper-V and it's a near-universal first annoyance: the desktop is stuck at a low, fixed resolution and won't resize with the window, no matter how you drag it. There are two real fixes here, and which one you need depends on whether you're using Enhanced Session Mode.",[230,732,734],{"id":733},"why-this-happens","Why This Happens",[10,736,737,738,741,742,745,746,749],{},"Hyper-V exposes video to a Linux guest through a synthetic framebuffer driver (",[253,739,740],{},"hyperv_fb","). In a ",[14,743,744],{},"Basic Session"," (the default ",[253,747,748],{},"VMConnect"," window), that driver only advertises a small, fixed list of resolutions — it has no way to know how big your window actually is, so it just picks one and sticks with it.",[10,751,752,755,756,759],{},[14,753,754],{},"Enhanced Session Mode"," works completely differently: instead of a raw framebuffer, it tunnels an RDP-like session over a Hyper-V socket, which ",[242,757,758],{},"does"," know your window's actual size and resizes dynamically, exactly like resizing a Remote Desktop window. This is the fix that makes the problem disappear entirely rather than working around it.",[230,761,763],{"id":762},"fix-1-turn-on-enhanced-session-mode-recommended","Fix 1: Turn On Enhanced Session Mode (Recommended)",[10,765,766],{},"This needs to be enabled in two places:",[10,768,769,772,773,776,777,780,781,784],{},[14,770,771],{},"On the Hyper-V host",", in Hyper-V Manager: right-click the host → ",[242,774,775],{},"Hyper-V Settings"," → ",[242,778,779],{},"Enhanced Session Mode Policy"," → check ",[14,782,783],{},"Allow enhanced session mode",".",[10,786,787,790],{},[14,788,789],{},"Inside the Ubuntu guest",", install the pieces that let it accept that session:",[247,792,794],{"className":249,"code":793,"language":251,"meta":19,"style":19},"sudo apt update\nsudo apt install -y linux-virtual linux-tools-virtual linux-cloud-tools-virtual\nsudo apt install -y xrdp\nsudo systemctl enable --now xrdp\n",[253,795,796,807,828,841],{"__ignoreMap":19},[256,797,798,801,804],{"class":258,"line":259},[256,799,800],{"class":262},"sudo",[256,802,803],{"class":266}," apt",[256,805,806],{"class":266}," update\n",[256,808,809,811,813,816,819,822,825],{"class":258,"line":20},[256,810,800],{"class":262},[256,812,803],{"class":266},[256,814,815],{"class":266}," install",[256,817,818],{"class":380}," -y",[256,820,821],{"class":266}," linux-virtual",[256,823,824],{"class":266}," linux-tools-virtual",[256,826,827],{"class":266}," linux-cloud-tools-virtual\n",[256,829,830,832,834,836,838],{"class":258,"line":318},[256,831,800],{"class":262},[256,833,803],{"class":266},[256,835,815],{"class":266},[256,837,818],{"class":380},[256,839,840],{"class":266}," xrdp\n",[256,842,843,845,848,851,854],{"class":258,"line":324},[256,844,800],{"class":262},[256,846,847],{"class":266}," systemctl",[256,849,850],{"class":266}," enable",[256,852,853],{"class":380}," --now",[256,855,840],{"class":266},[10,857,858,859,861],{},"Reboot the VM. When you reconnect via ",[253,860,748],{},", it should now negotiate an enhanced session automatically — resize the window and the guest resolution follows immediately, the same way it would over RDP.",[230,863,865],{"id":864},"fix-2-manually-set-a-resolution-basic-session","Fix 2: Manually Set a Resolution (Basic Session)",[10,867,868,869,871,872,875],{},"If you're intentionally staying on a Basic Session (e.g. no GUI login manager, or a minimal\u002Fserver install), you can still get a usable resolution out of ",[253,870,740],{}," by generating a custom mode with ",[253,873,874],{},"cvt"," and adding it manually:",[247,877,879],{"className":249,"code":878,"language":251,"meta":19,"style":19},"cvt 1920 1080\n# Outputs a Modeline you can pass to xrandr, e.g.:\nxrandr --newmode \"1920x1080_60.00\" 173.00 1920 2048 2248 2576 1080 1083 1088 1120 -hsync +vsync\nxrandr --addmode Virtual-1 \"1920x1080_60.00\"\nxrandr --output Virtual-1 --mode \"1920x1080_60.00\"\n",[253,880,881,891,897,940,953],{"__ignoreMap":19},[256,882,883,885,888],{"class":258,"line":259},[256,884,874],{"class":262},[256,886,887],{"class":380}," 1920",[256,889,890],{"class":380}," 1080\n",[256,892,893],{"class":258,"line":20},[256,894,896],{"class":895},"sJ8bj","# Outputs a Modeline you can pass to xrandr, e.g.:\n",[256,898,899,902,905,908,911,913,916,919,922,925,928,931,934,937],{"class":258,"line":318},[256,900,901],{"class":262},"xrandr",[256,903,904],{"class":380}," --newmode",[256,906,907],{"class":266}," \"1920x1080_60.00\"",[256,909,910],{"class":380}," 173.00",[256,912,887],{"class":380},[256,914,915],{"class":380}," 2048",[256,917,918],{"class":380}," 2248",[256,920,921],{"class":380}," 2576",[256,923,924],{"class":380}," 1080",[256,926,927],{"class":380}," 1083",[256,929,930],{"class":380}," 1088",[256,932,933],{"class":380}," 1120",[256,935,936],{"class":380}," -hsync",[256,938,939],{"class":266}," +vsync\n",[256,941,942,944,947,950],{"class":258,"line":324},[256,943,901],{"class":262},[256,945,946],{"class":380}," --addmode",[256,948,949],{"class":266}," Virtual-1",[256,951,952],{"class":266}," \"1920x1080_60.00\"\n",[256,954,955,957,960,962,965],{"class":258,"line":330},[256,956,901],{"class":262},[256,958,959],{"class":380}," --output",[256,961,949],{"class":266},[256,963,964],{"class":380}," --mode",[256,966,952],{"class":266},[10,968,969,970,973,974,976],{},"The output name (",[253,971,972],{},"Virtual-1"," above) varies — run ",[253,975,901],{}," on its own first to see what your VM calls its display. This survives until reboot; if you want it permanent, drop the same three commands into an Xorg startup script or a systemd unit.",[230,978,980],{"id":979},"which-one-should-you-use","Which One Should You Use?",[10,982,983,984,987],{},"If you have any GUI use for the VM at all, Enhanced Session Mode is worth the five minutes of setup — it's a proper fix rather than a workaround, it gives you clipboard sharing and drive redirection for free, and you'll never think about resolution again. Fix 2 is really only worth it for headless-adjacent setups where you occasionally need a GUI and don't want ",[253,985,986],{},"xrdp"," running permanently.",[10,989,990],{},"Full walkthrough with the exact host and guest settings is on the channel.",[702,992,993],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":19,"searchDepth":20,"depth":20,"links":995},[996,997,998,999],{"id":733,"depth":20,"text":734},{"id":762,"depth":20,"text":763},{"id":864,"depth":20,"text":865},{"id":979,"depth":20,"text":980},"Ubuntu stuck at a tiny resolution inside a Hyper-V VM? Here's why it happens and the two real fixes, depending on whether you're using Enhanced Session Mode.",{},"\u002Fposts\u002Ffixing-ubuntu-screen-resolution-in-hyper-v","5 min read",{"title":725,"description":1000},"posts\u002Ffixing-ubuntu-screen-resolution-in-hyper-v",[1007,1008,1009],"Linux","Virtualization","Hyper-V","https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=gznEhg0xraY","1g4nMpL1yr-9OHr3oYynCwWhdxMk4onYL4UzC4UCuao",{"id":1013,"title":1014,"body":1015,"date":1173,"description":1174,"extension":23,"image":713,"meta":1175,"navigation":25,"path":698,"readingTime":1176,"seo":1177,"stem":1178,"tags":1179,"videoUrl":713,"__hash__":1180},"posts\u002Fposts\u002Fgetting-started-with-a-home-lab.md","Getting Started With a Home Lab",{"type":7,"value":1016,"toc":1164},[1017,1020,1024,1027,1031,1053,1056,1060,1063,1084,1091,1095,1098,1129,1132,1136,1139,1150,1154,1157,1161],[10,1018,1019],{},"Every home lab tour on YouTube seems to open with a wall of blinking servers, and it scares people off before they even start. You don't need that. You need one machine and a reason to learn.",[230,1021,1023],{"id":1022},"what-a-home-lab-actually-is","What a Home Lab Actually Is",[10,1025,1026],{},"A home lab is just a personal environment — one box or several — where you run services, break things, and learn without any of it mattering to production. That's the whole point: the stakes are zero, so you can experiment freely.",[230,1028,1030],{"id":1029},"step-1-pick-your-hardware-you-probably-already-have-it","Step 1: Pick Your Hardware (You Probably Already Have It)",[1032,1033,1034,1041,1047],"ul",{},[1035,1036,1037,1040],"li",{},[14,1038,1039],{},"An old laptop or desktop"," you were about to sell. Perfect starter hardware.",[1035,1042,1043,1046],{},[14,1044,1045],{},"A Raspberry Pi"," (or three). Low power, quiet, great for lightweight services like Pi-hole or a small Docker host.",[1035,1048,1049,1052],{},[14,1050,1051],{},"A dedicated mini PC"," (Intel NUC-style) if you're ready to commit — low power draw, small footprint, surprisingly capable.",[10,1054,1055],{},"Don't buy anything for your first project. Use what's already gathering dust.",[230,1057,1059],{"id":1058},"step-2-pick-a-virtualization-layer","Step 2: Pick a Virtualization Layer",[10,1061,1062],{},"This is where most beginners overthink it. Three reasonable starting points:",[1064,1065,1066,1072,1078],"ol",{},[1035,1067,1068,1071],{},[14,1069,1070],{},"Proxmox VE"," — free, purpose-built for home labs, huge community, my default recommendation.",[1035,1073,1074,1077],{},[14,1075,1076],{},"TrueNAS Scale"," — if storage is your primary goal (NAS) and virtualization is secondary.",[1035,1079,1080,1083],{},[14,1081,1082],{},"Plain Docker on a minimal Linux install"," — if you don't need full VMs yet and just want to run services in containers.",[10,1085,1086,1087,1090],{},"If you're not sure, start with Proxmox. You can always run Docker ",[242,1088,1089],{},"inside"," a Proxmox VM later — it's not an either\u002For decision.",[230,1092,1094],{"id":1093},"step-3-pick-one-project-not-ten","Step 3: Pick One Project, Not Ten",[10,1096,1097],{},"The classic home lab failure mode is installing 15 services in a weekend, understanding none of them, and giving up. Instead, pick one:",[1032,1099,1100,1106,1112,1123],{},[1035,1101,1102,1105],{},[14,1103,1104],{},"Pi-hole"," — network-wide ad blocking, teaches you basic DNS.",[1035,1107,1108,1111],{},[14,1109,1110],{},"Jellyfin"," — a self-hosted media server, teaches you storage and transcoding.",[1035,1113,1114,1117,1118,1122],{},[14,1115,1116],{},"A Kali container"," for CLI security tools — see the ",[696,1119,1121],{"href":1120},"\u002Fposts\u002Fkali-linux-in-docker","Docker + Kali walkthrough"," if you want a low-commitment way to try this.",[1035,1124,1125,1128],{},[14,1126,1127],{},"Nextcloud"," — self-hosted file sync, teaches you reverse proxies and TLS certificates.",[10,1130,1131],{},"Get one thing running end-to-end, including backups, before adding the next.",[230,1133,1135],{"id":1134},"step-4-think-about-backups-before-you-need-them","Step 4: Think About Backups Before You Need Them",[10,1137,1138],{},"The single most common home lab regret is losing a config you never backed up. At minimum:",[1032,1140,1141,1144,1147],{},[1035,1142,1143],{},"Snapshot VMs before major changes (Proxmox makes this trivial).",[1035,1145,1146],{},"Keep configuration files in a private Git repository.",[1035,1148,1149],{},"Back up anything irreplaceable (photos, documents) to at least one location outside the lab itself.",[230,1151,1153],{"id":1152},"step-5-document-what-you-do","Step 5: Document What You Do",[10,1155,1156],{},"Future-you will not remember why you set a static route six months ago. A simple Markdown file per service — what it does, how it's configured, how to restore it — pays for itself the first time something breaks at 11 p.m.",[230,1158,1160],{"id":1159},"where-to-go-from-here","Where to Go From Here",[10,1162,1163],{},"Once you're comfortable with one host, the natural next steps are networking (VLANs, a proper firewall like OPNsense or pfSense), then clustering multiple nodes for high availability. But that's a \"someday\" problem — for now, get one box running one useful service, and let curiosity pull you forward from there.",{"title":19,"searchDepth":20,"depth":20,"links":1165},[1166,1167,1168,1169,1170,1171,1172],{"id":1022,"depth":20,"text":1023},{"id":1029,"depth":20,"text":1030},{"id":1058,"depth":20,"text":1059},{"id":1093,"depth":20,"text":1094},{"id":1134,"depth":20,"text":1135},{"id":1152,"depth":20,"text":1153},{"id":1159,"depth":20,"text":1160},"2026-08-24","You don't need a rack of enterprise servers to start a home lab. Here's how to begin with what you already own.",{},"8 min read",{"title":1014,"description":1174},"posts\u002Fgetting-started-with-a-home-lab",[721,1008],"ChMBkg4k9pE1Hh6iSsNIkNXntL5OzJiOAdIBGz7Q-gM",1788843378587]