[{"data":1,"prerenderedAt":1372},["ShallowReactive",2],{"navigation":3,"index":14,"index-blogs":125},[4],{"title":5,"path":6,"stem":7,"children":8,"page":13},"Blog","/blog","blog",[9],{"title":10,"path":11,"stem":12},"Docker Networks Explained for Real Projects","/blog/docker-networks-explained-for-real-projects","blog/docker-networks-explained-for-real-projects",false,{"id":15,"title":16,"about":17,"blog":20,"body":23,"description":24,"experience":25,"extension":36,"faq":23,"hero":37,"meta":72,"navigation":73,"path":74,"seo":75,"skills":78,"stem":123,"testimonials":23,"__hash__":124},"index/index.yml","Hey, I'm Iroko Victor Backend Developer",{"title":18,"description":19},"About Me","Backend developer experienced in TypeScript, Python and modern web frameworks like Nuxt and Hono.\nInterested in building scalable web systems and exploring AI/ML to develop intelligent applications.\n",{"title":21,"description":22},"Latest Articles","Some of my recent thoughts",null,"Backend developer experienced in TypeScript, Python and modern web frameworks like Nuxt and Hono. Interested in building scalable web systems and exploring AI/ML to develop intelligent applications.",{"title":26,"items":27},"Work Experience",[28],{"position":29,"date":30,"company":31},"Backend Developer at","2024 - 2025",{"name":32,"logo":33,"url":34,"color":35},"Pushtechn","i-lucide-building-2","#","#6366f1","yml",{"links":38,"images":44},[39],{"label":40,"to":41,"icon":42,"color":43},"Download CV","/resume.pdf","i-lucide-download","neutral",[45,48,51,54,57,60,63,66,69],{"src":46,"alt":47},"/hero/random-1.avif","Random Image 1",{"src":49,"alt":50},"/hero/random-2.avif","Random Image 2",{"src":52,"alt":53},"/hero/random-3.avif","Random Image 3",{"src":55,"alt":56},"/hero/random-4.avif","Random Image 4",{"src":58,"alt":59},"/hero/random-5.avif","Random Image 5",{"src":61,"alt":62},"/hero/random-6.avif","Random Image 6",{"src":64,"alt":65},"/hero/random-7.avif","Random Image 7",{"src":67,"alt":68},"/hero/random-8.avif","Random Image 8",{"src":70,"alt":71},"/hero/random-9.avif","Random Image 9",{},true,"/",{"title":76,"description":77},"Iroko Victor - Backend Developer","Backend developer experienced in TypeScript, Python and modern web frameworks like Nuxt and Hono. Interested in building scalable web systems and exploring AI/ML.",{"title":79,"categories":80},"Skills",[81,93,111],{"name":82,"items":83},"Languages",[84,87,90],{"label":85,"icon":86},"Python","i-simple-icons-python",{"label":88,"icon":89},"TypeScript","i-simple-icons-typescript",{"label":91,"icon":92},"SQL","i-lucide-database",{"name":94,"items":95},"Frameworks",[96,99,102,105,108],{"label":97,"icon":98},"Nuxt","i-simple-icons-nuxtdotjs",{"label":100,"icon":101},"Hono","i-simple-icons-hono",{"label":103,"icon":104},"FastAPI","i-simple-icons-fastapi",{"label":106,"icon":107},"Express","i-simple-icons-express",{"label":109,"icon":110},"React","i-simple-icons-react",{"name":112,"items":113},"Tools",[114,117,120],{"label":115,"icon":116},"Git","i-simple-icons-git",{"label":118,"icon":119},"Docker","i-simple-icons-docker",{"label":121,"icon":122},"Postman","i-simple-icons-postman","index","hBpGSunyRW9-jFvdriC1Vl_p_1rYB3LPCJ_puHhcBUI",[126],{"id":127,"title":10,"author":128,"body":136,"date":1364,"description":1365,"extension":1366,"image":1367,"mediumLink":1368,"meta":1369,"minRead":403,"navigation":73,"path":11,"seo":1370,"stem":12,"__hash__":1371},"blog/blog/docker-networks-explained-for-real-projects.md",{"name":129,"description":130,"username":131,"twitter":132,"to":133,"avatar":134},"Iroko Victor","Backend Developer","Victor-Iroko","IVictor476","https://github.com/Victor-Iroko",{"src":135,"alt":129},"/images/profile.jpg",{"type":137,"value":138,"toc":1336},"minimark",[139,143,151,154,157,162,165,168,184,187,190,194,197,209,212,215,231,237,248,252,262,265,268,273,276,280,283,286,297,300,323,326,436,447,453,457,460,463,466,475,478,487,490,494,497,500,681,696,702,714,717,721,724,727,751,757,768,771,782,785,794,797,806,810,813,817,820,823,834,838,841,844,852,855,859,862,864,872,876,879,881,889,892,896,899,902,910,913,1082,1085,1106,1109,1113,1116,1120,1145,1149,1152,1156,1159,1163,1169,1172,1175,1186,1190,1193,1213,1216,1219,1245,1251,1255,1258,1261,1275,1278,1282,1285,1299,1302,1306,1309,1312,1326,1329,1332],[140,141,142],"p",{},"If you work with Docker long enough, you eventually stop asking, \"How do I run this container?\" and start asking, \"How do these containers talk to each other properly?\"",[140,144,145,146,150],{},"That is where ",[147,148,149],"strong",{},"Docker networks"," stop being a side feature and start becoming part of your application design.",[140,152,153],{},"A lot of Docker setups work at first by accident. You run a database container, run an API container, expose a few ports, and things seem fine. But as soon as you add a second service, split environments, or tighten security, the networking model starts to matter.",[140,155,156],{},"This article is a practical guide to Docker networks: what they are, why they matter, and how to use them without turning your local setup into a mystery.",[158,159,161],"h2",{"id":160},"what-a-docker-network-actually-is","What a Docker network actually is",[140,163,164],{},"A Docker network is the communication layer Docker gives to containers.",[140,166,167],{},"It decides things like:",[169,170,171,175,178,181],"ul",{},[172,173,174],"li",{},"which containers can reach each other",[172,176,177],{},"how they resolve names",[172,179,180],{},"whether they are visible outside Docker",[172,182,183],{},"how traffic flows between services",[140,185,186],{},"Think of it as an application-level private network for your containers.",[140,188,189],{},"Without a clear network setup, teams often fall back to exposing everything with host ports. That works, but it is usually noisier and less safe than necessary.",[158,191,193],{"id":192},"the-first-thing-to-understand-containers-are-isolated-by-default","The first thing to understand: containers are isolated by default",[140,195,196],{},"A container is not your host machine.",[140,198,199,200,204,205,208],{},"It has its own network namespace, which means it gets its own interfaces, routes, and IP address inside Docker's virtual networking layer. So when your app tries to connect to ",[201,202,203],"code",{},"localhost",", it is connecting to ",[147,206,207],{},"itself",", not to another container.",[140,210,211],{},"This is one of the most common beginner mistakes.",[140,213,214],{},"If your API container tries to connect to Postgres using:",[216,217,222],"pre",{"className":218,"code":219,"language":220,"meta":221,"style":221},"language-env shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","DATABASE_URL=postgres://user:pass@localhost:5432/app\n","env","",[201,223,224],{"__ignoreMap":221},[225,226,229],"span",{"class":227,"line":228},"line",1,[225,230,219],{},[140,232,233,234,236],{},"that usually fails when Postgres is running in another container, because ",[201,235,203],{}," inside the API container is the API container itself.",[140,238,239,240,243,244,247],{},"What you usually want is the ",[147,241,242],{},"service name"," or ",[147,245,246],{},"container name on a shared Docker network",".",[158,249,251],{"id":250},"the-default-bridge-network-vs-user-defined-bridge-networks","The default bridge network vs user-defined bridge networks",[140,253,254,255,258,259,247],{},"Docker gives you a default ",[201,256,257],{},"bridge"," network, but for real projects you should usually create or use a ",[147,260,261],{},"user-defined bridge network",[140,263,264],{},"Why?",[140,266,267],{},"Because user-defined bridge networks give you better service discovery and cleaner isolation.",[269,270,272],"h3",{"id":271},"default-bridge-network","Default bridge network",[140,274,275],{},"The default bridge network exists automatically. Containers can be attached to it, but name resolution is limited and the setup is less explicit.",[269,277,279],{"id":278},"user-defined-bridge-network","User-defined bridge network",[140,281,282],{},"A user-defined bridge network is what you should reach for in most local multi-container projects.",[140,284,285],{},"It gives you:",[169,287,288,291,294],{},[172,289,290],{},"automatic DNS-based name resolution between containers",[172,292,293],{},"better control over which services can talk to each other",[172,295,296],{},"clearer project structure",[140,298,299],{},"Example:",[216,301,305],{"className":302,"code":303,"language":304,"meta":221,"style":221},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","docker network create app-net\n","bash",[201,306,307],{"__ignoreMap":221},[225,308,309,313,317,320],{"class":227,"line":228},[225,310,312],{"class":311},"sBMFI","docker",[225,314,316],{"class":315},"sfazB"," network",[225,318,319],{"class":315}," create",[225,321,322],{"class":315}," app-net\n",[140,324,325],{},"Then run services on it:",[216,327,329],{"className":302,"code":328,"language":304,"meta":221,"style":221},"docker run -d \\\n  --name postgres-db \\\n  --network app-net \\\n  -e POSTGRES_PASSWORD=secret \\\n  postgres:16\n\ndocker run -d \\\n  --name backend-api \\\n  --network app-net \\\n  -e DATABASE_URL=postgres://postgres:secret@postgres-db:5432/postgres \\\n  my-api-image\n",[201,330,331,345,356,367,378,384,390,401,411,420,430],{"__ignoreMap":221},[225,332,333,335,338,341],{"class":227,"line":228},[225,334,312],{"class":311},[225,336,337],{"class":315}," run",[225,339,340],{"class":315}," -d",[225,342,344],{"class":343},"sTEyZ"," \\\n",[225,346,348,351,354],{"class":227,"line":347},2,[225,349,350],{"class":315},"  --name",[225,352,353],{"class":315}," postgres-db",[225,355,344],{"class":343},[225,357,359,362,365],{"class":227,"line":358},3,[225,360,361],{"class":315},"  --network",[225,363,364],{"class":315}," app-net",[225,366,344],{"class":343},[225,368,370,373,376],{"class":227,"line":369},4,[225,371,372],{"class":315},"  -e",[225,374,375],{"class":315}," POSTGRES_PASSWORD=secret",[225,377,344],{"class":343},[225,379,381],{"class":227,"line":380},5,[225,382,383],{"class":315},"  postgres:16\n",[225,385,387],{"class":227,"line":386},6,[225,388,389],{"emptyLinePlaceholder":73},"\n",[225,391,393,395,397,399],{"class":227,"line":392},7,[225,394,312],{"class":311},[225,396,337],{"class":315},[225,398,340],{"class":315},[225,400,344],{"class":343},[225,402,404,406,409],{"class":227,"line":403},8,[225,405,350],{"class":315},[225,407,408],{"class":315}," backend-api",[225,410,344],{"class":343},[225,412,414,416,418],{"class":227,"line":413},9,[225,415,361],{"class":315},[225,417,364],{"class":315},[225,419,344],{"class":343},[225,421,423,425,428],{"class":227,"line":422},10,[225,424,372],{"class":315},[225,426,427],{"class":315}," DATABASE_URL=postgres://postgres:secret@postgres-db:5432/postgres",[225,429,344],{"class":343},[225,431,433],{"class":227,"line":432},11,[225,434,435],{"class":315},"  my-api-image\n",[140,437,438,439,442,443,446],{},"Now ",[201,440,441],{},"backend-api"," can reach Postgres using ",[201,444,445],{},"postgres-db"," as the hostname.",[140,448,449,450,247],{},"That is the key value: ",[147,451,452],{},"Docker handles the DNS for you inside the network",[158,454,456],{"id":455},"why-service-discovery-matters","Why service discovery matters",[140,458,459],{},"When multiple containers share a user-defined bridge network, Docker provides internal DNS.",[140,461,462],{},"That means you do not need to hardcode container IPs, which is good because container IPs are not something you should depend on. They change.",[140,464,465],{},"Instead of this fragile approach:",[216,467,469],{"className":218,"code":468,"language":220,"meta":221,"style":221},"REDIS_HOST=172.18.0.4\n",[201,470,471],{"__ignoreMap":221},[225,472,473],{"class":227,"line":228},[225,474,468],{},[140,476,477],{},"use this:",[216,479,481],{"className":218,"code":480,"language":220,"meta":221,"style":221},"REDIS_HOST=redis\n",[201,482,483],{"__ignoreMap":221},[225,484,485],{"class":227,"line":228},[225,486,480],{},[140,488,489],{},"This becomes especially useful in Docker Compose, where service names naturally become network hostnames.",[158,491,493],{"id":492},"docker-compose-makes-this-much-easier","Docker Compose makes this much easier",[140,495,496],{},"Most application teams should prefer Docker Compose for local orchestration.",[140,498,499],{},"A simple example:",[216,501,505],{"className":502,"code":503,"language":504,"meta":221,"style":221},"language-yaml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","services:\n  api:\n    build: .\n    ports:\n      - \"3000:3000\"\n    depends_on:\n      - db\n      - redis\n    environment:\n      DATABASE_URL: postgres://postgres:secret@db:5432/app\n      REDIS_URL: redis://redis:6379\n\n  db:\n    image: postgres:16\n    environment:\n      POSTGRES_PASSWORD: secret\n      POSTGRES_DB: app\n\n  redis:\n    image: redis:7\n","yaml",[201,506,507,517,524,536,543,557,564,571,578,585,595,605,610,618,629,636,647,658,663,671],{"__ignoreMap":221},[225,508,509,513],{"class":227,"line":228},[225,510,512],{"class":511},"swJcz","services",[225,514,516],{"class":515},"sMK4o",":\n",[225,518,519,522],{"class":227,"line":347},[225,520,521],{"class":511},"  api",[225,523,516],{"class":515},[225,525,526,529,532],{"class":227,"line":358},[225,527,528],{"class":511},"    build",[225,530,531],{"class":515},":",[225,533,535],{"class":534},"sbssI"," .\n",[225,537,538,541],{"class":227,"line":369},[225,539,540],{"class":511},"    ports",[225,542,516],{"class":515},[225,544,545,548,551,554],{"class":227,"line":380},[225,546,547],{"class":515},"      -",[225,549,550],{"class":515}," \"",[225,552,553],{"class":315},"3000:3000",[225,555,556],{"class":515},"\"\n",[225,558,559,562],{"class":227,"line":386},[225,560,561],{"class":511},"    depends_on",[225,563,516],{"class":515},[225,565,566,568],{"class":227,"line":392},[225,567,547],{"class":515},[225,569,570],{"class":315}," db\n",[225,572,573,575],{"class":227,"line":403},[225,574,547],{"class":515},[225,576,577],{"class":315}," redis\n",[225,579,580,583],{"class":227,"line":413},[225,581,582],{"class":511},"    environment",[225,584,516],{"class":515},[225,586,587,590,592],{"class":227,"line":422},[225,588,589],{"class":511},"      DATABASE_URL",[225,591,531],{"class":515},[225,593,594],{"class":315}," postgres://postgres:secret@db:5432/app\n",[225,596,597,600,602],{"class":227,"line":432},[225,598,599],{"class":511},"      REDIS_URL",[225,601,531],{"class":515},[225,603,604],{"class":315}," redis://redis:6379\n",[225,606,608],{"class":227,"line":607},12,[225,609,389],{"emptyLinePlaceholder":73},[225,611,613,616],{"class":227,"line":612},13,[225,614,615],{"class":511},"  db",[225,617,516],{"class":515},[225,619,621,624,626],{"class":227,"line":620},14,[225,622,623],{"class":511},"    image",[225,625,531],{"class":515},[225,627,628],{"class":315}," postgres:16\n",[225,630,632,634],{"class":227,"line":631},15,[225,633,582],{"class":511},[225,635,516],{"class":515},[225,637,639,642,644],{"class":227,"line":638},16,[225,640,641],{"class":511},"      POSTGRES_PASSWORD",[225,643,531],{"class":515},[225,645,646],{"class":315}," secret\n",[225,648,650,653,655],{"class":227,"line":649},17,[225,651,652],{"class":511},"      POSTGRES_DB",[225,654,531],{"class":515},[225,656,657],{"class":315}," app\n",[225,659,661],{"class":227,"line":660},18,[225,662,389],{"emptyLinePlaceholder":73},[225,664,666,669],{"class":227,"line":665},19,[225,667,668],{"class":511},"  redis",[225,670,516],{"class":515},[225,672,674,676,678],{"class":227,"line":673},20,[225,675,623],{"class":511},[225,677,531],{"class":515},[225,679,680],{"class":315}," redis:7\n",[140,682,683,684,687,688,691,692,695],{},"In this setup, ",[201,685,686],{},"api",", ",[201,689,690],{},"db",", and ",[201,693,694],{},"redis"," are automatically placed on the same default Compose network.",[140,697,698,699,701],{},"Inside the ",[201,700,686],{}," container:",[169,703,704,709],{},[172,705,706,708],{},[201,707,690],{}," resolves to the Postgres container",[172,710,711,713],{},[201,712,694],{}," resolves to the Redis container",[140,715,716],{},"You do not need to manually create the network unless you want more control.",[158,718,720],{"id":719},"exposing-ports-is-not-the-same-as-container-to-container-networking","Exposing ports is not the same as container-to-container networking",[140,722,723],{},"This distinction is important.",[140,725,726],{},"When you publish a port like this:",[216,728,730],{"className":502,"code":729,"language":504,"meta":221,"style":221},"ports:\n  - \"5432:5432\"\n",[201,731,732,739],{"__ignoreMap":221},[225,733,734,737],{"class":227,"line":228},[225,735,736],{"class":511},"ports",[225,738,516],{"class":515},[225,740,741,744,746,749],{"class":227,"line":347},[225,742,743],{"class":515},"  -",[225,745,550],{"class":515},[225,747,748],{"class":315},"5432:5432",[225,750,556],{"class":515},[140,752,753,754,247],{},"that makes the container reachable from your ",[147,755,756],{},"host machine",[140,758,759,760,763,764,767],{},"It does ",[147,761,762],{},"not"," mean another container should use ",[201,765,766],{},"localhost:5432"," to talk to it.",[140,769,770],{},"Inside Docker networks, containers should usually communicate using:",[169,772,773,776,779],{},[172,774,775],{},"the shared network",[172,777,778],{},"the service/container hostname",[172,780,781],{},"the container's internal port",[140,783,784],{},"So your app container should connect to:",[216,786,788],{"className":218,"code":787,"language":220,"meta":221,"style":221},"DATABASE_URL=postgres://postgres:secret@db:5432/app\n",[201,789,790],{"__ignoreMap":221},[225,791,792],{"class":227,"line":228},[225,793,787],{},[140,795,796],{},"not:",[216,798,800],{"className":218,"code":799,"language":220,"meta":221,"style":221},"DATABASE_URL=postgres://postgres:secret@localhost:5432/app\n",[201,801,802],{"__ignoreMap":221},[225,803,804],{"class":227,"line":228},[225,805,799],{},[158,807,809],{"id":808},"common-network-drivers-you-should-know","Common network drivers you should know",[140,811,812],{},"You do not need every Docker network driver every day, but you should know what they are for.",[269,814,816],{"id":815},"_1-bridge","1. Bridge",[140,818,819],{},"This is the most common driver for single-host container communication.",[140,821,822],{},"Use it for:",[169,824,825,828,831],{},[172,826,827],{},"local development",[172,829,830],{},"backend + database + cache setups",[172,832,833],{},"most standard Compose projects",[269,835,837],{"id":836},"_2-host","2. Host",[140,839,840],{},"The container shares the host's networking stack.",[140,842,843],{},"Use it when:",[169,845,846,849],{},[172,847,848],{},"you need maximum network performance",[172,850,851],{},"you explicitly need the container to bind directly to host interfaces",[140,853,854],{},"Be careful: this reduces isolation.",[269,856,858],{"id":857},"_3-none","3. None",[140,860,861],{},"The container gets no external networking.",[140,863,843],{},[169,865,866,869],{},[172,867,868],{},"you want a highly restricted container",[172,870,871],{},"the workload does not need network access",[269,873,875],{"id":874},"_4-overlay","4. Overlay",[140,877,878],{},"Used for multi-host communication, often in Docker Swarm environments.",[140,880,843],{},[169,882,883,886],{},[172,884,885],{},"services need to talk across multiple Docker hosts",[172,887,888],{},"you are working in orchestration environments that support it",[140,890,891],{},"For many developers, bridge networks are enough most of the time.",[158,893,895],{"id":894},"a-practical-pattern-for-real-applications","A practical pattern for real applications",[140,897,898],{},"A good mental model is to separate networks by responsibility.",[140,900,901],{},"For example:",[169,903,904,907],{},[172,905,906],{},"one network for internal app communication",[172,908,909],{},"one network for services that also need reverse-proxy access",[140,911,912],{},"Example Compose setup:",[216,914,916],{"className":502,"code":915,"language":504,"meta":221,"style":221},"services:\n  nginx:\n    image: nginx:latest\n    ports:\n      - \"80:80\"\n    networks:\n      - public\n\n  api:\n    build: ./api\n    networks:\n      - public\n      - private\n\n  db:\n    image: postgres:16\n    environment:\n      POSTGRES_PASSWORD: secret\n    networks:\n      - private\n\nnetworks:\n  public:\n  private:\n",[201,917,918,924,931,940,946,957,964,971,975,981,990,996,1002,1009,1013,1019,1027,1033,1041,1047,1053,1058,1066,1074],{"__ignoreMap":221},[225,919,920,922],{"class":227,"line":228},[225,921,512],{"class":511},[225,923,516],{"class":515},[225,925,926,929],{"class":227,"line":347},[225,927,928],{"class":511},"  nginx",[225,930,516],{"class":515},[225,932,933,935,937],{"class":227,"line":358},[225,934,623],{"class":511},[225,936,531],{"class":515},[225,938,939],{"class":315}," nginx:latest\n",[225,941,942,944],{"class":227,"line":369},[225,943,540],{"class":511},[225,945,516],{"class":515},[225,947,948,950,952,955],{"class":227,"line":380},[225,949,547],{"class":515},[225,951,550],{"class":515},[225,953,954],{"class":315},"80:80",[225,956,556],{"class":515},[225,958,959,962],{"class":227,"line":386},[225,960,961],{"class":511},"    networks",[225,963,516],{"class":515},[225,965,966,968],{"class":227,"line":392},[225,967,547],{"class":515},[225,969,970],{"class":315}," public\n",[225,972,973],{"class":227,"line":403},[225,974,389],{"emptyLinePlaceholder":73},[225,976,977,979],{"class":227,"line":413},[225,978,521],{"class":511},[225,980,516],{"class":515},[225,982,983,985,987],{"class":227,"line":422},[225,984,528],{"class":511},[225,986,531],{"class":515},[225,988,989],{"class":315}," ./api\n",[225,991,992,994],{"class":227,"line":432},[225,993,961],{"class":511},[225,995,516],{"class":515},[225,997,998,1000],{"class":227,"line":607},[225,999,547],{"class":515},[225,1001,970],{"class":315},[225,1003,1004,1006],{"class":227,"line":612},[225,1005,547],{"class":515},[225,1007,1008],{"class":315}," private\n",[225,1010,1011],{"class":227,"line":620},[225,1012,389],{"emptyLinePlaceholder":73},[225,1014,1015,1017],{"class":227,"line":631},[225,1016,615],{"class":511},[225,1018,516],{"class":515},[225,1020,1021,1023,1025],{"class":227,"line":638},[225,1022,623],{"class":511},[225,1024,531],{"class":515},[225,1026,628],{"class":315},[225,1028,1029,1031],{"class":227,"line":649},[225,1030,582],{"class":511},[225,1032,516],{"class":515},[225,1034,1035,1037,1039],{"class":227,"line":660},[225,1036,641],{"class":511},[225,1038,531],{"class":515},[225,1040,646],{"class":315},[225,1042,1043,1045],{"class":227,"line":665},[225,1044,961],{"class":511},[225,1046,516],{"class":515},[225,1048,1049,1051],{"class":227,"line":673},[225,1050,547],{"class":515},[225,1052,1008],{"class":315},[225,1054,1056],{"class":227,"line":1055},21,[225,1057,389],{"emptyLinePlaceholder":73},[225,1059,1061,1064],{"class":227,"line":1060},22,[225,1062,1063],{"class":511},"networks",[225,1065,516],{"class":515},[225,1067,1069,1072],{"class":227,"line":1068},23,[225,1070,1071],{"class":511},"  public",[225,1073,516],{"class":515},[225,1075,1077,1080],{"class":227,"line":1076},24,[225,1078,1079],{"class":511},"  private",[225,1081,516],{"class":515},[140,1083,1084],{},"In that structure:",[169,1086,1087,1095,1101],{},[172,1088,1089,1092,1093],{},[201,1090,1091],{},"nginx"," can reach ",[201,1094,686],{},[172,1096,1097,1092,1099],{},[201,1098,686],{},[201,1100,690],{},[172,1102,1103,1105],{},[201,1104,690],{}," is not directly exposed on the public side",[140,1107,1108],{},"That is a cleaner architecture than exposing every container port to the host and hoping people use the right one.",[158,1110,1112],{"id":1111},"debugging-docker-network-problems","Debugging Docker network problems",[140,1114,1115],{},"When containers cannot talk to each other, check the basics first.",[269,1117,1119],{"id":1118},"_1-are-the-containers-on-the-same-network","1. Are the containers on the same network?",[216,1121,1123],{"className":302,"code":1122,"language":304,"meta":221,"style":221},"docker network ls\ndocker network inspect app-net\n",[201,1124,1125,1134],{"__ignoreMap":221},[225,1126,1127,1129,1131],{"class":227,"line":228},[225,1128,312],{"class":311},[225,1130,316],{"class":315},[225,1132,1133],{"class":315}," ls\n",[225,1135,1136,1138,1140,1143],{"class":227,"line":347},[225,1137,312],{"class":311},[225,1139,316],{"class":315},[225,1141,1142],{"class":315}," inspect",[225,1144,322],{"class":315},[269,1146,1148],{"id":1147},"_2-is-the-hostname-correct","2. Is the hostname correct?",[140,1150,1151],{},"Use the service name or container name attached to the network.",[269,1153,1155],{"id":1154},"_3-are-you-using-the-internal-port-not-the-published-host-port","3. Are you using the internal port, not the published host port?",[140,1157,1158],{},"Inside the Docker network, use the container port.",[269,1160,1162],{"id":1161},"_4-is-the-target-service-actually-ready","4. Is the target service actually ready?",[140,1164,1165,1168],{},[201,1166,1167],{},"depends_on"," only controls startup order. It does not guarantee readiness.",[140,1170,1171],{},"A database container may be started but still not ready to accept connections.",[140,1173,1174],{},"That means your app may need:",[169,1176,1177,1180,1183],{},[172,1178,1179],{},"retries on startup",[172,1181,1182],{},"health checks",[172,1184,1185],{},"wait-for-it style readiness logic",[269,1187,1189],{"id":1188},"_5-can-you-test-connectivity-from-inside-the-container","5. Can you test connectivity from inside the container?",[140,1191,1192],{},"You can exec into a running container:",[216,1194,1196],{"className":302,"code":1195,"language":304,"meta":221,"style":221},"docker exec -it backend-api sh\n",[201,1197,1198],{"__ignoreMap":221},[225,1199,1200,1202,1205,1208,1210],{"class":227,"line":228},[225,1201,312],{"class":311},[225,1203,1204],{"class":315}," exec",[225,1206,1207],{"class":315}," -it",[225,1209,408],{"class":315},[225,1211,1212],{"class":315}," sh\n",[140,1214,1215],{},"Then test DNS or connectivity from there.",[140,1217,1218],{},"For example, depending on the image tools available:",[216,1220,1222],{"className":302,"code":1221,"language":304,"meta":221,"style":221},"ping db\nnc -zv db 5432\n",[201,1223,1224,1231],{"__ignoreMap":221},[225,1225,1226,1229],{"class":227,"line":228},[225,1227,1228],{"class":311},"ping",[225,1230,570],{"class":315},[225,1232,1233,1236,1239,1242],{"class":227,"line":347},[225,1234,1235],{"class":311},"nc",[225,1237,1238],{"class":315}," -zv",[225,1240,1241],{"class":315}," db",[225,1243,1244],{"class":534}," 5432\n",[140,1246,1247,1248,1250],{},"Even when ",[201,1249,1228],{}," is unavailable, being inside the container helps you reason about the real environment.",[158,1252,1254],{"id":1253},"docker-networks-and-security","Docker networks and security",[140,1256,1257],{},"Docker networking is not a full security boundary on its own, but good network design reduces unnecessary exposure.",[140,1259,1260],{},"Some practical rules:",[169,1262,1263,1266,1269,1272],{},[172,1264,1265],{},"do not publish ports you do not need on the host",[172,1267,1268],{},"keep internal-only services on internal networks",[172,1270,1271],{},"avoid putting databases directly on publicly reachable paths",[172,1273,1274],{},"prefer service-to-service communication over host-based routing when possible",[140,1276,1277],{},"A containerized architecture becomes much easier to reason about when each service only sees what it actually needs to see.",[158,1279,1281],{"id":1280},"a-simple-rule-for-local-development","A simple rule for local development",[140,1283,1284],{},"For most backend projects, this rule gets you surprisingly far:",[169,1286,1287,1290,1293,1296],{},[172,1288,1289],{},"use Docker Compose",[172,1291,1292],{},"let services share the default Compose network",[172,1294,1295],{},"connect by service name",[172,1297,1298],{},"only publish the ports you need from your host machine",[140,1300,1301],{},"That keeps the setup understandable and easy to debug.",[158,1303,1305],{"id":1304},"final-takeaway","Final takeaway",[140,1307,1308],{},"Docker networks are not just plumbing. They shape how your services discover each other, how much of your system is exposed, and how maintainable your environment becomes as the project grows.",[140,1310,1311],{},"If you remember only three things, make them these:",[1313,1314,1315,1320,1323],"ol",{},[172,1316,1317,1319],{},[201,1318,203],{}," inside a container means that container itself.",[172,1321,1322],{},"Containers on the same user-defined or Compose network should talk using service names.",[172,1324,1325],{},"Published host ports are for host access, not for container-to-container communication.",[140,1327,1328],{},"Once you internalize those three ideas, Docker networking stops feeling random and starts feeling predictable.",[140,1330,1331],{},"And that is usually the point where containerized systems get easier to work with.",[1333,1334,1335],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}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 .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":221,"searchDepth":347,"depth":347,"links":1337},[1338,1339,1340,1344,1345,1346,1347,1353,1354,1361,1362,1363],{"id":160,"depth":347,"text":161},{"id":192,"depth":347,"text":193},{"id":250,"depth":347,"text":251,"children":1341},[1342,1343],{"id":271,"depth":358,"text":272},{"id":278,"depth":358,"text":279},{"id":455,"depth":347,"text":456},{"id":492,"depth":347,"text":493},{"id":719,"depth":347,"text":720},{"id":808,"depth":347,"text":809,"children":1348},[1349,1350,1351,1352],{"id":815,"depth":358,"text":816},{"id":836,"depth":358,"text":837},{"id":857,"depth":358,"text":858},{"id":874,"depth":358,"text":875},{"id":894,"depth":347,"text":895},{"id":1111,"depth":347,"text":1112,"children":1355},[1356,1357,1358,1359,1360],{"id":1118,"depth":358,"text":1119},{"id":1147,"depth":358,"text":1148},{"id":1154,"depth":358,"text":1155},{"id":1161,"depth":358,"text":1162},{"id":1188,"depth":358,"text":1189},{"id":1253,"depth":347,"text":1254},{"id":1280,"depth":347,"text":1281},{"id":1304,"depth":347,"text":1305},"2026-03-09","A practical guide to Docker networks, how containers talk to each other, and how to design safer local and production-ready service communication.","md","/images/blog-docker-networks.svg","https://medium.com/@your-handle/docker-networks-explained-for-real-projects",{},{"title":10,"description":1365},"a7aWAHUImN0FlS07Vdw_vkNw6nqn-AgSNPm58FMokMI",1773085425617]