[{"data":1,"prerenderedAt":1345},["ShallowReactive",2],{"\u002Fblog\u002Fdevcontainer-to-mise-migration":3},{"path":4,"data":5,"meta":17,"nodes":45},"\u002Fblog\u002Fdevcontainer-to-mise-migration",{"title":6,"description":7,"date":8,"tags":9,"authors":11,"image":13,"seo":14},"Replacing Dev Containers: Reducing Setup Time from Minutes to Seconds","How we replaced a 170-line devcontainer.json with a single mise.toml and never looked back.","2026-03-24",[10],"engineering",[12],"Ibraheem Tuffaha","\u002Fimages\u002Fblog\u002Fdevcontainer-to-mise-migration.webp",{"title":15,"description":16},"Dev Containers to Mise Migration for Rails","We replaced VS Code Dev Containers with mise for our Rails app. Setup dropped from minutes to seconds, and we deleted 360 lines of config.",{"toc":18,"key":37,"source":38,"stem":39,"extension":40,"kind":41,"type":42,"partial":43,"hash":44},{"title":19,"searchDepth":20,"depth":20,"links":21},"",2,[22,25,28,31,34],{"id":23,"depth":20,"text":24},"what-dev-containers-actually-looked-like","What Dev Containers Actually Looked Like",{"id":26,"depth":20,"text":27},"why-we-left","Why We Left",{"id":29,"depth":20,"text":30},"what-we-replaced-it-with","What We Replaced It With",{"id":32,"depth":20,"text":33},"what-we-gained","What We Gained",{"id":35,"depth":20,"text":36},"the-trade-off","The Trade-off","blog\u002Fdevcontainer-to-mise-migration.md","blog","devcontainer-to-mise-migration",".md","document","text\u002Fmarkdown",false,"6bd08fa13d80f2a0",[46,55,96,99,107,110,118,126,351,357,562,568,794,804,902,905,907,975,977,990,1229,1244,1247,1265,1275,1278,1280,1283,1286,1306,1315,1317,1328,1331,1342],[47,48,49,54],"p",{},[50,51,53],"a",{"href":52},"https:\u002F\u002Fcontainers.dev\u002F","Dev Containers"," were supposed to make onboarding painless. Everyone gets the same environment. No \"works on my machine\" problems. In practice, they gave us a different set of problems.",[47,56,57,58,62,63,67,68,72,73,72,77,72,81,85,86,90,91,95],{},"At ",[50,59,61],{"href":60},"https:\u002F\u002Fmilkstraw.ai\u002F","MilkStraw AI",", we're a small team building an AWS cost optimization platform. We help companies understand and reduce their cloud spend. Our ",[50,64,66],{"href":65},"https:\u002F\u002Frubyonrails.org\u002F","Rails"," app ran inside a devcontainer that bundled ",[50,69,71],{"href":70},"https:\u002F\u002Fruby-lang.org\u002F","Ruby",", ",[50,74,76],{"href":75},"https:\u002F\u002Fnodejs.org\u002F","Node",[50,78,80],{"href":79},"https:\u002F\u002Fpostgresql.org\u002F","PostgreSQL",[50,82,84],{"href":83},"https:\u002F\u002Fredis.io\u002F","Redis",", the ",[50,87,89],{"href":88},"https:\u002F\u002Faws.amazon.com\u002Fcli","AWS CLI"," (we use it constantly), and a dozen ",[50,92,94],{"href":93},"https:\u002F\u002Fcode.visualstudio.com\u002F","VS Code"," extensions. It worked, technically. But we were debugging devcontainer issues on a weekly basis. Not big outages, just a steady drip of \"my container won't start\" or \"the database connection is refusing\" or \"I rebuilt and now a gem won't install.\"",[47,97,98],{},"Eventually we asked: why are we running our entire app inside a container when the only things that actually need containers are PostgreSQL and Redis?",[47,100,101,102,106],{},"We replaced the whole thing with ",[50,103,105],{"href":104},"https:\u002F\u002Fmise.jdx.dev\u002F","mise",". One config file. Native speed. Editor-agnostic. Setup went from 5-10 minutes to under 30 seconds.",[108,109,24],"h2",{"id":23},[47,111,112,113,117],{},"Our setup had four files under ",[114,115,116],"code",{},".devcontainer\u002F",". Here's what they looked like.",[47,119,120,121,125],{},"The ",[122,123,124],"strong",{},"Dockerfile"," built a custom Ruby image, installed the Stripe CLI, and cleaned up after itself:",[127,128,131],"pre",{"language":129,"class":130},"js","shiki shiki-themes github-light-default github-dark-default dark:github-dark-default",[114,132,134,160,161,160,194,160,196,160,204,160,206,160,220,160,236,160,278,160,295,160,312,160,323,160,344,160,346],{"class":133},"language-js",[135,136,139,143,146,150,153,157],"span",{"class":137,"style":138},"line","display: inline",[135,140,142],{"style":141},"color:#0550AE;--shiki-dark:#79C0FF","ARG",[135,144,145],{"style":141}," RUBY_VERSION",[135,147,149],{"style":148},"color:#CF222E;--shiki-dark:#FF7B72","=",[135,151,152],{"style":141},"3.4",[135,154,156],{"style":155},"color:#1F2328;--shiki-dark:#E6EDF3",".",[135,158,159],{"style":141},"2","\n",[135,162,163,166,169,172,175,177,180,182,185,187,191],{"class":137,"style":138},[135,164,165],{"style":141},"FROM",[135,167,168],{"style":155}," ghcr.io",[135,170,171],{"style":148},"\u002F",[135,173,174],{"style":155},"rails",[135,176,171],{"style":148},[135,178,179],{"style":155},"devcontainer",[135,181,171],{"style":148},[135,183,184],{"style":155},"images",[135,186,171],{"style":148},[135,188,190],{"style":189},"color:#953800;--shiki-dark:#FFA657","ruby",[135,192,193],{"style":155},":$RUBY_VERSION",[135,195],{"class":137,"style":138},[135,197,198,201],{"class":137,"style":138},[135,199,200],{"style":141},"USER",[135,202,203],{"style":155}," root",[135,205],{"class":137,"style":138},[135,207,208,211,214,217],{"class":137,"style":138},[135,209,210],{"style":141},"RUN",[135,212,213],{"style":155}," apt",[135,215,216],{"style":148},"-",[135,218,219],{"style":155},"get update \\",[135,221,222,225,228,231,233],{"class":137,"style":138},[135,223,224],{"style":148},"    &&",[135,226,227],{"style":148}," export",[135,229,230],{"style":141}," DEBIAN_FRONTEND",[135,232,149],{"style":148},[135,234,235],{"style":155},"noninteractive \\",[135,237,238,240,242,244,247,249,252,255,258,260,263,265,268,270,273,275],{"class":137,"style":138},[135,239,224],{"style":148},[135,241,213],{"style":155},[135,243,216],{"style":148},[135,245,246],{"style":155},"get ",[135,248,216],{"style":148},[135,250,251],{"style":155},"y install ",[135,253,254],{"style":148},"--",[135,256,257],{"style":155},"no",[135,259,216],{"style":148},[135,261,262],{"style":155},"install",[135,264,216],{"style":148},[135,266,267],{"style":155},"recommends curl software",[135,269,216],{"style":148},[135,271,272],{"style":155},"properties",[135,274,216],{"style":148},[135,276,277],{"style":155},"common \\",[135,279,280,282,285,288,291],{"class":137,"style":138},[135,281,224],{"style":148},[135,283,284],{"style":155}," wget ",[135,286,287],{"style":189},"https",[135,289,290],{"style":155},":",[135,292,294],{"style":293},"color:#6E7781;--shiki-dark:#8B949E","\u002F\u002Fgithub.com\u002Fstripe\u002Fstripe-cli\u002Freleases\u002Fdownload\u002Fv1.21.10\u002Fstripe_1.21.10_linux_${BUILDARCH}.deb -O stripe_cli.deb \\",[135,296,297,299,302,304,307,309],{"class":137,"style":138},[135,298,224],{"style":148},[135,300,301],{"style":155}," dpkg ",[135,303,216],{"style":148},[135,305,306],{"style":155},"i .",[135,308,171],{"style":148},[135,310,311],{"style":155},"stripe_cli.deb \\",[135,313,314,316,318,320],{"class":137,"style":138},[135,315,224],{"style":148},[135,317,213],{"style":155},[135,319,216],{"style":148},[135,321,322],{"style":155},"get clean \\",[135,324,325,327,330,332,335,338,341],{"class":137,"style":138},[135,326,224],{"style":148},[135,328,329],{"style":155}," rm ",[135,331,216],{"style":148},[135,333,334],{"style":155},"rf ",[135,336,337],{"style":148},"\u002Fvar",[135,339,340],{"style":155},"\u002Flib\u002Fapt\u002Flists",[135,342,343],{"style":293},"\u002F*",[135,345],{"class":137,"style":138},[135,347,348],{"class":137,"style":138},[135,349,350],{"style":293},"USER vscode",[47,352,120,353,356],{},[122,354,355],{},"docker-compose.yml"," orchestrated three services: the app container, PostgreSQL, and Redis:",[127,358,360],{"language":359,"class":130},"yaml",[114,361,363,160,371,160,378,160,385,160,396,160,407,160,414,160,422,160,432,160,434,160,441,160,451,160,461,160,467,160,474,160,481,160,491,160,500,160,502,160,509,160,518,160,526,160,532,160,539,160,541,160,548,160,555],{"class":362},"language-yaml",[135,364,365,369],{"class":137,"style":138},[135,366,368],{"style":367},"color:#116329;--shiki-dark:#7EE787","services",[135,370,290],{"style":155},[135,372,373,376],{"class":137,"style":138},[135,374,375],{"style":367},"  app",[135,377,290],{"style":155},[135,379,380,383],{"class":137,"style":138},[135,381,382],{"style":367},"    build",[135,384,290],{"style":155},[135,386,387,390,393],{"class":137,"style":138},[135,388,389],{"style":367},"      context",[135,391,392],{"style":155},": ",[135,394,395],{"style":141},"..",[135,397,398,401,403],{"class":137,"style":138},[135,399,400],{"style":367},"      dockerfile",[135,402,392],{"style":155},[135,404,406],{"style":405},"color:#0A3069;--shiki-dark:#A5D6FF",".devcontainer\u002FDockerfile",[135,408,409,412],{"class":137,"style":138},[135,410,411],{"style":367},"    volumes",[135,413,290],{"style":155},[135,415,416,419],{"class":137,"style":138},[135,417,418],{"style":155},"      - ",[135,420,421],{"style":405},"..\u002F..:\u002Fworkspaces:cached",[135,423,424,427,429],{"class":137,"style":138},[135,425,426],{"style":367},"    command",[135,428,392],{"style":155},[135,430,431],{"style":405},"sleep infinity",[135,433],{"class":137,"style":138},[135,435,436,439],{"class":137,"style":138},[135,437,438],{"style":367},"  db",[135,440,290],{"style":155},[135,442,443,446,448],{"class":137,"style":138},[135,444,445],{"style":367},"    image",[135,447,392],{"style":155},[135,449,450],{"style":405},"postgres:latest",[135,452,453,456,458],{"class":137,"style":138},[135,454,455],{"style":367},"    restart",[135,457,392],{"style":155},[135,459,460],{"style":405},"unless-stopped",[135,462,463,465],{"class":137,"style":138},[135,464,411],{"style":367},[135,466,290],{"style":155},[135,468,469,471],{"class":137,"style":138},[135,470,418],{"style":155},[135,472,473],{"style":405},"postgres-data:\u002Fvar\u002Flib\u002Fpostgresql\u002Fdata",[135,475,476,479],{"class":137,"style":138},[135,477,478],{"style":367},"    environment",[135,480,290],{"style":155},[135,482,483,486,488],{"class":137,"style":138},[135,484,485],{"style":367},"      POSTGRES_USER",[135,487,392],{"style":155},[135,489,490],{"style":405},"postgres",[135,492,493,496,498],{"class":137,"style":138},[135,494,495],{"style":367},"      POSTGRES_PASSWORD",[135,497,392],{"style":155},[135,499,490],{"style":405},[135,501],{"class":137,"style":138},[135,503,504,507],{"class":137,"style":138},[135,505,506],{"style":367},"  redis",[135,508,290],{"style":155},[135,510,511,513,515],{"class":137,"style":138},[135,512,445],{"style":367},[135,514,392],{"style":155},[135,516,517],{"style":405},"redis:7.2.3",[135,519,520,522,524],{"class":137,"style":138},[135,521,455],{"style":367},[135,523,392],{"style":155},[135,525,460],{"style":405},[135,527,528,530],{"class":137,"style":138},[135,529,411],{"style":367},[135,531,290],{"style":155},[135,533,534,536],{"class":137,"style":138},[135,535,418],{"style":155},[135,537,538],{"style":405},"redis-data:\u002Fdata",[135,540],{"class":137,"style":138},[135,542,543,546],{"class":137,"style":138},[135,544,545],{"style":367},"volumes",[135,547,290],{"style":155},[135,549,550,553],{"class":137,"style":138},[135,551,552],{"style":367},"  postgres-data",[135,554,290],{"style":155},[135,556,557,560],{"class":137,"style":138},[135,558,559],{"style":367},"  redis-data",[135,561,290],{"style":155},[47,563,120,564,567],{},[122,565,566],{},"devcontainer.json"," tied it all together with features, port forwarding, environment variables, VS Code settings, and extensions:",[127,569,570],{"language":129,"class":130},[114,571,572,160,577,160,590,160,602,160,614,160,626,160,634,160,642,160,649,160,656,160,663,160,670,160,677,160,687,160,692,160,697,160,704,160,716,160,726,160,730,160,749,160,761,160,768,160,775,160,780,160,784,160,789],{"class":133},[135,573,574],{"class":137,"style":138},[135,575,576],{"style":155},"{",[135,578,579,582,584,587],{"class":137,"style":138},[135,580,581],{"style":405},"  \"name\"",[135,583,392],{"style":155},[135,585,586],{"style":405},"\"MilkstrawWebApp\"",[135,588,589],{"style":155},",",[135,591,592,595,597,600],{"class":137,"style":138},[135,593,594],{"style":405},"  \"dockerComposeFile\"",[135,596,392],{"style":155},[135,598,599],{"style":405},"\"docker-compose.yml\"",[135,601,589],{"style":155},[135,603,604,607,609,612],{"class":137,"style":138},[135,605,606],{"style":405},"  \"service\"",[135,608,392],{"style":155},[135,610,611],{"style":405},"\"app\"",[135,613,589],{"style":155},[135,615,616,619,621,624],{"class":137,"style":138},[135,617,618],{"style":405},"  \"workspaceFolder\"",[135,620,392],{"style":155},[135,622,623],{"style":405},"\"\u002Fworkspaces\u002F${localWorkspaceFolderBasename}\"",[135,625,589],{"style":155},[135,627,628,631],{"class":137,"style":138},[135,629,630],{"style":405},"  \"features\"",[135,632,633],{"style":155},": {",[135,635,636,639],{"class":137,"style":138},[135,637,638],{"style":405},"    \"ghcr.io\u002Fdevcontainers\u002Ffeatures\u002Fnode\"",[135,640,641],{"style":155},": {},",[135,643,644,647],{"class":137,"style":138},[135,645,646],{"style":405},"    \"ghcr.io\u002Fdevcontainers\u002Ffeatures\u002Fdocker-in-docker\"",[135,648,641],{"style":155},[135,650,651,654],{"class":137,"style":138},[135,652,653],{"style":405},"    \"ghcr.io\u002Frails\u002Fdevcontainer\u002Ffeatures\u002Factivestorage\"",[135,655,641],{"style":155},[135,657,658,661],{"class":137,"style":138},[135,659,660],{"style":405},"    \"ghcr.io\u002Frails\u002Fdevcontainer\u002Ffeatures\u002Fpostgres-client\"",[135,662,641],{"style":155},[135,664,665,668],{"class":137,"style":138},[135,666,667],{"style":405},"    \"ghcr.io\u002Fdevcontainers\u002Ffeatures\u002Faws-cli\"",[135,669,641],{"style":155},[135,671,672,675],{"class":137,"style":138},[135,673,674],{"style":405},"    \"ghcr.io\u002Fdevcontainers\u002Ffeatures\u002Fcommon-utils:latest\"",[135,676,633],{"style":155},[135,678,679,682,684],{"class":137,"style":138},[135,680,681],{"style":405},"      \"configureZshAsDefaultShell\"",[135,683,392],{"style":155},[135,685,686],{"style":141},"true",[135,688,689],{"class":137,"style":138},[135,690,691],{"style":155},"    }",[135,693,694],{"class":137,"style":138},[135,695,696],{"style":155},"  },",[135,698,699,702],{"class":137,"style":138},[135,700,701],{"style":405},"  \"containerEnv\"",[135,703,633],{"style":155},[135,705,706,709,711,714],{"class":137,"style":138},[135,707,708],{"style":405},"    \"AWS_ACCESS_KEY_ID\"",[135,710,392],{"style":155},[135,712,713],{"style":405},"\"${localEnv:AWS_ACCESS_KEY_ID}\"",[135,715,589],{"style":155},[135,717,718,721,723],{"class":137,"style":138},[135,719,720],{"style":405},"    \"AWS_SECRET_ACCESS_KEY\"",[135,722,392],{"style":155},[135,724,725],{"style":405},"\"${localEnv:AWS_SECRET_ACCESS_KEY}\"",[135,727,728],{"class":137,"style":138},[135,729,696],{"style":155},[135,731,732,735,738,741,743,746],{"class":137,"style":138},[135,733,734],{"style":405},"  \"forwardPorts\"",[135,736,737],{"style":155},": [",[135,739,740],{"style":141},"3000",[135,742,72],{"style":155},[135,744,745],{"style":141},"5432",[135,747,748],{"style":155},"],",[135,750,751,754,756,759],{"class":137,"style":138},[135,752,753],{"style":405},"  \"postCreateCommand\"",[135,755,392],{"style":155},[135,757,758],{"style":405},"\".devcontainer\u002Fsetup.sh\"",[135,760,589],{"style":155},[135,762,763,766],{"class":137,"style":138},[135,764,765],{"style":405},"  \"customizations\"",[135,767,633],{"style":155},[135,769,770,773],{"class":137,"style":138},[135,771,772],{"style":405},"    \"vscode\"",[135,774,633],{"style":155},[135,776,777],{"class":137,"style":138},[135,778,779],{"style":293},"      \u002F\u002F ... 100+ lines of settings and extensions",[135,781,782],{"class":137,"style":138},[135,783,691],{"style":155},[135,785,786],{"class":137,"style":138},[135,787,788],{"style":155},"  }",[135,790,791],{"class":137,"style":138},[135,792,793],{"style":155},"}",[47,795,796,797,803],{},"And finally a ",[122,798,799],{},[50,800,802],{"href":801},"http:\u002F\u002Fsetup.sh","setup.sh"," that ran after the container was created:",[127,805,807],{"language":806,"class":130},"bash",[114,808,810,160,821,160,832,160,834,160,856,160,858,160,869,160,874,160,879,160,881,160,888,160,895],{"class":809},"language-bash",[135,811,812,815,818],{"class":137,"style":138},[135,813,814],{"style":189},"mkdir",[135,816,817],{"style":141}," -p",[135,819,820],{"style":405}," .ruby-lsp",[135,822,823,826,829],{"class":137,"style":138},[135,824,825],{"style":189},"cp",[135,827,828],{"style":405}," .ruby-version",[135,830,831],{"style":405}," .ruby-lsp\u002F.ruby-version",[135,833],{"class":137,"style":138},[135,835,836,839,842,845,848,851,854],{"class":137,"style":138},[135,837,838],{"style":141},"test",[135,840,841],{"style":141}," -f",[135,843,844],{"style":405}," .env",[135,846,847],{"style":148}," ||",[135,849,850],{"style":189}," cp",[135,852,853],{"style":405}," .env.example",[135,855,844],{"style":405},[135,857],{"class":137,"style":138},[135,859,860,863,866],{"class":137,"style":138},[135,861,862],{"style":189},"gem",[135,864,865],{"style":405}," update",[135,867,868],{"style":141}," --system",[135,870,871],{"class":137,"style":138},[135,872,873],{"style":189},"bundle",[135,875,876],{"class":137,"style":138},[135,877,878],{"style":189},"yarn",[135,880],{"class":137,"style":138},[135,882,883,885],{"class":137,"style":138},[135,884,174],{"style":189},[135,886,887],{"style":405}," db:create",[135,889,890,892],{"class":137,"style":138},[135,891,174],{"style":189},[135,893,894],{"style":405}," db:migrate",[135,896,897,899],{"class":137,"style":138},[135,898,174],{"style":189},[135,900,901],{"style":405}," db:seed",[47,903,904],{},"All told, about 360 lines of config spread across four files just to open the project.",[108,906,27],{"id":26},[908,909,910,922,938,949,965],"ol",{},[911,912,913,919],"li",{},[47,914,915,918],{},[122,916,917],{},"Docker within Docker."," This was the big one. Our app ran inside a container, but PostgreSQL and Redis ran as their own containers in the same compose stack. That meant Docker-in-Docker as a devcontainer feature, compose networking between services, and volume mounts for data persistence.",[47,920,921],{},"Getting this to work reliably was a constant fight. Containers couldn't find each other. Ports conflicted. Volumes had permission problems. All just to get a database connection.",[911,923,924,930],{},[47,925,926,929],{},[122,927,928],{},"Slow and heavy."," First-time setup took 5-10 minutes: image build, feature installation, post-create script. Rebuilds after Dockerfile changes weren't much better.",[47,931,932,933,937],{},"Our team runs macOS, which doesn't run ",[50,934,936],{"href":935},"https:\u002F\u002Fdocker.com\u002F","Docker"," natively. Everything goes through a Linux VM under the hood. File system performance through bind mounts was sluggish. Docker Desktop ate significant disk space, CPU, and RAM just sitting in the background. You're running your entire development environment inside a VM. That has a cost, and we were paying it on every keystroke.",[911,939,940,946],{},[47,941,942,945],{},[122,943,944],{},"Endless debugging across layers."," When something broke, you had to figure out which layer was responsible. The Dockerfile? The Docker-in-Docker networking? The compose config? The post-create script? A devcontainer feature conflict? A volume mount permission issue?",[47,947,948],{},"I've watched team members lose entire mornings to container rebuild loops where each attempt surfaced a new error. Dev Containers were supposed to eliminate environment problems. Instead, we swapped one class of problems for another that was harder to debug.",[911,950,951,954,955,959,960,964],{},[122,952,953],{},"Editor lock-in."," Everything was wired to VS Code. The settings, the formatters, the run-on-save commands. If you wanted to use ",[50,956,958],{"href":957},"https:\u002F\u002Fwww.jetbrains.com\u002Fruby\u002F","RubyMine"," or ",[50,961,963],{"href":962},"https:\u002F\u002Fzed.dev\u002F","Zed",", you were on your own.",[911,966,967,970,971,974],{},[122,968,969],{},"Version drift."," Ruby version was hardcoded in the Dockerfile, referenced in ",[114,972,973],{},".ruby-version",", and needed in CI. Three places to keep in sync.",[108,976,30],{"id":29},[47,978,979,980,983,984,72,986,989],{},"One file: ",[114,981,982],{},"mise.toml",". It replaced not just the devcontainer, but also ",[114,985,973],{},[114,987,988],{},".node-version",", and the scattered shell scripts we used for common tasks. One tool instead of four. (The fact that this was even possible surprised us.)",[127,991,992],{"language":129,"class":130},[114,993,994,160,999,160,1009,160,1019,160,1029,160,1039,160,1053,160,1055,160,1060,160,1070,160,1080,160,1089,160,1100,160,1109,160,1119,160,1121,160,1130,160,1141,160,1149,160,1153,160,1155,160,1166,160,1180,160,1184,160,1189,160,1191,160,1199,160,1208,160,1210,160,1220],{"class":133},[135,995,996],{"class":137,"style":138},[135,997,998],{"style":155},"[tools]",[135,1000,1001,1004,1006],{"class":137,"style":138},[135,1002,1003],{"style":155},"ruby ",[135,1005,149],{"style":148},[135,1007,1008],{"style":405}," \"3.4.2\"",[135,1010,1011,1014,1016],{"class":137,"style":138},[135,1012,1013],{"style":155},"node ",[135,1015,149],{"style":148},[135,1017,1018],{"style":405}," \"20.15.0\"",[135,1020,1021,1024,1026],{"class":137,"style":138},[135,1022,1023],{"style":155},"yarn ",[135,1025,149],{"style":148},[135,1027,1028],{"style":405}," \"1.22.22\"",[135,1030,1031,1034,1036],{"class":137,"style":138},[135,1032,1033],{"style":155},"stripe ",[135,1035,149],{"style":148},[135,1037,1038],{"style":405}," \"latest\"",[135,1040,1041,1044,1046,1049,1051],{"class":137,"style":138},[135,1042,1043],{"style":155},"aws",[135,1045,216],{"style":148},[135,1047,1048],{"style":155},"cli ",[135,1050,149],{"style":148},[135,1052,1038],{"style":405},[135,1054],{"class":137,"style":138},[135,1056,1057],{"class":137,"style":138},[135,1058,1059],{"style":155},"[tasks.dev]",[135,1061,1062,1065,1067],{"class":137,"style":138},[135,1063,1064],{"style":155},"description ",[135,1066,149],{"style":148},[135,1068,1069],{"style":405}," \"Start development environment\"",[135,1071,1072,1075,1077],{"class":137,"style":138},[135,1073,1074],{"style":155},"run ",[135,1076,149],{"style":148},[135,1078,1079],{"style":405}," '''",[135,1081,1082,1085],{"class":137,"style":138},[135,1083,1084],{"style":405},"mise run docker:star",[135,1086,1088],{"style":1087},"color:#82071E;--shiki-light-font-style:italic;--shiki-dark:#FFA198;--shiki-dark-font-style:italic","t",[135,1090,1091,1094,1097],{"class":137,"style":138},[135,1092,1093],{"style":155},"mise run ",[135,1095,1096],{"style":189},"deps",[135,1098,1099],{"style":155},":js",[135,1101,1102,1104,1106],{"class":137,"style":138},[135,1103,1093],{"style":155},[135,1105,1096],{"style":189},[135,1107,1108],{"style":155},":ruby",[135,1110,1111,1113,1116],{"class":137,"style":138},[135,1112,1093],{"style":155},[135,1114,1115],{"style":189},"db",[135,1117,1118],{"style":155},":prepare",[135,1120],{"class":137,"style":138},[135,1122,1123,1127],{"class":137,"style":138},[135,1124,1126],{"style":1125},"color:#8250DF;--shiki-dark:#D2A8FF","cleanup",[135,1128,1129],{"style":155},"() {",[135,1131,1132,1135,1138],{"class":137,"style":138},[135,1133,1134],{"style":155},"  mise ",[135,1136,1137],{"style":189},"docker",[135,1139,1140],{"style":155},":stop",[135,1142,1143,1146],{"class":137,"style":138},[135,1144,1145],{"style":155},"  exit ",[135,1147,1148],{"style":141},"0",[135,1150,1151],{"class":137,"style":138},[135,1152,793],{"style":155},[135,1154],{"class":137,"style":138},[135,1156,1157,1160,1163],{"class":137,"style":138},[135,1158,1159],{"style":155},"trap cleanup ",[135,1161,1162],{"style":141},"SIGINT",[135,1164,1165],{"style":141}," SIGTERM",[135,1167,1168,1170,1172,1175,1177],{"class":137,"style":138},[135,1169,156],{"style":155},[135,1171,171],{"style":148},[135,1173,1174],{"style":155},"bin",[135,1176,171],{"style":148},[135,1178,1179],{"style":155},"dev",[135,1181,1182],{"class":137,"style":138},[135,1183,1126],{"style":155},[135,1185,1186],{"class":137,"style":138},[135,1187,1188],{"style":405},"'''",[135,1190],{"class":137,"style":138},[135,1192,1193,1196],{"class":137,"style":138},[135,1194,1195],{"style":405},"[tasks.\"docker:start\"",[135,1197,1198],{"style":1087},"]",[135,1200,1201,1203,1205],{"class":137,"style":138},[135,1202,1074],{"style":155},[135,1204,149],{"style":148},[135,1206,1207],{"style":405}," \"docker compose -f dev-docker-compose.yml up -d\"",[135,1209],{"class":137,"style":138},[135,1211,1212,1215,1218],{"class":137,"style":138},[135,1213,1214],{"style":155},"[tasks.",[135,1216,1217],{"style":405},"\"docker:stop\"",[135,1219,1198],{"style":155},[135,1221,1222,1224,1226],{"class":137,"style":138},[135,1223,1074],{"style":155},[135,1225,149],{"style":148},[135,1227,1228],{"style":405}," \"docker compose -f dev-docker-compose.yml down\"",[47,1230,1231,1232,72,1236,1240,1241,1243],{},"Mise installs Ruby, Node, ",[50,1233,1235],{"href":1234},"https:\u002F\u002Fyarnpkg.com\u002F","Yarn",[50,1237,1239],{"href":1238},"https:\u002F\u002Fdocs.stripe.com\u002Fstripe-cli","Stripe CLI",", and ",[50,1242,89],{"href":88}," natively on your machine. No container image to build. Docker is still there, but only for what actually needs it: PostgreSQL and Redis as lightweight background services.",[47,1245,1246],{},"A new developer runs two commands:",[127,1248,1249],{"language":806,"class":130},[114,1250,1251,160,1258],{"class":809},[135,1252,1253,1255],{"class":137,"style":138},[135,1254,105],{"style":189},[135,1256,1257],{"style":405}," install",[135,1259,1260,1262],{"class":137,"style":138},[135,1261,105],{"style":189},[135,1263,1264],{"style":405}," dev",[47,1266,1267,1270,1271,1274],{},[114,1268,1269],{},"mise install"," takes about 30 seconds. ",[114,1272,1273],{},"mise dev"," starts the full environment in under 10 seconds. Day-to-day, it's instant.",[47,1276,1277],{},"360 lines of config became about 100. One PR. No drama.",[108,1279,33],{"id":32},[47,1281,1282],{},"The immediate win was simplicity. One file defines tools and tasks. It reads top to bottom and does exactly what it says. When something breaks (rare now), you know exactly where to look.",[47,1284,1285],{},"We also stopped caring about editors. Mise doesn't know or care whether you use VS Code, RubyMine, Zed, or anything else. The dev environment just works.",[47,1287,1288,1289,72,1292,72,1295,1298,1299,1302,1303,1305],{},"What surprised us was how much the task runner grew after the migration. We kept adding to it: ",[114,1290,1291],{},"mise lint",[114,1293,1294],{},"mise test",[114,1296,1297],{},"mise pr:create"," (wraps ",[114,1300,1301],{},"gh"," for branch pushing and PR creation), git hooks in ",[114,1304,1273],{},". Each addition was a few lines of TOML. Try doing that in a devcontainer setup.",[47,1307,1308,1309,1311,1312,1314],{},"And Ruby version, Node version, tool versions, dev tasks, CI — all live in ",[114,1310,982],{}," now. No more syncing ",[114,1313,973],{}," files across three different places.",[108,1316,36],{"id":35},[47,1318,1319,1320,1323,1324,1327],{},"There's one: initial machine setup. With Dev Containers, you installed Docker and VS Code and you were done. With mise, a new developer needs Docker, mise, and a couple of system libraries (",[114,1321,1322],{},"libpq"," for PostgreSQL, ",[114,1325,1326],{},"gpg"," for signing). It's a few extra steps documented in our README.",[47,1329,1330],{},"A one-time 5-minute README walkthrough beats a recurring 5-minute container rebuild that you can't skip. We'd make this trade-off again every time.",[47,1332,1333,1334,1338,1339,1341],{},"If your team uses Dev Containers and it genuinely works, keep going. They solve real problems, especially for teams on ",[50,1335,1337],{"href":1336},"https:\u002F\u002Fgithub.com\u002Ffeatures\u002Fcodespaces","GitHub Codespaces",". But if you're losing time to Docker-in-Docker issues, slow rebuilds, and config sprawl, give ",[50,1340,105],{"href":104}," an afternoon.",[47,1343,1344],{},"The best dev tooling is the kind you forget exists. We've been on mise for almost a year now. Nobody has filed a single issue about the dev environment. It just works.",1793704871164]