2025-11-06 15:14:46 -08:00
<!DOCTYPE html>
< html lang = "en" dir = "auto" data-theme = "auto" >
< head > < script src = "/livereload.js?mindelay=10&v=2&port=1313&path=livereload" data-no-instant defer > < / script > < meta charset = "utf-8" >
< meta http-equiv = "X-UA-Compatible" content = "IE=edge" >
< meta name = "viewport" content = "width=device-width, initial-scale=1, shrink-to-fit=no" >
< meta name = "robots" content = "noindex, nofollow" >
< title > Project Log: Docker Dreams and YAML Nightmares | Ask KennyB< / title >
< meta name = "keywords" content = "homelab, docker, networking, humor" >
< meta name = "description" content = "A totally serious update on my local lab, featuring unexpected container drama, a misbehaving reverse proxy, and lessons in patience." >
< meta name = "author" content = "Kenny Bondelie" >
< link rel = "canonical" href = "http://localhost:1313/blog/project-log-docker-dreams-and-yaml-nightmares/" >
< link crossorigin = "anonymous" href = "/assets/css/stylesheet.d1be478e0ac21456f47a24e92e3c75a5fb7aac2ff5827f9447dbc93b4dd76b50.css" integrity = "sha256-0b5HjgrCFFb0eiTpLjx1pft6rC/1gn+UR9vJO03Xa1A=" rel = "preload stylesheet" as = "style" >
< link rel = "icon" href = "http://localhost:1313/favicon.ico" >
< link rel = "icon" type = "image/png" sizes = "16x16" href = "http://localhost:1313/favicon-16x16.png" >
< link rel = "icon" type = "image/png" sizes = "32x32" href = "http://localhost:1313/favicon-32x32.png" >
< link rel = "apple-touch-icon" href = "http://localhost:1313/apple-touch-icon.png" >
< link rel = "mask-icon" href = "http://localhost:1313/safari-pinned-tab.svg" >
< meta name = "theme-color" content = "#2e2e33" >
< meta name = "msapplication-TileColor" content = "#2e2e33" >
< link rel = "alternate" hreflang = "en" href = "http://localhost:1313/blog/project-log-docker-dreams-and-yaml-nightmares/" >
< noscript >
< style >
# theme-toggle ,
. top-link {
display : none ;
}
< / style >
< style >
@ media ( prefers-color-scheme : dark ) {
: root {
--theme : rgb ( 29 , 30 , 32 ) ;
--entry : rgb ( 46 , 46 , 51 ) ;
--primary : rgb ( 218 , 218 , 219 ) ;
--secondary : rgb ( 155 , 156 , 157 ) ;
--tertiary : rgb ( 65 , 66 , 68 ) ;
--content : rgb ( 196 , 196 , 197 ) ;
--code-block-bg : rgb ( 46 , 46 , 51 ) ;
--code-bg : rgb ( 55 , 56 , 62 ) ;
--border : rgb ( 51 , 51 , 51 ) ;
color-scheme : dark ;
}
. list {
background : var ( - - theme ) ;
}
. toc {
background : var ( - - entry ) ;
}
}
@ media ( prefers-color-scheme : light ) {
. list :: -webkit-scrollbar-thumb {
border-color : var ( - - code - bg ) ;
}
}
< / style >
< / noscript >
< script >
if ( localStorage . getItem ( "pref-theme" ) === "dark" ) {
document . querySelector ( "html" ) . dataset . theme = 'dark' ;
} else if ( localStorage . getItem ( "pref-theme" ) === "light" ) {
document . querySelector ( "html" ) . dataset . theme = 'light' ;
} else if ( window . matchMedia ( '(prefers-color-scheme: dark)' ) . matches ) {
document . querySelector ( "html" ) . dataset . theme = 'dark' ;
} else {
document . querySelector ( "html" ) . dataset . theme = 'light' ;
}
< / script > < link rel = "preconnect" href = "https://fonts.googleapis.com" >
< link rel = "preconnect" href = "https://fonts.gstatic.com" crossorigin >
< link href = "https://fonts.googleapis.com/css2?family=Inter:wght@400;600&family=Source+Serif+4:opsz,wght@8..60,500..700&display=swap" rel = "stylesheet" >
< link rel = "icon" href = "/favicon.ico" sizes = "any" >
< link rel = "icon" type = "image/png" sizes = "32x32" href = "/favicon-32x32.png" >
< link rel = "icon" type = "image/png" sizes = "16x16" href = "/favicon-16x16.png" >
< link rel = "apple-touch-icon" href = "/apple-touch-icon.png" >
< link rel = "manifest" href = "/site.webmanifest" >
< meta name = "theme-color" content = "#007a70" >
< script defer src = "https://stats.askkennyb.com/script.js" data-website-id = "9ff21094-6881-404e-a30e-534c23dde9f8" > < / script >
< / head >
< body id = "top" >
< header class = "header" >
< nav class = "nav" >
< div class = "logo" >
< a href = "http://localhost:1313/" accesskey = "h" title = " (Alt + H)" >
< img src = "http://localhost:1313/images/logo_words.svg" alt = "" aria-label = "logo"
height = "75" > < / a >
< div class = "logo-switches" >
< button id = "theme-toggle" accesskey = "t" title = "(Alt + T)" aria-label = "Toggle theme" >
< svg id = "moon" xmlns = "http://www.w3.org/2000/svg" width = "24" height = "18" viewBox = "0 0 24 24"
fill = "none" stroke = "currentColor" stroke-width = "2" stroke-linecap = "round"
stroke-linejoin = "round" >
< path d = "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" > < / path >
< / svg >
< svg id = "sun" xmlns = "http://www.w3.org/2000/svg" width = "24" height = "18" viewBox = "0 0 24 24"
fill = "none" stroke = "currentColor" stroke-width = "2" stroke-linecap = "round"
stroke-linejoin = "round" >
< circle cx = "12" cy = "12" r = "5" > < / circle >
< line x1 = "12" y1 = "1" x2 = "12" y2 = "3" > < / line >
< line x1 = "12" y1 = "21" x2 = "12" y2 = "23" > < / line >
< line x1 = "4.22" y1 = "4.22" x2 = "5.64" y2 = "5.64" > < / line >
< line x1 = "18.36" y1 = "18.36" x2 = "19.78" y2 = "19.78" > < / line >
< line x1 = "1" y1 = "12" x2 = "3" y2 = "12" > < / line >
< line x1 = "21" y1 = "12" x2 = "23" y2 = "12" > < / line >
< line x1 = "4.22" y1 = "19.78" x2 = "5.64" y2 = "18.36" > < / line >
< line x1 = "18.36" y1 = "5.64" x2 = "19.78" y2 = "4.22" > < / line >
< / svg >
< / button >
< / div >
< / div >
< ul id = "menu" >
< li >
< a href = "http://localhost:1313/posts/" title = "Posts" >
< span > Posts< / span >
< / a >
< / li >
< li >
< a href = "http://localhost:1313/about/" title = "About" >
< span > About< / span >
< / a >
< / li >
< / ul >
< / nav >
< / header >
< main class = "main" >
< article class = "post-single" >
< header class = "post-header" >
< div class = "breadcrumbs" > < a href = "http://localhost:1313/" > Home< / a > » < a href = "http://localhost:1313/posts/" > Posts< / a > < / div >
< h1 class = "post-title entry-hint-parent" >
Project Log: Docker Dreams and YAML Nightmares
< / h1 >
< div class = "post-description" >
A totally serious update on my local lab, featuring unexpected container drama, a misbehaving reverse proxy, and lessons in patience.
< / div >
< div class = "post-meta" > < span title = '2025-11-05 00:00:00 +0000 UTC' > November 5, 2025< / span > · < span > 1 min< / span > · < span > Kenny Bondelie< / span >
< / div >
< / header > < div class = "toc" >
< details >
< summary accesskey = "c" title = "(Alt + C)" >
< span class = "details" > Table of Contents< / span >
< / summary >
< div class = "inner" > < ul >
< li >
< a href = "#the-symptoms" aria-label = "The Symptoms" > The Symptoms< / a > < / li >
< li >
< a href = "#the-diagnosis" aria-label = "The Diagnosis" > The Diagnosis< / a > < / li >
< li >
< a href = "#the-fix" aria-label = "The Fix" > The Fix< / a > < / li >
< li >
< a href = "#lessons-learned" aria-label = "Lessons Learned" > Lessons Learned< / a >
< / li >
< / ul >
< / div >
< / details >
< / div >
< div class = "post-content" > < blockquote >
< p > Sometimes the difference between a ‘ production-ready stack’ and ‘ why is my NAS on fire?’ is one missing space in a YAML file.< / p >
< / blockquote >
< p > It started innocently enough:< br >
a single < code > docker-compose.yml< / code > , neat and tidy, humming along like a well-trained orchestra. Then I added < em > one< / em > new service—my self-hosted note app—and everything fell apart.< / p >
< h3 id = "the-symptoms" > The Symptoms< a hidden class = "anchor" aria-hidden = "true" href = "#the-symptoms" > #< / a > < / h3 >
< ul >
< li > Containers refusing to start with no useful logs< / li >
< li > DNS loops that made my router question its purpose< / li >
< li > My wife asking, “Why is our TV buffering when you touch the server?”< / li >
< / ul >
< h3 id = "the-diagnosis" > The Diagnosis< a hidden class = "anchor" aria-hidden = "true" href = "#the-diagnosis" > #< / a > < / h3 >
< p > Turns out, I nested a volume mount under the wrong key.< br >
YAML: 1 — Human: 0.< / p >
< h3 id = "the-fix" > The Fix< a hidden class = "anchor" aria-hidden = "true" href = "#the-fix" > #< / a > < / h3 >
< p > A humble indent.< br >
Four spaces, to be precise.< br >
Suddenly the world made sense again, DNS was stable, and my cat stopped judging me.< / p >
< h3 id = "lessons-learned" > Lessons Learned< a hidden class = "anchor" aria-hidden = "true" href = "#lessons-learned" > #< / a > < / h3 >
< ol >
< li > < strong > Version control everything< / strong > , even your test Compose files.< / li >
< li > < strong > Automate backups< / strong > before you “just try something real quick.”< / li >
< li > < strong > Celebrate small victories< / strong > —sometimes the win is just getting your network back online before dinner.< / li >
< / ol >
< hr >
< p > If you read this and thought, “I’ ve been there,” then welcome to the club.< br >
Homelabs teach patience, humility, and the thrill of a perfectly clean < code > docker ps< / code > output.< / p >
< p > < em > Stay tuned for next week’ s adventure: rebuilding my reverse proxy after a 301 loop ate my weekend.< / em > < / p >
< / div >
< footer class = "post-footer" >
< ul class = "post-tags" >
< li > < a href = "http://localhost:1313/tags/homelab/" > Homelab< / a > < / li >
< li > < a href = "http://localhost:1313/tags/docker/" > Docker< / a > < / li >
< li > < a href = "http://localhost:1313/tags/networking/" > Networking< / a > < / li >
< li > < a href = "http://localhost:1313/tags/humor/" > Humor< / a > < / li >
< / ul >
< nav class = "paginav" >
< a class = "next" href = "http://localhost:1313/blog/hello-world-why-ask-kenny-b/" >
< span class = "title" > Next »< / span >
< br >
< span > Hello, World — Why Ask Kenny B?< / span >
< / a >
< / nav >
< / footer >
< / article >
< / main >
< footer class = "footer" >
< span > © 2025 < a href = "http://localhost:1313/" > Ask KennyB< / a > < / span > ·
< span >
Powered by
< a href = "https://gohugo.io/" rel = "noopener noreferrer" target = "_blank" > Hugo< / a > &
< a href = "https://github.com/adityatelange/hugo-PaperMod/" rel = "noopener" target = "_blank" > PaperMod< / a >
< / span >
< / footer >
< a href = "#top" aria-label = "go to top" title = "Go to Top (Alt + G)" class = "top-link" id = "top-link" accesskey = "g" >
< svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 12 6" fill = "currentColor" >
< path d = "M12 6H0l6-6z" / >
< / svg >
< / a >
< script >
let menu = document . getElementById ( 'menu' ) ;
if ( menu ) {
const scrollPosition = localStorage . getItem ( "menu-scroll-position" ) ;
if ( scrollPosition ) {
menu . scrollLeft = parseInt ( scrollPosition , 10 ) ;
}
menu . onscroll = function ( ) {
localStorage . setItem ( "menu-scroll-position" , menu . scrollLeft ) ;
}
}
document . querySelectorAll ( 'a[href^="#"]' ) . forEach ( anchor => {
anchor . addEventListener ( "click" , function ( e ) {
e . preventDefault ( ) ;
var id = this . getAttribute ( "href" ) . substr ( 1 ) ;
if ( ! window . matchMedia ( '(prefers-reduced-motion: reduce)' ) . matches ) {
document . querySelector ( ` [id=' ${ decodeURIComponent ( id ) } '] ` ) . scrollIntoView ( {
behavior : "smooth"
} ) ;
} else {
document . querySelector ( ` [id=' ${ decodeURIComponent ( id ) } '] ` ) . scrollIntoView ( ) ;
}
if ( id === "top" ) {
history . replaceState ( null , null , " " ) ;
} else {
history . pushState ( null , null , ` # ${ id } ` ) ;
}
} ) ;
} ) ;
< / script >
< script >
var mybutton = document . getElementById ( "top-link" ) ;
window . onscroll = function ( ) {
if ( document . body . scrollTop > 800 || document . documentElement . scrollTop > 800 ) {
mybutton . style . visibility = "visible" ;
mybutton . style . opacity = "1" ;
} else {
mybutton . style . visibility = "hidden" ;
mybutton . style . opacity = "0" ;
}
} ;
< / script >
< script >
document . getElementById ( "theme-toggle" ) . addEventListener ( "click" , ( ) => {
const html = document . querySelector ( "html" ) ;
if ( html . dataset . theme === "dark" ) {
html . dataset . theme = 'light' ;
localStorage . setItem ( "pref-theme" , 'light' ) ;
} else {
html . dataset . theme = 'dark' ;
localStorage . setItem ( "pref-theme" , 'dark' ) ;
}
} )
< / script >
< script >
document . querySelectorAll ( 'pre > code' ) . forEach ( ( codeblock ) => {
const container = codeblock . parentNode . parentNode ;
const copybutton = document . createElement ( 'button' ) ;
copybutton . classList . add ( 'copy-code' ) ;
copybutton . innerHTML = 'copy' ;
function copyingDone ( ) {
copybutton . innerHTML = 'copied!' ;
setTimeout ( ( ) => {
copybutton . innerHTML = 'copy' ;
} , 2000 ) ;
}
copybutton . addEventListener ( 'click' , ( cb ) => {
if ( 'clipboard' in navigator ) {
navigator . clipboard . writeText ( codeblock . textContent ) ;
copyingDone ( ) ;
return ;
}
const range = document . createRange ( ) ;
range . selectNodeContents ( codeblock ) ;
const selection = window . getSelection ( ) ;
selection . removeAllRanges ( ) ;
selection . addRange ( range ) ;
try {
document . execCommand ( 'copy' ) ;
copyingDone ( ) ;
} catch ( e ) { } ;
selection . removeRange ( range ) ;
} ) ;
if ( container . classList . contains ( "highlight" ) ) {
container . appendChild ( copybutton ) ;
} else if ( container . parentNode . firstChild == container ) {
} else if ( codeblock . parentNode . parentNode . parentNode . parentNode . parentNode . nodeName == "TABLE" ) {
codeblock . parentNode . parentNode . parentNode . parentNode . parentNode . appendChild ( copybutton ) ;
} else {
codeblock . parentNode . appendChild ( copybutton ) ;
}
} ) ;
< / script >
< / body >
< / html >