[{"data":1,"prerenderedAt":3745},["ShallowReactive",2],{"content-index":3,"doc-es-docker":80},{"en":4,"de":54,"es":67},{"paths":5,"docs":29},[6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28],"\u002Fdocs\u002Fgetting-started","\u002Fdocs\u002Flinux","\u002Fdocs\u002Fmacos","\u002Fdocs\u002Fwindows","\u002Fdocs\u002Fdocker","\u002Fdocs\u002Fcreate-api-key","\u002Fguides\u002Ffind-your-public-ip-address\u002Ffind-your-ip-address-on-linux","\u002Fguides\u002Ffind-your-public-ip-address\u002Ffind-your-ip-address-on-mac","\u002Fguides\u002Ffind-your-public-ip-address\u002Ffind-your-ip-address-on-windows","\u002Fguides\u002Ffind-your-public-ip-address","\u002Fguides\u002Fself-hosting\u002Fdocker-desktop-mac-client-ip","\u002Fguides\u002Fself-hosting\u002Fexpose-docker-containers-to-the-internet","\u002Fguides\u002Fself-hosting\u002Fexpose-home-server-to-internet","\u002Fguides\u002Fself-hosting\u002Fgetpublicip-vs-cloudflare-tunnel-vs-tailscale","\u002Fguides\u002Fself-hosting\u002Fmac-mini-home-server","\u002Fguides\u002Fself-hosting\u002Fport-forwarding-not-working","\u002Fguides\u002Fself-hosting\u002Fself-hosting-behind-carrier-grade-nat-cgnat","\u002Fguides\u002Fself-hosting\u002Fwireguard-simple-watchdog-script","\u002Fguides\u002Fstatic-public-ip-address\u002Fhow-to-get-a-public-ip-address","\u002Fguides\u002Fstatic-public-ip-address\u002Fhow-to-get-a-static-ip-address","\u002Fguides\u002Fstatic-public-ip-address","\u002Fguides\u002Fuse-cases\u002Fhome-server","\u002Fguides\u002Fuse-cases\u002Foffice-server",[30,34,38,42,46,50],{"path":6,"title":31,"icon":32,"stem":33},"Getting Started","mdi-file-document-outline","docs\u002F1.getting-started",{"path":7,"title":35,"icon":36,"stem":37},"Linux","mdi-linux","docs\u002F2.linux",{"path":8,"title":39,"icon":40,"stem":41},"macOS","mdi-apple","docs\u002F3.macos",{"path":9,"title":43,"icon":44,"stem":45},"Windows","mdi-microsoft-windows","docs\u002F3.windows",{"path":10,"title":47,"icon":48,"stem":49},"Docker","mdi-docker","docs\u002F4.docker",{"path":11,"title":51,"icon":52,"stem":53},"Create API Key","mdi-key","docs\u002F5.create-api-key",{"paths":55,"docs":58},[6,7,8,9,10,11,12,14,15,56,17,18,57,19,21,22,24,25,26,27,28],"\u002Fguides\u002Fself-hosting\u002Fdyndns-hinter-cgnat","\u002Fguides\u002Fself-hosting\u002Ffritzbox-portfreigabe-ds-lite",[59,61,62,63,64,65],{"path":6,"title":60,"icon":32,"stem":33},"Erste Schritte",{"path":7,"title":35,"icon":36,"stem":37},{"path":8,"title":39,"icon":40,"stem":41},{"path":9,"title":43,"icon":44,"stem":45},{"path":10,"title":47,"icon":48,"stem":49},{"path":11,"title":66,"icon":52,"stem":53},"API-Schlüssel erstellen",{"paths":68,"docs":71},[6,7,8,9,10,11,12,14,15,69,70,17,18,19,21,22,24,25,26,27,28],"\u002Fguides\u002Fself-hosting\u002Fcomo-saber-si-tengo-cgnat","\u002Fguides\u002Fself-hosting\u002Fddns-detras-de-cgnat",[72,74,75,76,77,78],{"path":6,"title":73,"icon":32,"stem":33},"Primeros pasos",{"path":7,"title":35,"icon":36,"stem":37},{"path":8,"title":39,"icon":40,"stem":41},{"path":9,"title":43,"icon":44,"stem":45},{"path":10,"title":47,"icon":48,"stem":49},{"path":11,"title":79,"icon":52,"stem":53},"Crear clave API",{"id":81,"title":82,"body":83,"createdAt":3713,"description":3714,"extension":3715,"faq":3716,"meta":3739,"navigation":3740,"path":10,"seo":3742,"stem":49,"updatedAt":3743,"__hash__":3744},"content_es\u002Fdocs\u002F4.docker.md","Configura una IP pública con Docker",{"type":84,"value":85,"toc":3675},"minimark",[86,90,99,102,107,181,194,208,212,223,249,262,266,269,434,445,457,462,469,660,663,682,689,707,711,721,729,840,918,928,931,934,938,941,947,953,968,978,982,992,1002,1067,1080,1090,1103,1107,1110,1124,1128,1131,1134,1138,1141,1175,1179,1182,1186,1192,1242,1273,1285,1289,1296,1402,1409,1413,1443,1450,1453,1459,1474,1478,1485,1488,1507,1510,1513,1516,1527,1533,1536,1539,1546,1552,1561,1568,1571,1575,1578,1583,1589,1593,1599,1602,1605,1609,1612,1616,2006,2010,2024,2440,2443,2456,2466,2490,2500,2519,2526,2538,2542,2545,2584,2590,2593,2600,2604,2614,2617,2658,2662,2669,2672,2811,2819,2822,2844,2847,2851,2857,2884,2887,2891,2897,2903,2909,2945,2949,3016,3019,3026,3029,3032,3038,3041,3047,3057,3074,3077,3084,3093,3096,3100,3106,3110,3116,3119,3122,3126,3132,3422,3425,3484,3488,3506,3521,3534,3548,3557,3581,3594,3607,3618,3630,3643,3652,3655,3671],[87,88,47],"h1",{"id":89},"docker",[91,92,93,94,98],"p",{},"Si tus servicios se ejecutan con Docker Compose, añade nuestro contenedor al proyecto y serán\naccesibles desde internet en tu dirección IPv4 pública dedicada, sin cambiar nada en los propios\nservicios. El tráfico entrante llega por el túnel y no a través de un puerto publicado, así que\nno tienes que añadir entradas ",[95,96,97],"code",{},"ports:",", no necesitas una dirección enrutable de tu operador y no\nhay nada que abrir en el router ni en el firewall del host.",[100,101],"docs-toc",{},[103,104,106],"h2",{"id":105},"antes-de-empezar","Antes de empezar",[108,109,110,126,143,156],"ul",{},[111,112,113,114,118,119],"li",{},"Una dirección IP de GetPublicIP y su ",[115,116,117],"strong",{},"clave API",". Consulta\n",[120,121,125],"a",{"className":122,"href":124},[123],"link","\u002Fes\u002Fdocs\u002Fcreate-api-key","Crear una clave API",[111,127,128,131,132,135,136,139,140],{},[115,129,130],{},"Linux:"," Docker Engine y ",[115,133,134],{},"Compose v2",", es decir, ",[95,137,138],{},"docker compose"," en lugar del antiguo\nscript ",[95,141,142],{},"docker-compose",[111,144,145,148,149,155],{},[115,146,147],{},"macOS:"," ",[120,150,154],{"className":151,"href":152,"target":153},[123],"https:\u002F\u002Fwww.docker.com\u002Fproducts\u002Fdocker-desktop\u002F","_blank","Docker Desktop",", en Intel o Apple Silicon",[111,157,158,148,161,164,165,168,169,172,173,176,177,180],{},[115,159,160],{},"Windows:",[120,162,154],{"className":163,"href":152,"target":153},[123]," en modo de ",[115,166,167],{},"contenedores Linux",", con un ",[115,170,171],{},"kernel de WSL2 6.6",". Compruébalo\ncon ",[95,174,175],{},"wsl --version"," y ejecuta ",[95,178,179],{},"wsl --update"," si muestra una versión anterior, porque a los\nkernels anteriores a 6.6 les falta un módulo de netfilter que el túnel necesita",[91,182,183,184,188,189,193],{},"Todo lo que hay en esta página funciona sin cambios en Windows y macOS con Docker Desktop, sin\ninstalar nada más que el propio Docker Desktop. Docker Desktop es gratuito para uso personal,\neducación, proyectos de código abierto no comerciales y pequeñas empresas con menos de 250\nempleados y menos de 10 millones de USD de ingresos anuales; las organizaciones más grandes\nnecesitan una suscripción de pago de Docker. Consulta\n",[120,185,39],{"className":186,"href":187},[123],"#macos"," y ",[120,190,43],{"className":191,"href":192},[123],"#windows"," para ver\nlos detalles de cada uno.",[91,195,196,197,188,200,203,204,207],{},"La imagen se publica para ",[95,198,199],{},"linux\u002Famd64",[95,201,202],{},"linux\u002Farm64"," en\n",[95,205,206],{},"ghcr.io\u002Fgetpublicip\u002Fgetpublicip",".",[103,209,211],{"id":210},"pon-tu-clave-api-en-un-archivo-env","Pon tu clave API en un archivo .env",[91,213,214,215,218,219,222],{},"Crea un archivo ",[95,216,217],{},".env"," junto a tu archivo de Compose. Consulta\n",[120,220,125],{"className":221,"href":124},[123]," para más información.",[224,225,230],"pre",{"className":226,"code":227,"language":228,"meta":229,"style":229},"language-bash shiki shiki-themes monokai","GETPUBLICIP_API_KEY=your-api-key-from-the-dashboard\n","bash","",[95,231,232],{"__ignoreMap":229},[233,234,237,241,245],"span",{"class":235,"line":236},"line",1,[233,238,240],{"class":239},"sCdxs","GETPUBLICIP_API_KEY",[233,242,244],{"class":243},"s8I7P","=",[233,246,248],{"class":247},"s_Ekj","your-api-key-from-the-dashboard\n",[91,250,251,252,255,256,258,259,207],{},"Compose lee el archivo .env automáticamente, y por eso los archivos de Compose de abajo hacen\nreferencia a ",[95,253,254],{},"${GETPUBLICIP_API_KEY}"," en lugar de contener la clave. Añade ",[95,257,217],{}," a tu\n",[95,260,261],{},".gitignore",[103,263,265],{"id":264},"añádelo-a-tu-archivo-de-docker-compose","Añádelo a tu archivo de Docker Compose",[91,267,268],{},"Añade este servicio junto a los contenedores que ya ejecutas:",[224,270,274],{"className":271,"code":272,"language":273,"meta":229,"style":229},"language-yaml shiki shiki-themes monokai","services:\n  getpublicip:\n    image: ghcr.io\u002Fgetpublicip\u002Fgetpublicip:latest\n    restart: unless-stopped\n    environment:\n      GETPUBLICIP_API_KEY: \"${GETPUBLICIP_API_KEY}\"\n      GETPUBLICIP_MAPPINGS: \"8080\u002Ftcp->web:80; 443\u002Ftcp->web:443\"\n    cap_add:\n      - NET_ADMIN\n    devices:\n      - \u002Fdev\u002Fnet\u002Ftun\n    sysctls:\n      net.ipv4.ip_forward: 1\n      net.ipv4.conf.all.src_valid_mark: 1\n      net.ipv6.conf.all.forwarding: 1\n    networks:\n      - appnet\n","yaml",[95,275,276,284,292,304,315,323,334,345,353,362,370,378,386,398,408,418,426],{"__ignoreMap":229},[233,277,278,281],{"class":235,"line":236},[233,279,280],{"class":243},"services",[233,282,283],{"class":239},":\n",[233,285,287,290],{"class":235,"line":286},2,[233,288,289],{"class":243},"  getpublicip",[233,291,283],{"class":239},[233,293,295,298,301],{"class":235,"line":294},3,[233,296,297],{"class":243},"    image",[233,299,300],{"class":239},": ",[233,302,303],{"class":247},"ghcr.io\u002Fgetpublicip\u002Fgetpublicip:latest\n",[233,305,307,310,312],{"class":235,"line":306},4,[233,308,309],{"class":243},"    restart",[233,311,300],{"class":239},[233,313,314],{"class":247},"unless-stopped\n",[233,316,318,321],{"class":235,"line":317},5,[233,319,320],{"class":243},"    environment",[233,322,283],{"class":239},[233,324,326,329,331],{"class":235,"line":325},6,[233,327,328],{"class":243},"      GETPUBLICIP_API_KEY",[233,330,300],{"class":239},[233,332,333],{"class":247},"\"${GETPUBLICIP_API_KEY}\"\n",[233,335,337,340,342],{"class":235,"line":336},7,[233,338,339],{"class":243},"      GETPUBLICIP_MAPPINGS",[233,341,300],{"class":239},[233,343,344],{"class":247},"\"8080\u002Ftcp->web:80; 443\u002Ftcp->web:443\"\n",[233,346,348,351],{"class":235,"line":347},8,[233,349,350],{"class":243},"    cap_add",[233,352,283],{"class":239},[233,354,356,359],{"class":235,"line":355},9,[233,357,358],{"class":239},"      - ",[233,360,361],{"class":247},"NET_ADMIN\n",[233,363,365,368],{"class":235,"line":364},10,[233,366,367],{"class":243},"    devices",[233,369,283],{"class":239},[233,371,373,375],{"class":235,"line":372},11,[233,374,358],{"class":239},[233,376,377],{"class":247},"\u002Fdev\u002Fnet\u002Ftun\n",[233,379,381,384],{"class":235,"line":380},12,[233,382,383],{"class":243},"    sysctls",[233,385,283],{"class":239},[233,387,389,392,394],{"class":235,"line":388},13,[233,390,391],{"class":243},"      net.ipv4.ip_forward",[233,393,300],{"class":239},[233,395,397],{"class":396},"s7s5_","1\n",[233,399,401,404,406],{"class":235,"line":400},14,[233,402,403],{"class":243},"      net.ipv4.conf.all.src_valid_mark",[233,405,300],{"class":239},[233,407,397],{"class":396},[233,409,411,414,416],{"class":235,"line":410},15,[233,412,413],{"class":243},"      net.ipv6.conf.all.forwarding",[233,415,300],{"class":239},[233,417,397],{"class":396},[233,419,421,424],{"class":235,"line":420},16,[233,422,423],{"class":243},"    networks",[233,425,283],{"class":239},[233,427,429,431],{"class":235,"line":428},17,[233,430,358],{"class":239},[233,432,433],{"class":247},"appnet\n",[91,435,436,437,440,441,444],{},"Sustituye ",[95,438,439],{},"appnet"," por la red en la que ya están tus servicios, y ",[95,442,443],{},"web"," por los nombres de tus\npropios servicios. Todo lo demás puede quedarse como está.",[91,446,447,448,451,452,207],{},"Mantén ",[95,449,450],{},"restart: unless-stopped",". Es la forma en que el agente se recupera de los fallos que no\npuede arreglar sobre la marcha, como se describe en\n",[120,453,456],{"className":454,"href":455},[123],"#caídas-de-conexión","Caídas de conexión",[458,459,461],"h3",{"id":460},"un-ejemplo-completo-que-funciona","Un ejemplo completo que funciona",[91,463,464,465,468],{},"Si todavía no tienes un proyecto de Compose, este archivo es una configuración completa: un\nservidor web en tu propia dirección IP pública, accesible desde cualquier lugar. Guárdalo como\n",[95,466,467],{},"compose.yaml",":",[224,470,472],{"className":271,"code":471,"language":273,"meta":229,"style":229},"services:\n  web:\n    image: nginx:alpine\n    restart: unless-stopped\n    networks:\n      - appnet\n\n  getpublicip:\n    image: ghcr.io\u002Fgetpublicip\u002Fgetpublicip:latest\n    restart: unless-stopped\n    environment:\n      GETPUBLICIP_API_KEY: \"${GETPUBLICIP_API_KEY}\"\n      GETPUBLICIP_MAPPINGS: \"80\u002Ftcp->web:80\"\n    cap_add:\n      - NET_ADMIN\n    devices:\n      - \u002Fdev\u002Fnet\u002Ftun\n    sysctls:\n      net.ipv4.ip_forward: 1\n      net.ipv4.conf.all.src_valid_mark: 1\n      net.ipv6.conf.all.forwarding: 1\n    networks:\n      - appnet\n\nnetworks:\n  appnet:\n",[95,473,474,480,487,496,504,510,516,522,528,536,544,550,558,567,573,579,585,591,598,607,616,625,632,639,644,652],{"__ignoreMap":229},[233,475,476,478],{"class":235,"line":236},[233,477,280],{"class":243},[233,479,283],{"class":239},[233,481,482,485],{"class":235,"line":286},[233,483,484],{"class":243},"  web",[233,486,283],{"class":239},[233,488,489,491,493],{"class":235,"line":294},[233,490,297],{"class":243},[233,492,300],{"class":239},[233,494,495],{"class":247},"nginx:alpine\n",[233,497,498,500,502],{"class":235,"line":306},[233,499,309],{"class":243},[233,501,300],{"class":239},[233,503,314],{"class":247},[233,505,506,508],{"class":235,"line":317},[233,507,423],{"class":243},[233,509,283],{"class":239},[233,511,512,514],{"class":235,"line":325},[233,513,358],{"class":239},[233,515,433],{"class":247},[233,517,518],{"class":235,"line":336},[233,519,521],{"emptyLinePlaceholder":520},true,"\n",[233,523,524,526],{"class":235,"line":347},[233,525,289],{"class":243},[233,527,283],{"class":239},[233,529,530,532,534],{"class":235,"line":355},[233,531,297],{"class":243},[233,533,300],{"class":239},[233,535,303],{"class":247},[233,537,538,540,542],{"class":235,"line":364},[233,539,309],{"class":243},[233,541,300],{"class":239},[233,543,314],{"class":247},[233,545,546,548],{"class":235,"line":372},[233,547,320],{"class":243},[233,549,283],{"class":239},[233,551,552,554,556],{"class":235,"line":380},[233,553,328],{"class":243},[233,555,300],{"class":239},[233,557,333],{"class":247},[233,559,560,562,564],{"class":235,"line":388},[233,561,339],{"class":243},[233,563,300],{"class":239},[233,565,566],{"class":247},"\"80\u002Ftcp->web:80\"\n",[233,568,569,571],{"class":235,"line":400},[233,570,350],{"class":243},[233,572,283],{"class":239},[233,574,575,577],{"class":235,"line":410},[233,576,358],{"class":239},[233,578,361],{"class":247},[233,580,581,583],{"class":235,"line":420},[233,582,367],{"class":243},[233,584,283],{"class":239},[233,586,587,589],{"class":235,"line":428},[233,588,358],{"class":239},[233,590,377],{"class":247},[233,592,594,596],{"class":235,"line":593},18,[233,595,383],{"class":243},[233,597,283],{"class":239},[233,599,601,603,605],{"class":235,"line":600},19,[233,602,391],{"class":243},[233,604,300],{"class":239},[233,606,397],{"class":396},[233,608,610,612,614],{"class":235,"line":609},20,[233,611,403],{"class":243},[233,613,300],{"class":239},[233,615,397],{"class":396},[233,617,619,621,623],{"class":235,"line":618},21,[233,620,413],{"class":243},[233,622,300],{"class":239},[233,624,397],{"class":396},[233,626,628,630],{"class":235,"line":627},22,[233,629,423],{"class":243},[233,631,283],{"class":239},[233,633,635,637],{"class":235,"line":634},23,[233,636,358],{"class":239},[233,638,433],{"class":247},[233,640,642],{"class":235,"line":641},24,[233,643,521],{"emptyLinePlaceholder":520},[233,645,647,650],{"class":235,"line":646},25,[233,648,649],{"class":243},"networks",[233,651,283],{"class":239},[233,653,655,658],{"class":235,"line":654},26,[233,656,657],{"class":243},"  appnet",[233,659,283],{"class":239},[91,661,662],{},"Después, inícialo:",[224,664,666],{"className":226,"code":665,"language":228,"meta":229,"style":229},"docker compose up -d\n",[95,667,668],{"__ignoreMap":229},[233,669,670,673,676,679],{"class":235,"line":236},[233,671,89],{"class":672},"sHkqI",[233,674,675],{"class":247}," compose",[233,677,678],{"class":247}," up",[233,680,681],{"class":396}," -d\n",[91,683,684,685,688],{},"Espera entre 30 y 60 segundos y abre ",[95,686,687],{},"http:\u002F\u002F{YOUR IP ADDRESS}"," desde cualquier red, o desde tu\nteléfono con datos móviles. Si ves la página de bienvenida de nginx, una solicitud desde\ninternet ha llegado a tu contenedor.",[91,690,691,693,694,696,697,699,700,702,703,706],{},[95,692,443],{}," no tiene ninguna entrada ",[95,695,97],{},". El agente llega a nginx a través de la red interna\n",[95,698,439],{},", y los dos servicios se unen a ella porque el agente resuelve ",[95,701,443],{}," por su nombre de\nservicio, algo que solo funciona en una red que compartan ambos. Si quitaras los bloques\n",[95,704,705],{},"networks:",", Compose pondría los dos en la red predeterminada del proyecto, y eso funciona igual\nde bien, pero darle nombre a la red deja visible el requisito.",[103,708,710],{"id":709},"redirige-tus-puertos","Redirige tus puertos",[91,712,713,716,717,720],{},[95,714,715],{},"GETPUBLICIP_MAPPINGS"," decide qué puertos de tu IP pública van a cada uno de tus contenedores.\nSepara las entradas con ",[95,718,719],{},";"," o con saltos de línea:",[224,722,727],{"className":723,"code":725,"language":726},[724],"language-text","publicPort[\u002Fproto[,proto]][\u002Fstack[,stack]]->service[:internalPort]\n","text",[95,728,725],{"__ignoreMap":229},[730,731,732,748],"table",{},[733,734,735],"thead",{},[736,737,738,742,745],"tr",{},[739,740,741],"th",{},"Parte",[739,743,744],{},"Valor predeterminado",[739,746,747],{},"Notas",[749,750,751,768,789,809,825],"tbody",{},[736,752,753,759,762],{},[754,755,756],"td",{},[95,757,758],{},"publicPort",[754,760,761],{},"Ninguno",[754,763,764,765],{},"un solo puerto, o un rango como ",[95,766,767],{},"60000-60099",[736,769,770,775,780],{},[754,771,772],{},[95,773,774],{},"proto",[754,776,777],{},[95,778,779],{},"tcp",[754,781,782,784,785,788],{},[95,783,779],{}," o ",[95,786,787],{},"udp","; sepáralos con comas para usar ambos",[736,790,791,796,801],{},[754,792,793],{},[95,794,795],{},"stack",[754,797,798],{},[95,799,800],{},"ipv4",[754,802,803,784,805,808],{},[95,804,800],{},[95,806,807],{},"ipv6","; sepáralos con comas para doble pila",[736,810,811,816,818],{},[754,812,813],{},[95,814,815],{},"service",[754,817,761],{},[754,819,820,821,824],{},"el destino, que se resuelve en tiempo de ejecución: un ",[115,822,823],{},"nombre de servicio"," de Compose, cualquier nombre de host que se pueda resolver o una dirección IPv4 literal",[736,826,827,832,837],{},[754,828,829],{},[95,830,831],{},"internalPort",[754,833,834,835],{},"igual que ",[95,836,758],{},[754,838,839],{},"el puerto en el destino; para un rango, omítelo o repite el mismo rango",[730,841,842,852],{},[733,843,844],{},[736,845,846,849],{},[739,847,848],{},"Ejemplo",[739,850,851],{},"Significado",[749,853,854,867,880,894,904],{},[736,855,856,861],{},[754,857,858],{},[95,859,860],{},"8080\u002Ftcp->web:80",[754,862,863,864,866],{},"El TCP 8080 de tu IP pública va a ",[95,865,443],{}," en el puerto 80",[736,868,869,874],{},[754,870,871],{},[95,872,873],{},"443\u002Ftcp,udp->web:443",[754,875,876,877,879],{},"TCP y UDP 443 van a ",[95,878,443],{}," en el puerto 443",[736,881,882,887],{},[754,883,884],{},[95,885,886],{},"53\u002Fudp->dns:53",[754,888,889,890,893],{},"UDP 53 va a ",[95,891,892],{},"dns"," en el puerto 53",[736,895,896,901],{},[754,897,898],{},[95,899,900],{},"9000\u002Ftcp\u002Fipv4,ipv6->api",[754,902,903],{},"doble pila; el puerto interno es 9000 de forma predeterminada",[736,905,906,911],{},[754,907,908],{},[95,909,910],{},"60000-60099\u002Fudp->turn",[754,912,913,914,917],{},"UDP del 60000 al 60099 va a ",[95,915,916],{},"turn"," en los mismos puertos",[91,919,920,921,188,924,927],{},"Los segmentos que siguen al puerto se reconocen por palabra clave, así que su orden no importa.\n",[95,922,923],{},"8080\u002Ftcp\u002Fipv4",[95,925,926],{},"8080\u002Fipv4\u002Ftcp"," significan lo mismo.",[91,929,930],{},"Refiérete a tus contenedores por su nombre de servicio, nunca por su dirección IP. Compose\nasigna las IP de los contenedores de forma dinámica, así que el agente resuelve los nombres por\nsu cuenta y los vuelve a comprobar cada 30 segundos. Cuando un contenedor se reinicia con otra\nIP, el agente actualiza las reglas de reenvío.",[91,932,933],{},"Un destino también puede ser cualquier nombre de host que se resuelva o una dirección IPv4\nliteral, y las tres opciones se comportan igual. No se acepta una dirección IPv6 literal; usa en\nsu lugar un nombre de host con un registro AAAA.",[458,935,937],{"id":936},"rangos-de-puertos","Rangos de puertos",[91,939,940],{},"Algunos servicios necesitan un bloque entero de puertos en lugar de uno solo: un servidor TURN\npara llamadas de voz y videollamadas, FTP en modo pasivo o cualquier cosa que transporte medios\nRTP. Escribe el puerto público como un rango y cada puerto del rango se redirige al mismo\npuerto de tu contenedor:",[224,942,945],{"className":943,"code":944,"language":726},[724],"GETPUBLICIP_MAPPINGS: \"3478\u002Ftcp,udp->turn; 60000-60099\u002Fudp->turn\"\n",[95,946,944],{"__ignoreMap":229},[91,948,949,950,952],{},"El puerto 60042 de tu IP pública siempre llega al puerto 60042 de ",[95,951,916],{},". Estos servicios le\nindican al otro extremo qué puerto usar, así que un puerto que hubiera cambiado por el camino\nrompería la conexión sin ningún error.",[91,954,955,956,959,960,963,964,967],{},"Por el mismo motivo, un rango solo puede ir al mismo rango. Puedes omitir el puerto interno,\ncomo arriba, o repetir el rango exactamente (",[95,957,958],{},"60000-60099\u002Fudp->turn:60000-60099","). Enviarlo a\npuertos distintos, como ",[95,961,962],{},"->turn:61000-61099",", se rechaza al iniciar el contenedor con\n",[95,965,966],{},"a port range must forward to the same range",". Un rango tampoco puede incluir el puerto 51820,\nque usa el propio túnel.",[91,969,970,971],{},"Abre solo los puertos que tu servicio esté configurado para usar. En un servidor TURN, eso\nsignifica el rango de puertos de relay que tenga configurado, no todo lo que está por encima de\n49152. ",[115,972,973,974,977],{},"Requiere la imagen ",[95,975,976],{},"1.3.1"," o posterior.",[458,979,981],{"id":980},"redirigir-ipv6","Redirigir IPv6",[91,983,984,985,987,988,991],{},"Las redirecciones son IPv4 salvo que indiques otra cosa, así que añade la pila ",[95,986,807],{}," para\nredirigir tu dirección IPv6 pública, o ",[95,989,990],{},"ipv4,ipv6"," para redirigir ambas. Para que funcione\ntienen que cumplirse dos condiciones.",[91,993,994,997,998,1001],{},[115,995,996],{},"Tu red de Compose necesita tener IPv6 activado."," Las redes bridge de Docker son solo IPv4 de\nforma predeterminada, así que un contenedor en una de ellas no tiene una dirección IPv6 a la que\nel agente pueda reenviar. Añade a la red ",[95,999,1000],{},"enable_ipv6: true"," y una subred IPv6:",[224,1003,1005],{"className":271,"code":1004,"language":273,"meta":229,"style":229},"networks:\n  appnet:\n    enable_ipv6: true\n    ipam:\n      config:\n        - subnet: 172.29.7.0\u002F24\n        - subnet: fd00:dead:beef::\u002F64\n",[95,1006,1007,1013,1019,1029,1036,1043,1056],{"__ignoreMap":229},[233,1008,1009,1011],{"class":235,"line":236},[233,1010,649],{"class":243},[233,1012,283],{"class":239},[233,1014,1015,1017],{"class":235,"line":286},[233,1016,657],{"class":243},[233,1018,283],{"class":239},[233,1020,1021,1024,1026],{"class":235,"line":294},[233,1022,1023],{"class":243},"    enable_ipv6",[233,1025,300],{"class":239},[233,1027,1028],{"class":396},"true\n",[233,1030,1031,1034],{"class":235,"line":306},[233,1032,1033],{"class":243},"    ipam",[233,1035,283],{"class":239},[233,1037,1038,1041],{"class":235,"line":317},[233,1039,1040],{"class":243},"      config",[233,1042,283],{"class":239},[233,1044,1045,1048,1051,1053],{"class":235,"line":325},[233,1046,1047],{"class":239},"        - ",[233,1049,1050],{"class":243},"subnet",[233,1052,300],{"class":239},[233,1054,1055],{"class":247},"172.29.7.0\u002F24\n",[233,1057,1058,1060,1062,1064],{"class":235,"line":336},[233,1059,1047],{"class":239},[233,1061,1050],{"class":243},[233,1063,300],{"class":239},[233,1065,1066],{"class":247},"fd00:dead:beef::\u002F64\n",[91,1068,1069,1072,1073,1076,1077,1079],{},[115,1070,1071],{},"La pila se aplica tanto al destino como al puerto público."," Las reglas de reenvío no pueden\ntraducir entre las dos familias de direcciones, así que una solicitud IPv6 tiene que llegar a tu\ncontenedor por IPv6. Por eso, ",[95,1074,1075],{},"8080\u002Ftcp\u002Fipv4,ipv6->web:80"," necesita que ",[95,1078,443],{}," tenga tanto una\ndirección IPv4 como una IPv6, y eso es lo que le da la red de arriba.",[91,1081,447,1082,1085,1086,1089],{},[95,1083,1084],{},"net.ipv6.conf.all.forwarding: 1"," en el bloque ",[95,1087,1088],{},"sysctls"," del agente. Ya está en los\nejemplos de esta página, y solo hace falta cuando rediriges IPv6.",[91,1091,1092,1093,1096,1097,1099,1100,207],{},"Si falta algo, el agente te indica qué destino y qué familia fallaron, con\n",[95,1094,1095],{},"no destination resolved in the family its mapping asked for",". Si una configuración que por lo\ndemás funciona bien muestra esa línea para una redirección ",[95,1098,807],{},", casi siempre se trata de una\nred sin ",[95,1101,1102],{},"enable_ipv6",[103,1104,1106],{"id":1105},"ssl-tls","SSL \u002F TLS",[91,1108,1109],{},"GetPublicIP trabaja a nivel de paquete. Reenvía TCP y UDP a tus contenedores, y el cifrado y\nlos certificados quedan en tus manos: si sirves HTTPS, es tu propio servicio el que termina la\nconexión TLS. Redirige el 443 al contenedor que ya tiene tu certificado, y tu configuración TLS\nse queda como está:",[224,1111,1113],{"className":271,"code":1112,"language":273,"meta":229,"style":229},"GETPUBLICIP_MAPPINGS: \"443\u002Ftcp->web:443; 80\u002Ftcp->web:80\"\n",[95,1114,1115],{"__ignoreMap":229},[233,1116,1117,1119,1121],{"class":235,"line":236},[233,1118,715],{"class":243},[233,1120,300],{"class":239},[233,1122,1123],{"class":247},"\"443\u002Ftcp->web:443; 80\u002Ftcp->web:80\"\n",[458,1125,1127],{"id":1126},"no-desciframos-tu-tráfico","No desciframos tu tráfico",[91,1129,1130],{},"Tu IP pública no es un proxy TLS. No tiene ninguno de tus certificados ni de tus claves\nprivadas, así que no tiene nada con lo que descifrar. La sesión TLS se negocia directamente\nentre el navegador de tu visitante y tu propio servicio, y permanece cifrada durante todo el\ntrayecto: al salir del navegador, a través de internet hasta tu IP pública, por el túnel\nWireGuard y dentro de tu contenedor, donde se descifra por primera vez.",[91,1132,1133],{},"El túnel añade una segunda capa de cifrado, exterior, entre nuestra red y tu máquina, y dentro\nde ella viaja el mismo texto cifrado TLS que envió tu visitante. Tus certificados y claves\nprivadas nunca salen de tu máquina, y tu tráfico nunca se descifra y se vuelve a cifrar por el\ncamino. No desciframos el tráfico TLS ni tenemos planes de hacerlo.",[458,1135,1137],{"id":1136},"tu-servicio-necesita-un-certificado-válido","Tu servicio necesita un certificado válido",[91,1139,1140],{},"Como el certificado está en el servicio que termina la conexión, ese servicio necesita un\ncertificado válido, igual que en cualquier otro host público.",[108,1142,1143,1157,1163,1169],{},[111,1144,1145,1148,1149,1152,1153,1156],{},[115,1146,1147],{},"Apunta un dominio a tu IP pública."," Añade un registro ",[95,1150,1151],{},"A"," para tu dirección IPv4, y un\nregistro ",[95,1154,1155],{},"AAAA"," si también sirves IPv6. Las autoridades de certificación emiten certificados\npara nombres de dominio, así que una dirección IP sola no basta.",[111,1158,1159,1162],{},[115,1160,1161],{},"Obtén el certificado de Let's Encrypt."," Es gratuito y automatizado. Caddy y Traefik lo\nsolicitan y lo renuevan por ti sin más configuración que tu nombre de dominio; nginx y Apache\nse combinan con certbot.",[111,1164,1165,1168],{},[115,1166,1167],{},"Si usas un desafío HTTP-01, redirige el puerto 80 además del 443"," al mismo servicio. Let's\nEncrypt se conecta al puerto 80 de tu IP pública para validar el desafío, y falla si solo\nestá redirigido el 443. Un desafío DNS-01 no necesita el puerto 80.",[111,1170,1171,1174],{},[115,1172,1173],{},"No quites esas redirecciones."," La renovación repite el mismo desafío aproximadamente cada\n60 días, y falla sin avisar si la redirección ha desaparecido.",[458,1176,1178],{"id":1177},"el-http-sin-cifrar-sigue-sin-cifrar","El HTTP sin cifrar sigue sin cifrar",[91,1180,1181],{},"Una redirección al puerto 80 que sirve HTTP sin cifrar va sin cifrar entre tu visitante y tu\nIP pública, exactamente igual que en cualquier otro lugar de internet. El túnel WireGuard solo\ncubre el tramo entre nuestra red y tu máquina. Si el contenido importa, activa TLS.",[103,1183,1185],{"id":1184},"redirigir-a-un-servicio-del-host","Redirigir a un servicio del host",[91,1187,1188,1189,468],{},"Para hacer público un servicio que se ejecuta directamente en el host de Docker, apunta una\nredirección a ",[95,1190,1191],{},"host.docker.internal",[224,1193,1195],{"className":271,"code":1194,"language":273,"meta":229,"style":229},"services:\n  getpublicip:\n    environment:\n      GETPUBLICIP_MAPPINGS: \"8081\u002Ftcp->host.docker.internal:8081\"\n    extra_hosts:\n      - \"host.docker.internal:host-gateway\"   # needed on Linux; built in on Docker Desktop\n",[95,1196,1197,1203,1209,1215,1224,1231],{"__ignoreMap":229},[233,1198,1199,1201],{"class":235,"line":236},[233,1200,280],{"class":243},[233,1202,283],{"class":239},[233,1204,1205,1207],{"class":235,"line":286},[233,1206,289],{"class":243},[233,1208,283],{"class":239},[233,1210,1211,1213],{"class":235,"line":294},[233,1212,320],{"class":243},[233,1214,283],{"class":239},[233,1216,1217,1219,1221],{"class":235,"line":306},[233,1218,339],{"class":243},[233,1220,300],{"class":239},[233,1222,1223],{"class":247},"\"8081\u002Ftcp->host.docker.internal:8081\"\n",[233,1225,1226,1229],{"class":235,"line":317},[233,1227,1228],{"class":243},"    extra_hosts",[233,1230,283],{"class":239},[233,1232,1233,1235,1238],{"class":235,"line":325},[233,1234,358],{"class":239},[233,1236,1237],{"class":247},"\"host.docker.internal:host-gateway\"",[233,1239,1241],{"class":1240},"snpHw","   # needed on Linux; built in on Docker Desktop\n",[108,1243,1244,1260],{},[111,1245,1246,1256,1257,207],{},[115,1247,1248,1249,1252,1253,207],{},"El servicio del host tiene que escuchar en ",[95,1250,1251],{},"0.0.0.0",", no en ",[95,1254,1255],{},"127.0.0.1"," Un servicio\nvinculado a loopback rechaza la conexión que viene del contenedor. Compruébalo con\n",[95,1258,1259],{},"ss -lntp",[111,1261,1262,1265,1266,1269,1270,207],{},[115,1263,1264],{},"Un firewall en el host la descartará sin avisar"," a menos que permitas el tráfico entrante\ndesde la subred del bridge en ",[95,1267,1268],{},"docker0"," o en la interfaz ",[95,1271,1272],{},"br-*",[91,1274,1275,1276,1278,1279,1284],{},"Los destinos en el host y en contenedores se pueden mezclar libremente en un mismo\n",[95,1277,715],{},", salvo con\n",[120,1280,1283],{"className":1281,"href":1282},[123],"#ver-la-ip-real-del-cliente","Ver la IP real del cliente",",\nque no funciona con destinos en el host.",[103,1286,1288],{"id":1287},"redes-de-docker-compose","Redes de Docker Compose",[91,1290,1291,1292,1295],{},"Como los destinos se resuelven por nombre de servicio, el contenedor ",[95,1293,1294],{},"getpublicip"," tiene que\nestar en la misma red de Docker que los contenedores a los que reenvía.",[108,1297,1298,1304,1318],{},[111,1299,1300,1303],{},[115,1301,1302],{},"Una red predeterminada."," Funciona tal cual.",[111,1305,1306,1309,1310,1312,1313,1317],{},[115,1307,1308],{},"Varias redes."," Incluye ",[95,1311,1294],{}," en ",[1314,1315,1316],"em",{},"cada"," red que contenga un servicio al que\nreenvíe.",[111,1319,1320,1323,1324,1342,1345,1346],{},[115,1321,1322],{},"Destinos en otro proyecto de Compose."," Ambos proyectos tienen que unirse a una red externa\ncompartida:",[224,1325,1327],{"className":226,"code":1326,"language":228,"meta":229,"style":229},"docker network create shared\n",[95,1328,1329],{"__ignoreMap":229},[233,1330,1331,1333,1336,1339],{"class":235,"line":236},[233,1332,89],{"class":672},[233,1334,1335],{"class":247}," network",[233,1337,1338],{"class":247}," create",[233,1340,1341],{"class":247}," shared\n",[1343,1344],"br",{},"Después, en cada archivo de Compose:",[224,1347,1349],{"className":271,"code":1348,"language":273,"meta":229,"style":229},"services:\n  getpublicip:\n    networks:\n      - shared\n\nnetworks:\n  shared:\n    external: true\n",[95,1350,1351,1357,1363,1369,1376,1380,1386,1393],{"__ignoreMap":229},[233,1352,1353,1355],{"class":235,"line":236},[233,1354,280],{"class":243},[233,1356,283],{"class":239},[233,1358,1359,1361],{"class":235,"line":286},[233,1360,289],{"class":243},[233,1362,283],{"class":239},[233,1364,1365,1367],{"class":235,"line":294},[233,1366,423],{"class":243},[233,1368,283],{"class":239},[233,1370,1371,1373],{"class":235,"line":306},[233,1372,358],{"class":239},[233,1374,1375],{"class":247},"shared\n",[233,1377,1378],{"class":235,"line":317},[233,1379,521],{"emptyLinePlaceholder":520},[233,1381,1382,1384],{"class":235,"line":325},[233,1383,649],{"class":243},[233,1385,283],{"class":239},[233,1387,1388,1391],{"class":235,"line":336},[233,1389,1390],{"class":243},"  shared",[233,1392,283],{"class":239},[233,1394,1395,1398,1400],{"class":235,"line":347},[233,1396,1397],{"class":243},"    external",[233,1399,300],{"class":239},[233,1401,1028],{"class":396},[91,1403,1404,1405,1408],{},"Si esto está mal, los logs repiten ",[95,1406,1407],{},"waiting for destinations to resolve"," y el agente sigue\nreintentándolo en lugar de fallar directamente.",[103,1410,1412],{"id":1411},"revisa-los-logs","Revisa los logs",[224,1414,1416],{"className":226,"code":1415,"language":228,"meta":229,"style":229},"docker compose up -d\ndocker compose logs -f getpublicip\n",[95,1417,1418,1428],{"__ignoreMap":229},[233,1419,1420,1422,1424,1426],{"class":235,"line":236},[233,1421,89],{"class":672},[233,1423,675],{"class":247},[233,1425,678],{"class":247},[233,1427,681],{"class":396},[233,1429,1430,1432,1434,1437,1440],{"class":235,"line":286},[233,1431,89],{"class":672},[233,1433,675],{"class":247},[233,1435,1436],{"class":247}," logs",[233,1438,1439],{"class":396}," -f",[233,1441,1442],{"class":247}," getpublicip\n",[91,1444,1445,1446,1449],{},"Un arranque correcto levanta el túnel en la interfaz ",[95,1447,1448],{},"pi0",", resuelve tus destinos, instala las\nreglas de reenvío y envía las redirecciones a GetPublicIP. Después, el agente sigue en marcha y\nvuelve a comprobar los destinos y el propio túnel cada 30 segundos.",[91,1451,1452],{},"Un túnel en buen estado escribe en el log una línea como esta. Tenla presente para compararla\nsi el túnel da problemas más adelante:",[224,1454,1457],{"className":1455,"code":1456,"language":726},[724],"tunnel status up=true interfaces=1 peers=1 healthy=true handshakeAge=31s rxDelta=0\n",[95,1458,1456],{"__ignoreMap":229},[91,1460,1461,1462,1465,1466,1469,1470,1473],{},"Fíjate en ",[95,1463,1464],{},"healthy=true",". ",[95,1467,1468],{},"up=true"," solo significa que la interfaz existe, y sigue siendo ",[95,1471,1472],{},"true","\nincluso en un túnel que ha dejado de pasar tráfico.",[103,1475,1477],{"id":1476},"pruebas","Pruebas",[91,1479,1480,1481,1484],{},"Espera unos 30 a 60 segundos antes de probar. Al enviar redirecciones nuevas, tu dirección\nIP pasa a un estado ",[95,1482,1483],{},"updating"," mientras las aplicamos, y las solicitudes que se hagan en ese\nintervalo fallarán. Es normal que haya dos o tres fallos seguidos de un acierto.",[91,1486,1487],{},"Haz la prueba desde una red que no sea la tuya. Lo más fácil es usar datos móviles:",[224,1489,1491],{"className":226,"code":1490,"language":228,"meta":229,"style":229},"curl http:\u002F\u002F{YOUR IP ADDRESS}\n",[95,1492,1493],{"__ignoreMap":229},[233,1494,1495,1498,1501,1504],{"class":235,"line":236},[233,1496,1497],{"class":672},"curl",[233,1499,1500],{"class":247}," http:\u002F\u002F{YOUR",[233,1502,1503],{"class":247}," IP",[233,1505,1506],{"class":247}," ADDRESS}\n",[103,1508,456],{"id":1509},"caídas-de-conexión",[91,1511,1512],{},"El túnel se restablece solo tras una caída de la conexión, un reinicio del router o un cambio\nde dirección por parte de tu operador, sin que tengas que reiniciar ni configurar nada.",[91,1514,1515],{},"La mayoría de las veces se repara solo, sin que el agente tenga que hacer nada. El túnel es una\nconexión saliente que se mantiene abierta con un keepalive cada 25 segundos, y nuestro servidor\nvuelve a aprender tu dirección a partir de cualquier paquete que envíe el agente, así que, cuando\ntu router elimina la entrada NAT o te pasa a un puerto nuevo, el siguiente keepalive la\nrestablece.",[91,1517,1518,1519,1522,1523,1526],{},"Para los fallos menos frecuentes que un keepalive no puede arreglar, el agente se detiene en\nlugar de intentar reparar el túnel sobre la marcha, y Docker lo reinicia con una conexión nueva.\nEn el log verás ",[95,1520,1521],{},"tunnel appears broken"," cuando lo detecta por primera vez, y después\n",[95,1524,1525],{},"exiting so the container is restarted"," si el problema persiste durante varias comprobaciones.\nLas dos líneas forman parte de la recuperación normal.",[91,1528,1529,1530,1532],{},"La recuperación depende de tu política de reinicio, así que mantén ",[95,1531,450],{}," en\nel servicio. Sin ella, el contenedor se detiene y se queda detenido.",[91,1534,1535],{},"Mientras el host esté sin conexión a internet, tus servicios tampoco serán accesibles. El túnel\nse recupera en cuanto vuelve a haber conexión.",[103,1537,1283],{"id":1538},"ver-la-ip-real-del-cliente",[91,1540,1541,1542,1545],{},"De forma predeterminada, tus contenedores no ven la dirección IP del visitante. El contenedor de\nGetPublicIP reescribe la dirección de origen del tráfico entrante al reenviarlo, así que todos\nlos visitantes aparecen en tus logs de acceso con la misma dirección IP local. La\ngeolocalización, la limitación de solicitudes por cliente, el bloqueo de abusos y ",[95,1543,1544],{},"fail2ban"," ven\ntodos una sola dirección IP.",[91,1547,1548,1551],{},[95,1549,1550],{},"GETPUBLICIP_PRESERVE_CLIENT_IP"," desactiva esa reescritura, y entonces tus contenedores ven la\ndirección IP real del cliente.",[91,1553,1554,1557,1558,1560],{},[115,1555,1556],{},"Requiere un cambio en cada servicio al que reenvías, así que lee esto antes de activarlo.","\nMientras la dirección de origen se reescribe con una de la red de Compose, tus servicios\nresponden a través del contenedor de GetPublicIP automáticamente. Con\n",[95,1559,1550],{}," activado, la ruta predeterminada de cada servicio tiene que\napuntar al contenedor de GetPublicIP, para que sus respuestas vuelvan al cliente a través de tu\ndirección IP pública. Sin esa ruta, las respuestas salen por tu conexión a internet normal y el\ncliente las descarta.",[91,1562,1563],{},[115,1564,973,1565,977],{},[95,1566,1567],{},"1.1.0",[91,1569,1570],{},"El ajuste se aplica a todo el agente y no a una sola redirección, así que afecta a todos los\nservicios a los que reenvía ese agente.",[458,1572,1574],{"id":1573},"por-qué-hay-que-cambiar-la-ruta-predeterminada","Por qué hay que cambiar la ruta predeterminada",[91,1576,1577],{},"Todo lo demás de esta sección se deriva de lo que le ocurre a una solicitud que entra y a su\nrespuesta, que vuelve a salir:",[1579,1580,1582],"h4",{"id":1581},"de-forma-predeterminada","De forma predeterminada",[224,1584,1587],{"className":1585,"code":1586,"language":726},[724],"visitor 203.0.113.9 → your public IP → tunnel → agent \nagent rewrites the source to its own address, 172.29.7.2\nweb replies to 172.29.7.2, which is on its own subnet\nagent puts the real address back, reply leaves through the tunnel\n",[95,1588,1586],{"__ignoreMap":229},[1579,1590,1592],{"id":1591},"con-la-preservación-de-la-ip-del-cliente-activada","Con la preservación de la IP del cliente activada",[224,1594,1597],{"className":1595,"code":1596,"language":726},[724],"visitor 203.0.113.9 → your public IP → tunnel → agent\nweb sees 203.0.113.9 and then send replies to 203.0.113.9\nthe web container reply will follow the default route \n",[95,1598,1596],{"__ignoreMap":229},[91,1600,1601],{},"Un contenedor decide adónde enviar una respuesta mirando primero su propia subred y después su\nruta predeterminada. Mientras se reescribe la dirección de origen, todas las respuestas van\ndirigidas a algo de la subred local, y la ruta predeterminada nunca entra en juego. Con la\npreservación de la IP del cliente activada, todas las respuestas van dirigidas a algún lugar de\ninternet, así que la ruta predeterminada decide sobre todas ellas. La solución es, por tanto,\nuna ruta configurada dentro de cada servicio, y ningún ajuste del agente puede sustituirla.",[91,1603,1604],{},"Docker no tiene una forma integrada de hacerlo, así que los ejemplos de abajo configuran la ruta\npredeterminada de cada contenedor de servicio con un pequeño contenedor sidecar.",[458,1606,1608],{"id":1607},"proyecto-de-ejemplo","Proyecto de ejemplo",[91,1610,1611],{},"Hay dos versiones del mismo proyecto. Empieza por la de solo IPv4, a menos que también redirijas\ntu dirección IPv6 pública. Cada línea de IPv6 de abajo es una cosa más que acertar, y una\nconfiguración IPv6 a medias te deja un servicio que funciona por IPv4 y se queda colgado por\nIPv6.",[1579,1613,1615],{"id":1614},"solo-ipv4","Solo IPv4",[224,1617,1619],{"className":271,"code":1618,"language":273,"meta":229,"style":229},"services:\n  getpublicip:\n    image: ghcr.io\u002Fgetpublicip\u002Fgetpublicip:latest\n    restart: unless-stopped\n    environment:\n      GETPUBLICIP_API_KEY: \"${GETPUBLICIP_API_KEY}\"\n      GETPUBLICIP_MAPPINGS: \"80\u002Ftcp->web:80\"\n      GETPUBLICIP_PRESERVE_CLIENT_IP: \"true\"\n    cap_add:\n      - NET_ADMIN\n    devices:\n      - \u002Fdev\u002Fnet\u002Ftun\n    sysctls:\n      net.ipv4.ip_forward: 1\n      net.ipv4.conf.all.src_valid_mark: 1\n    networks:\n      appnet:\n        ipv4_address: 172.29.7.2      # fixed, because the sidecar routes to it\n\n  web:\n    image: nginx:alpine\n    restart: unless-stopped\n    networks:\n      appnet:\n        ipv4_address: 172.29.7.3      # give every service a fixed address, not just the agent\n\n  # Points web's default route at the agent, from inside web's own network\n  # namespace. Runs once and exits.\n  web-route:\n    image: alpine:3.20\n    network_mode: \"service:web\"\n    cap_add:\n      - NET_ADMIN\n    restart: \"no\"\n    command: sh -c 'ip route replace default via 172.29.7.2'\n    depends_on:\n      web:\n        condition: service_started\n        restart: true               # re-run this sidecar whenever web restarts\n      getpublicip:\n        condition: service_started\n\nnetworks:\n  appnet:\n    driver: bridge\n    ipam:\n      config:\n        - subnet: 172.29.7.0\u002F24\n          gateway: 172.29.7.1\n",[95,1620,1621,1627,1633,1641,1649,1655,1663,1671,1681,1687,1693,1699,1705,1711,1719,1727,1733,1740,1753,1757,1763,1771,1779,1785,1791,1803,1807,1813,1819,1827,1837,1848,1855,1862,1872,1883,1891,1899,1910,1923,1931,1940,1945,1952,1959,1970,1977,1984,1995],{"__ignoreMap":229},[233,1622,1623,1625],{"class":235,"line":236},[233,1624,280],{"class":243},[233,1626,283],{"class":239},[233,1628,1629,1631],{"class":235,"line":286},[233,1630,289],{"class":243},[233,1632,283],{"class":239},[233,1634,1635,1637,1639],{"class":235,"line":294},[233,1636,297],{"class":243},[233,1638,300],{"class":239},[233,1640,303],{"class":247},[233,1642,1643,1645,1647],{"class":235,"line":306},[233,1644,309],{"class":243},[233,1646,300],{"class":239},[233,1648,314],{"class":247},[233,1650,1651,1653],{"class":235,"line":317},[233,1652,320],{"class":243},[233,1654,283],{"class":239},[233,1656,1657,1659,1661],{"class":235,"line":325},[233,1658,328],{"class":243},[233,1660,300],{"class":239},[233,1662,333],{"class":247},[233,1664,1665,1667,1669],{"class":235,"line":336},[233,1666,339],{"class":243},[233,1668,300],{"class":239},[233,1670,566],{"class":247},[233,1672,1673,1676,1678],{"class":235,"line":347},[233,1674,1675],{"class":243},"      GETPUBLICIP_PRESERVE_CLIENT_IP",[233,1677,300],{"class":239},[233,1679,1680],{"class":247},"\"true\"\n",[233,1682,1683,1685],{"class":235,"line":355},[233,1684,350],{"class":243},[233,1686,283],{"class":239},[233,1688,1689,1691],{"class":235,"line":364},[233,1690,358],{"class":239},[233,1692,361],{"class":247},[233,1694,1695,1697],{"class":235,"line":372},[233,1696,367],{"class":243},[233,1698,283],{"class":239},[233,1700,1701,1703],{"class":235,"line":380},[233,1702,358],{"class":239},[233,1704,377],{"class":247},[233,1706,1707,1709],{"class":235,"line":388},[233,1708,383],{"class":243},[233,1710,283],{"class":239},[233,1712,1713,1715,1717],{"class":235,"line":400},[233,1714,391],{"class":243},[233,1716,300],{"class":239},[233,1718,397],{"class":396},[233,1720,1721,1723,1725],{"class":235,"line":410},[233,1722,403],{"class":243},[233,1724,300],{"class":239},[233,1726,397],{"class":396},[233,1728,1729,1731],{"class":235,"line":420},[233,1730,423],{"class":243},[233,1732,283],{"class":239},[233,1734,1735,1738],{"class":235,"line":428},[233,1736,1737],{"class":243},"      appnet",[233,1739,283],{"class":239},[233,1741,1742,1745,1747,1750],{"class":235,"line":593},[233,1743,1744],{"class":243},"        ipv4_address",[233,1746,300],{"class":239},[233,1748,1749],{"class":396},"172.29.7.2",[233,1751,1752],{"class":1240},"      # fixed, because the sidecar routes to it\n",[233,1754,1755],{"class":235,"line":600},[233,1756,521],{"emptyLinePlaceholder":520},[233,1758,1759,1761],{"class":235,"line":609},[233,1760,484],{"class":243},[233,1762,283],{"class":239},[233,1764,1765,1767,1769],{"class":235,"line":618},[233,1766,297],{"class":243},[233,1768,300],{"class":239},[233,1770,495],{"class":247},[233,1772,1773,1775,1777],{"class":235,"line":627},[233,1774,309],{"class":243},[233,1776,300],{"class":239},[233,1778,314],{"class":247},[233,1780,1781,1783],{"class":235,"line":634},[233,1782,423],{"class":243},[233,1784,283],{"class":239},[233,1786,1787,1789],{"class":235,"line":641},[233,1788,1737],{"class":243},[233,1790,283],{"class":239},[233,1792,1793,1795,1797,1800],{"class":235,"line":646},[233,1794,1744],{"class":243},[233,1796,300],{"class":239},[233,1798,1799],{"class":396},"172.29.7.3",[233,1801,1802],{"class":1240},"      # give every service a fixed address, not just the agent\n",[233,1804,1805],{"class":235,"line":654},[233,1806,521],{"emptyLinePlaceholder":520},[233,1808,1810],{"class":235,"line":1809},27,[233,1811,1812],{"class":1240},"  # Points web's default route at the agent, from inside web's own network\n",[233,1814,1816],{"class":235,"line":1815},28,[233,1817,1818],{"class":1240},"  # namespace. Runs once and exits.\n",[233,1820,1822,1825],{"class":235,"line":1821},29,[233,1823,1824],{"class":243},"  web-route",[233,1826,283],{"class":239},[233,1828,1830,1832,1834],{"class":235,"line":1829},30,[233,1831,297],{"class":243},[233,1833,300],{"class":239},[233,1835,1836],{"class":247},"alpine:3.20\n",[233,1838,1840,1843,1845],{"class":235,"line":1839},31,[233,1841,1842],{"class":243},"    network_mode",[233,1844,300],{"class":239},[233,1846,1847],{"class":247},"\"service:web\"\n",[233,1849,1851,1853],{"class":235,"line":1850},32,[233,1852,350],{"class":243},[233,1854,283],{"class":239},[233,1856,1858,1860],{"class":235,"line":1857},33,[233,1859,358],{"class":239},[233,1861,361],{"class":247},[233,1863,1865,1867,1869],{"class":235,"line":1864},34,[233,1866,309],{"class":243},[233,1868,300],{"class":239},[233,1870,1871],{"class":247},"\"no\"\n",[233,1873,1875,1878,1880],{"class":235,"line":1874},35,[233,1876,1877],{"class":243},"    command",[233,1879,300],{"class":239},[233,1881,1882],{"class":247},"sh -c 'ip route replace default via 172.29.7.2'\n",[233,1884,1886,1889],{"class":235,"line":1885},36,[233,1887,1888],{"class":243},"    depends_on",[233,1890,283],{"class":239},[233,1892,1894,1897],{"class":235,"line":1893},37,[233,1895,1896],{"class":243},"      web",[233,1898,283],{"class":239},[233,1900,1902,1905,1907],{"class":235,"line":1901},38,[233,1903,1904],{"class":243},"        condition",[233,1906,300],{"class":239},[233,1908,1909],{"class":247},"service_started\n",[233,1911,1913,1916,1918,1920],{"class":235,"line":1912},39,[233,1914,1915],{"class":243},"        restart",[233,1917,300],{"class":239},[233,1919,1472],{"class":396},[233,1921,1922],{"class":1240},"               # re-run this sidecar whenever web restarts\n",[233,1924,1926,1929],{"class":235,"line":1925},40,[233,1927,1928],{"class":243},"      getpublicip",[233,1930,283],{"class":239},[233,1932,1934,1936,1938],{"class":235,"line":1933},41,[233,1935,1904],{"class":243},[233,1937,300],{"class":239},[233,1939,1909],{"class":247},[233,1941,1943],{"class":235,"line":1942},42,[233,1944,521],{"emptyLinePlaceholder":520},[233,1946,1948,1950],{"class":235,"line":1947},43,[233,1949,649],{"class":243},[233,1951,283],{"class":239},[233,1953,1955,1957],{"class":235,"line":1954},44,[233,1956,657],{"class":243},[233,1958,283],{"class":239},[233,1960,1962,1965,1967],{"class":235,"line":1961},45,[233,1963,1964],{"class":243},"    driver",[233,1966,300],{"class":239},[233,1968,1969],{"class":247},"bridge\n",[233,1971,1973,1975],{"class":235,"line":1972},46,[233,1974,1033],{"class":243},[233,1976,283],{"class":239},[233,1978,1980,1982],{"class":235,"line":1979},47,[233,1981,1040],{"class":243},[233,1983,283],{"class":239},[233,1985,1987,1989,1991,1993],{"class":235,"line":1986},48,[233,1988,1047],{"class":239},[233,1990,1050],{"class":243},[233,1992,300],{"class":239},[233,1994,1055],{"class":247},[233,1996,1998,2001,2003],{"class":235,"line":1997},49,[233,1999,2000],{"class":243},"          gateway",[233,2002,300],{"class":239},[233,2004,2005],{"class":396},"172.29.7.1\n",[1579,2007,2009],{"id":2008},"ipv4-e-ipv6","IPv4 e IPv6",[91,2011,2012,2013,2015,2016,2019,2020,2023],{},"El mismo proyecto con la mitad de IPv6 añadida. Cambian cuatro cosas: la red recibe\n",[95,2014,1000],{}," y una subred IPv6, cada servicio recibe una ",[95,2017,2018],{},"ipv6_address"," fija, el agente\nrecibe el sysctl ",[95,2021,2022],{},"net.ipv6.conf.all.forwarding"," y el sidecar configura una segunda ruta\npredeterminada.",[224,2025,2027],{"className":271,"code":2026,"language":273,"meta":229,"style":229},"services:\n  getpublicip:\n    image: ghcr.io\u002Fgetpublicip\u002Fgetpublicip:latest\n    restart: unless-stopped\n    environment:\n      GETPUBLICIP_API_KEY: \"${GETPUBLICIP_API_KEY}\"\n      GETPUBLICIP_MAPPINGS: \"80\u002Ftcp\u002Fipv4,ipv6->web:80\"\n      GETPUBLICIP_PRESERVE_CLIENT_IP: \"true\"\n    cap_add:\n      - NET_ADMIN\n    devices:\n      - \u002Fdev\u002Fnet\u002Ftun\n    sysctls:\n      net.ipv4.ip_forward: 1\n      net.ipv4.conf.all.src_valid_mark: 1\n      net.ipv6.conf.all.forwarding: 1\n    networks:\n      appnet:\n        ipv4_address: 172.29.7.2      # fixed, because the sidecar routes to it\n        ipv6_address: fd00:c0de:7::2\n\n  web:\n    image: nginx:alpine\n    restart: unless-stopped\n    networks:\n      appnet:\n        ipv4_address: 172.29.7.3      # give every service a fixed address, not just the agent\n        ipv6_address: fd00:c0de:7::3\n\n  # Points web's default routes at the agent, from inside web's own network\n  # namespace. Runs once and exits. Both families need their own route.\n  web-route:\n    image: alpine:3.20\n    network_mode: \"service:web\"\n    cap_add:\n      - NET_ADMIN\n    restart: \"no\"\n    command: >\n      sh -c 'ip route replace default via 172.29.7.2;\n      ip -6 route replace default via fd00:c0de:7::2'\n    depends_on:\n      web:\n        condition: service_started\n        restart: true               # re-run this sidecar whenever web restarts\n      getpublicip:\n        condition: service_started\n\nnetworks:\n  appnet:\n    driver: bridge\n    enable_ipv6: true\n    ipam:\n      config:\n        - subnet: 172.29.7.0\u002F24\n          gateway: 172.29.7.1\n        - subnet: fd00:c0de:7::\u002F64\n          gateway: fd00:c0de:7::1\n",[95,2028,2029,2035,2041,2049,2057,2063,2071,2080,2088,2094,2100,2106,2112,2118,2126,2134,2142,2148,2154,2164,2174,2178,2184,2192,2200,2206,2212,2222,2231,2235,2240,2245,2251,2259,2267,2273,2279,2287,2296,2301,2306,2312,2318,2326,2336,2342,2350,2354,2360,2366,2375,2384,2391,2398,2409,2418,2430],{"__ignoreMap":229},[233,2030,2031,2033],{"class":235,"line":236},[233,2032,280],{"class":243},[233,2034,283],{"class":239},[233,2036,2037,2039],{"class":235,"line":286},[233,2038,289],{"class":243},[233,2040,283],{"class":239},[233,2042,2043,2045,2047],{"class":235,"line":294},[233,2044,297],{"class":243},[233,2046,300],{"class":239},[233,2048,303],{"class":247},[233,2050,2051,2053,2055],{"class":235,"line":306},[233,2052,309],{"class":243},[233,2054,300],{"class":239},[233,2056,314],{"class":247},[233,2058,2059,2061],{"class":235,"line":317},[233,2060,320],{"class":243},[233,2062,283],{"class":239},[233,2064,2065,2067,2069],{"class":235,"line":325},[233,2066,328],{"class":243},[233,2068,300],{"class":239},[233,2070,333],{"class":247},[233,2072,2073,2075,2077],{"class":235,"line":336},[233,2074,339],{"class":243},[233,2076,300],{"class":239},[233,2078,2079],{"class":247},"\"80\u002Ftcp\u002Fipv4,ipv6->web:80\"\n",[233,2081,2082,2084,2086],{"class":235,"line":347},[233,2083,1675],{"class":243},[233,2085,300],{"class":239},[233,2087,1680],{"class":247},[233,2089,2090,2092],{"class":235,"line":355},[233,2091,350],{"class":243},[233,2093,283],{"class":239},[233,2095,2096,2098],{"class":235,"line":364},[233,2097,358],{"class":239},[233,2099,361],{"class":247},[233,2101,2102,2104],{"class":235,"line":372},[233,2103,367],{"class":243},[233,2105,283],{"class":239},[233,2107,2108,2110],{"class":235,"line":380},[233,2109,358],{"class":239},[233,2111,377],{"class":247},[233,2113,2114,2116],{"class":235,"line":388},[233,2115,383],{"class":243},[233,2117,283],{"class":239},[233,2119,2120,2122,2124],{"class":235,"line":400},[233,2121,391],{"class":243},[233,2123,300],{"class":239},[233,2125,397],{"class":396},[233,2127,2128,2130,2132],{"class":235,"line":410},[233,2129,403],{"class":243},[233,2131,300],{"class":239},[233,2133,397],{"class":396},[233,2135,2136,2138,2140],{"class":235,"line":420},[233,2137,413],{"class":243},[233,2139,300],{"class":239},[233,2141,397],{"class":396},[233,2143,2144,2146],{"class":235,"line":428},[233,2145,423],{"class":243},[233,2147,283],{"class":239},[233,2149,2150,2152],{"class":235,"line":593},[233,2151,1737],{"class":243},[233,2153,283],{"class":239},[233,2155,2156,2158,2160,2162],{"class":235,"line":600},[233,2157,1744],{"class":243},[233,2159,300],{"class":239},[233,2161,1749],{"class":396},[233,2163,1752],{"class":1240},[233,2165,2166,2169,2171],{"class":235,"line":609},[233,2167,2168],{"class":243},"        ipv6_address",[233,2170,300],{"class":239},[233,2172,2173],{"class":247},"fd00:c0de:7::2\n",[233,2175,2176],{"class":235,"line":618},[233,2177,521],{"emptyLinePlaceholder":520},[233,2179,2180,2182],{"class":235,"line":627},[233,2181,484],{"class":243},[233,2183,283],{"class":239},[233,2185,2186,2188,2190],{"class":235,"line":634},[233,2187,297],{"class":243},[233,2189,300],{"class":239},[233,2191,495],{"class":247},[233,2193,2194,2196,2198],{"class":235,"line":641},[233,2195,309],{"class":243},[233,2197,300],{"class":239},[233,2199,314],{"class":247},[233,2201,2202,2204],{"class":235,"line":646},[233,2203,423],{"class":243},[233,2205,283],{"class":239},[233,2207,2208,2210],{"class":235,"line":654},[233,2209,1737],{"class":243},[233,2211,283],{"class":239},[233,2213,2214,2216,2218,2220],{"class":235,"line":1809},[233,2215,1744],{"class":243},[233,2217,300],{"class":239},[233,2219,1799],{"class":396},[233,2221,1802],{"class":1240},[233,2223,2224,2226,2228],{"class":235,"line":1815},[233,2225,2168],{"class":243},[233,2227,300],{"class":239},[233,2229,2230],{"class":247},"fd00:c0de:7::3\n",[233,2232,2233],{"class":235,"line":1821},[233,2234,521],{"emptyLinePlaceholder":520},[233,2236,2237],{"class":235,"line":1829},[233,2238,2239],{"class":1240},"  # Points web's default routes at the agent, from inside web's own network\n",[233,2241,2242],{"class":235,"line":1839},[233,2243,2244],{"class":1240},"  # namespace. Runs once and exits. Both families need their own route.\n",[233,2246,2247,2249],{"class":235,"line":1850},[233,2248,1824],{"class":243},[233,2250,283],{"class":239},[233,2252,2253,2255,2257],{"class":235,"line":1857},[233,2254,297],{"class":243},[233,2256,300],{"class":239},[233,2258,1836],{"class":247},[233,2260,2261,2263,2265],{"class":235,"line":1864},[233,2262,1842],{"class":243},[233,2264,300],{"class":239},[233,2266,1847],{"class":247},[233,2268,2269,2271],{"class":235,"line":1874},[233,2270,350],{"class":243},[233,2272,283],{"class":239},[233,2274,2275,2277],{"class":235,"line":1885},[233,2276,358],{"class":239},[233,2278,361],{"class":247},[233,2280,2281,2283,2285],{"class":235,"line":1893},[233,2282,309],{"class":243},[233,2284,300],{"class":239},[233,2286,1871],{"class":247},[233,2288,2289,2291,2293],{"class":235,"line":1901},[233,2290,1877],{"class":243},[233,2292,300],{"class":239},[233,2294,2295],{"class":243},">\n",[233,2297,2298],{"class":235,"line":1912},[233,2299,2300],{"class":247},"      sh -c 'ip route replace default via 172.29.7.2;\n",[233,2302,2303],{"class":235,"line":1925},[233,2304,2305],{"class":247},"      ip -6 route replace default via fd00:c0de:7::2'\n",[233,2307,2308,2310],{"class":235,"line":1933},[233,2309,1888],{"class":243},[233,2311,283],{"class":239},[233,2313,2314,2316],{"class":235,"line":1942},[233,2315,1896],{"class":243},[233,2317,283],{"class":239},[233,2319,2320,2322,2324],{"class":235,"line":1947},[233,2321,1904],{"class":243},[233,2323,300],{"class":239},[233,2325,1909],{"class":247},[233,2327,2328,2330,2332,2334],{"class":235,"line":1954},[233,2329,1915],{"class":243},[233,2331,300],{"class":239},[233,2333,1472],{"class":396},[233,2335,1922],{"class":1240},[233,2337,2338,2340],{"class":235,"line":1961},[233,2339,1928],{"class":243},[233,2341,283],{"class":239},[233,2343,2344,2346,2348],{"class":235,"line":1972},[233,2345,1904],{"class":243},[233,2347,300],{"class":239},[233,2349,1909],{"class":247},[233,2351,2352],{"class":235,"line":1979},[233,2353,521],{"emptyLinePlaceholder":520},[233,2355,2356,2358],{"class":235,"line":1986},[233,2357,649],{"class":243},[233,2359,283],{"class":239},[233,2361,2362,2364],{"class":235,"line":1997},[233,2363,657],{"class":243},[233,2365,283],{"class":239},[233,2367,2369,2371,2373],{"class":235,"line":2368},50,[233,2370,1964],{"class":243},[233,2372,300],{"class":239},[233,2374,1969],{"class":247},[233,2376,2378,2380,2382],{"class":235,"line":2377},51,[233,2379,1023],{"class":243},[233,2381,300],{"class":239},[233,2383,1028],{"class":396},[233,2385,2387,2389],{"class":235,"line":2386},52,[233,2388,1033],{"class":243},[233,2390,283],{"class":239},[233,2392,2394,2396],{"class":235,"line":2393},53,[233,2395,1040],{"class":243},[233,2397,283],{"class":239},[233,2399,2401,2403,2405,2407],{"class":235,"line":2400},54,[233,2402,1047],{"class":239},[233,2404,1050],{"class":243},[233,2406,300],{"class":239},[233,2408,1055],{"class":247},[233,2410,2412,2414,2416],{"class":235,"line":2411},55,[233,2413,2000],{"class":243},[233,2415,300],{"class":239},[233,2417,2005],{"class":396},[233,2419,2421,2423,2425,2427],{"class":235,"line":2420},56,[233,2422,1047],{"class":239},[233,2424,1050],{"class":243},[233,2426,300],{"class":239},[233,2428,2429],{"class":247},"fd00:c0de:7::\u002F64\n",[233,2431,2433,2435,2437],{"class":235,"line":2432},57,[233,2434,2000],{"class":243},[233,2436,300],{"class":239},[233,2438,2439],{"class":247},"fd00:c0de:7::1\n",[91,2441,2442],{},"Sea cual sea la versión de la que partas, repite el sidecar para cada servicio al que reenvíes y\ncomprueba los cuatro puntos siguientes. Si falla cualquiera de ellos, el servicio se queda\ncolgado sin mostrar ningún error.",[91,2444,2445,2448,2449,2452,2453,207],{},[115,2446,2447],{},"Da una dirección fija a cada servicio de la red, no solo al agente."," Un servicio sin\ndirección fija toma la dirección libre más baja, que es la que reservaste para el agente, y por\n",[95,2450,2451],{},"depends_on"," a menudo arranca primero y se la queda. Entonces el agente ni siquiera llega a\narrancar y muestra ",[95,2454,2455],{},"Address already in use",[91,2457,2458,2461,2462,2465],{},[115,2459,2460],{},"Si rediriges IPv6, configura las dos rutas."," La ruta predeterminada de IPv6 es independiente\nde la de IPv4, así que un sidecar que solo configura la ruta IPv4 deja que las respuestas IPv6\nsalgan por el bridge, y esas conexiones se quedan colgadas mientras IPv4 funciona. La segunda\nlínea ",[95,2463,2464],{},"ip -6 route replace"," del ejemplo de doble pila configura esa ruta. Olvidarla es el fallo\nmás habitual de esa versión, porque todo lo que pruebas por IPv4 funciona.",[91,2467,2468,2471,2472,2474,2475,2478,2479,2481,2482,2485,2486,2489],{},[115,2469,2470],{},"La ruta no sobrevive a un reinicio de tu servicio."," Docker crea un espacio de nombres de red\nnuevo con una tabla de rutas limpia, así que la ruta desaparece y el tráfico entrante se detiene\nhasta que el sidecar vuelve a ejecutarse. El ",[95,2473,2451],{}," de arriba se encarga de esto:\n",[95,2476,2477],{},"restart: true"," le indica a Compose que vuelva a ejecutar el sidecar cada vez que ",[95,2480,443],{}," se\nreinicie, de modo que tanto ",[95,2483,2484],{},"docker compose restart web"," como ",[95,2487,2488],{},"docker compose up -d"," reparan la\nruta por sí solos.",[91,2491,2492,2493,2495,2496,2499],{},"No cubre el caso en que Docker reinicia tu servicio por su cuenta. Si ",[95,2494,443],{}," se cae, o lo mata el\nout-of-memory killer, su propia política ",[95,2497,2498],{},"restart:"," lo vuelve a levantar sin que intervenga\nCompose, y nada vuelve a ejecutar el sidecar. Falta la ruta, el tráfico entrante se detiene y\nnada avisa de un problema. Restablécela con:",[224,2501,2503],{"className":226,"code":2502,"language":228,"meta":229,"style":229},"docker compose up -d web-route\n",[95,2504,2505],{"__ignoreMap":229},[233,2506,2507,2509,2511,2513,2516],{"class":235,"line":236},[233,2508,89],{"class":672},[233,2510,675],{"class":247},[233,2512,678],{"class":247},[233,2514,2515],{"class":396}," -d",[233,2517,2518],{"class":247}," web-route\n",[91,2520,2521,2522,2525],{},"Recomendamos añadir la ruta predeterminada en el Dockerfile del servicio para que sobreviva a\nestos reinicios. Si no, comprueba las rutas con ",[95,2523,2524],{},"docker exec web ip route"," y vuelve a configurar\nla ruta predeterminada cada vez que haya desaparecido.",[91,2527,2528,2531,2532,2537],{},[115,2529,2530],{},"Los destinos en el host no pueden funcionar en este modo."," Reenviar a\n",[120,2533,2536],{"className":2534,"href":2535},[123],"#redirigir-a-un-servicio-del-host","un servicio del host de Docker","\nrequiere también que la respuesta vuelva a través del agente, y eso implicaría cambiar la ruta\npredeterminada del propio host.",[458,2539,2541],{"id":2540},"comprueba-que-funciona","Comprueba que funciona",[91,2543,2544],{},"Haz una solicitud a tu dirección IP:",[224,2546,2548],{"className":226,"code":2547,"language":228,"meta":229,"style":229},"curl http:\u002F\u002F{YOUR IP ADDRESS}              # one request through your public IP\ndocker compose logs --tail 10 web           # what your container recorded\n",[95,2549,2550,2564],{"__ignoreMap":229},[233,2551,2552,2554,2556,2558,2561],{"class":235,"line":236},[233,2553,1497],{"class":672},[233,2555,1500],{"class":247},[233,2557,1503],{"class":247},[233,2559,2560],{"class":247}," ADDRESS}",[233,2562,2563],{"class":1240},"              # one request through your public IP\n",[233,2565,2566,2568,2570,2572,2575,2578,2581],{"class":235,"line":286},[233,2567,89],{"class":672},[233,2569,675],{"class":247},[233,2571,1436],{"class":247},[233,2573,2574],{"class":396}," --tail",[233,2576,2577],{"class":396}," 10",[233,2579,2580],{"class":247}," web",[233,2582,2583],{"class":1240},"           # what your container recorded\n",[91,2585,2586,2587,2589],{},"El log debería mostrar la dirección IP real del cliente. Si muestra ",[95,2588,1749],{},", la\npreservación de la IP del cliente no está activada y estás viendo el comportamiento\npredeterminado.",[91,2591,2592],{},"Hacer la prueba desde el propio host de Docker no es problema. La solicitud sigue saliendo hacia\ntu IP pública, llega a nuestra red y vuelve por el túnel, así que tu contenedor registra la\ndirección pública de tu conexión a internet, fácil de distinguir de la dirección del bridge que\nhabría puesto la reescritura.",[91,2594,2595,2596,2599],{},"Si rediriges IPv6, compruébalo por separado con ",[95,2597,2598],{},"curl -6",". Las dos familias tienen rutas\npredeterminadas distintas, así que una puede funcionar mientras la otra está rota.",[458,2601,2603],{"id":2602},"cuando-no-funciona","Cuando no funciona",[91,2605,2606,2607,2609,2610,2613],{},"Una ruta predeterminada mal configurada no produce ningún error. Las conexiones se quedan\ncolgadas, el túnel sigue activo y sigue registrando ",[95,2608,1464],{},", las reglas de reenvío siguen\nsiendo correctas y nada en ",[95,2611,2612],{},"docker compose logs getpublicip"," informa de un problema, porque desde\nel punto de vista del agente no lo hay. Las respuestas de tu contenedor salen por el camino\nequivocado en lugar de a través de tu dirección IP pública.",[91,2615,2616],{},"Revisa la tabla de rutas dentro del servicio:",[224,2618,2620],{"className":226,"code":2619,"language":228,"meta":229,"style":229},"docker exec web ip route      # default must be via the agent's address\ndocker exec web ip -6 route   # and this one too, if you forward IPv6\n",[95,2621,2622,2640],{"__ignoreMap":229},[233,2623,2624,2626,2629,2631,2634,2637],{"class":235,"line":236},[233,2625,89],{"class":672},[233,2627,2628],{"class":247}," exec",[233,2630,2580],{"class":247},[233,2632,2633],{"class":247}," ip",[233,2635,2636],{"class":247}," route",[233,2638,2639],{"class":1240},"      # default must be via the agent's address\n",[233,2641,2642,2644,2646,2648,2650,2653,2655],{"class":235,"line":286},[233,2643,89],{"class":672},[233,2645,2628],{"class":247},[233,2647,2580],{"class":247},[233,2649,2633],{"class":247},[233,2651,2652],{"class":396}," -6",[233,2654,2636],{"class":247},[233,2656,2657],{"class":1240},"   # and this one too, if you forward IPv6\n",[103,2659,2661],{"id":2660},"enviar-el-tráfico-saliente-por-tu-ip","Enviar el tráfico saliente por tu IP",[91,2663,2664,2665,2668],{},"Las secciones anteriores tratan del tráfico entrante. ",[95,2666,2667],{},"GETPUBLICIP_OUTBOUND"," cubre la otra\ndirección: tus contenedores salen a internet desde tu IP pública en lugar de desde la dirección\nde tu operador. Es útil cuando algo a lo que te conectas solo permite una dirección conocida, o\ncuando quieres que tu tráfico saliente venga de la misma dirección que el entrante.",[91,2670,2671],{},"Necesita el mismo cambio de ruta predeterminada que la preservación de la IP del cliente, por el\nmismo motivo: la respuesta tiene que volver a través del agente. Si ya configuraste el sidecar\npara eso, solo tienes que añadir el ajuste.",[224,2673,2675],{"className":271,"code":2674,"language":273,"meta":229,"style":229},"services:\n  getpublicip:\n    image: ghcr.io\u002Fgetpublicip\u002Fgetpublicip:latest\n    restart: unless-stopped\n    environment:\n      GETPUBLICIP_API_KEY: \"${GETPUBLICIP_API_KEY}\"\n      GETPUBLICIP_MAPPINGS: \"80\u002Ftcp->web:80\"\n      GETPUBLICIP_OUTBOUND: \"true\"\n    cap_add:\n      - NET_ADMIN\n    devices:\n      - \u002Fdev\u002Fnet\u002Ftun\n    sysctls:\n      net.ipv4.ip_forward: 1\n      net.ipv4.conf.all.src_valid_mark: 1\n      net.ipv6.conf.all.forwarding: 1\n    networks:\n      appnet:\n        ipv4_address: 172.29.7.2\n",[95,2676,2677,2683,2689,2697,2705,2711,2719,2727,2736,2742,2748,2754,2760,2766,2774,2782,2790,2796,2802],{"__ignoreMap":229},[233,2678,2679,2681],{"class":235,"line":236},[233,2680,280],{"class":243},[233,2682,283],{"class":239},[233,2684,2685,2687],{"class":235,"line":286},[233,2686,289],{"class":243},[233,2688,283],{"class":239},[233,2690,2691,2693,2695],{"class":235,"line":294},[233,2692,297],{"class":243},[233,2694,300],{"class":239},[233,2696,303],{"class":247},[233,2698,2699,2701,2703],{"class":235,"line":306},[233,2700,309],{"class":243},[233,2702,300],{"class":239},[233,2704,314],{"class":247},[233,2706,2707,2709],{"class":235,"line":317},[233,2708,320],{"class":243},[233,2710,283],{"class":239},[233,2712,2713,2715,2717],{"class":235,"line":325},[233,2714,328],{"class":243},[233,2716,300],{"class":239},[233,2718,333],{"class":247},[233,2720,2721,2723,2725],{"class":235,"line":336},[233,2722,339],{"class":243},[233,2724,300],{"class":239},[233,2726,566],{"class":247},[233,2728,2729,2732,2734],{"class":235,"line":347},[233,2730,2731],{"class":243},"      GETPUBLICIP_OUTBOUND",[233,2733,300],{"class":239},[233,2735,1680],{"class":247},[233,2737,2738,2740],{"class":235,"line":355},[233,2739,350],{"class":243},[233,2741,283],{"class":239},[233,2743,2744,2746],{"class":235,"line":364},[233,2745,358],{"class":239},[233,2747,361],{"class":247},[233,2749,2750,2752],{"class":235,"line":372},[233,2751,367],{"class":243},[233,2753,283],{"class":239},[233,2755,2756,2758],{"class":235,"line":380},[233,2757,358],{"class":239},[233,2759,377],{"class":247},[233,2761,2762,2764],{"class":235,"line":388},[233,2763,383],{"class":243},[233,2765,283],{"class":239},[233,2767,2768,2770,2772],{"class":235,"line":400},[233,2769,391],{"class":243},[233,2771,300],{"class":239},[233,2773,397],{"class":396},[233,2775,2776,2778,2780],{"class":235,"line":410},[233,2777,403],{"class":243},[233,2779,300],{"class":239},[233,2781,397],{"class":396},[233,2783,2784,2786,2788],{"class":235,"line":420},[233,2785,413],{"class":243},[233,2787,300],{"class":239},[233,2789,397],{"class":396},[233,2791,2792,2794],{"class":235,"line":428},[233,2793,423],{"class":243},[233,2795,283],{"class":239},[233,2797,2798,2800],{"class":235,"line":593},[233,2799,1737],{"class":243},[233,2801,283],{"class":239},[233,2803,2804,2806,2808],{"class":235,"line":600},[233,2805,1744],{"class":243},[233,2807,300],{"class":239},[233,2809,2810],{"class":396},"172.29.7.2\n",[91,2812,2813,2814,2818],{},"Después, apunta al agente cada contenedor que deba usarlo, exactamente igual que en el\n",[120,2815,1608],{"className":2816,"href":2817},[123],"#proyecto-de-ejemplo"," de arriba. Un contenedor\ncuya ruta no toques sigue usando el bridge normal de Docker, así que puedes pasar los servicios\nde uno en uno.",[91,2820,2821],{},"Compruébalo desde dentro de un contenedor que hayas enrutado:",[224,2823,2825],{"className":226,"code":2824,"language":228,"meta":229,"style":229},"docker exec web curl -s https:\u002F\u002Fapi.getpublicip.com\u002Fip\n",[95,2826,2827],{"__ignoreMap":229},[233,2828,2829,2831,2833,2835,2838,2841],{"class":235,"line":236},[233,2830,89],{"class":672},[233,2832,2628],{"class":247},[233,2834,2580],{"class":247},[233,2836,2837],{"class":247}," curl",[233,2839,2840],{"class":396}," -s",[233,2842,2843],{"class":247}," https:\u002F\u002Fapi.getpublicip.com\u002Fip\n",[91,2845,2846],{},"Debería mostrar tu dirección de GetPublicIP, no la de tu casa ni la de tu oficina.",[458,2848,2850],{"id":2849},"solo-tráfico-saliente-sin-puertos-redirigidos","Solo tráfico saliente, sin puertos redirigidos",[91,2852,2853,2854,2856],{},"Si lo único que quieres es la dirección saliente, ",[95,2855,715],{}," pasa a ser\nopcional:",[224,2858,2860],{"className":271,"code":2859,"language":273,"meta":229,"style":229},"    environment:\n      GETPUBLICIP_API_KEY: \"${GETPUBLICIP_API_KEY}\"\n      GETPUBLICIP_OUTBOUND: \"true\"\n",[95,2861,2862,2868,2876],{"__ignoreMap":229},[233,2863,2864,2866],{"class":235,"line":236},[233,2865,320],{"class":243},[233,2867,283],{"class":239},[233,2869,2870,2872,2874],{"class":235,"line":286},[233,2871,328],{"class":243},[233,2873,300],{"class":239},[233,2875,333],{"class":247},[233,2877,2878,2880,2882],{"class":235,"line":294},[233,2879,2731],{"class":243},[233,2881,300],{"class":239},[233,2883,1680],{"class":247},[91,2885,2886],{},"Un agente iniciado así deja las redirecciones de puertos de tu dirección IP como están, incluidas\nlas que hayas configurado en el panel.",[458,2888,2890],{"id":2889},"lo-que-debes-saber-antes-de-activarlo","Lo que debes saber antes de activarlo",[91,2892,2893,2896],{},[115,2894,2895],{},"Tus contenedores comparten una dirección."," Todo lo que hay detrás del agente sale desde la\nmisma dirección IPv4 pública y la misma IPv6 pública, así que el otro extremo no puede distinguir\nun contenedor de otro.",[91,2898,2899,2902],{},[115,2900,2901],{},"Falla en modo cerrado."," Un contenedor enrutado a través del agente no tiene internet en\nabsoluto mientras el túnel esté caído, cuando antes habría usado tu conexión normal. Es\nintencionado, para que tu tráfico nunca vuelva a salir desde la dirección de tu operador sin que\nlo sepas, pero piénsalo antes de enrutar a través del agente algo de lo que dependes.",[91,2904,2905,2908],{},[115,2906,2907],{},"Si un contenedor no puede salir a internet",", el problema casi siempre está en su ruta y no en\nel agente. Compruébalo dentro del propio contenedor:",[224,2910,2912],{"className":226,"code":2911,"language":228,"meta":229,"style":229},"docker exec web ip route      # default must be via the agent's address\ndocker exec web ip -6 route   # and this one too, if you use IPv6\n",[95,2913,2914,2928],{"__ignoreMap":229},[233,2915,2916,2918,2920,2922,2924,2926],{"class":235,"line":236},[233,2917,89],{"class":672},[233,2919,2628],{"class":247},[233,2921,2580],{"class":247},[233,2923,2633],{"class":247},[233,2925,2636],{"class":247},[233,2927,2639],{"class":1240},[233,2929,2930,2932,2934,2936,2938,2940,2942],{"class":235,"line":286},[233,2931,89],{"class":672},[233,2933,2628],{"class":247},[233,2935,2580],{"class":247},[233,2937,2633],{"class":247},[233,2939,2652],{"class":396},[233,2941,2636],{"class":247},[233,2943,2944],{"class":1240},"   # and this one too, if you use IPv6\n",[103,2946,2948],{"id":2947},"permisos-del-contenedor","Permisos del contenedor",[730,2950,2951,2961],{},[733,2952,2953],{},[736,2954,2955,2958],{},[739,2956,2957],{},"Ajuste",[739,2959,2960],{},"Por qué hace falta",[749,2962,2963,2973,2983,2993,3006],{},[736,2964,2965,2970],{},[754,2966,2967],{},[95,2968,2969],{},"cap_add: NET_ADMIN",[754,2971,2972],{},"Configurar la interfaz WireGuard y las reglas de reenvío",[736,2974,2975,2980],{},[754,2976,2977],{},[95,2978,2979],{},"devices: \u002Fdev\u002Fnet\u002Ftun",[754,2981,2982],{},"El propio dispositivo del túnel",[736,2984,2985,2990],{},[754,2986,2987],{},[95,2988,2989],{},"net.ipv4.ip_forward=1",[754,2991,2992],{},"Reenviar el tráfico del túnel a tu contenedor de destino",[736,2994,2995,3000],{},[754,2996,2997],{},[95,2998,2999],{},"net.ipv4.conf.all.src_valid_mark=1",[754,3001,3002,3003],{},"Lo requiere la configuración de rutas de ",[95,3004,3005],{},"wg-quick",[736,3007,3008,3013],{},[754,3009,3010],{},[95,3011,3012],{},"net.ipv6.conf.all.forwarding=1",[754,3014,3015],{},"Solo hace falta si rediriges IPv6",[103,3017,39],{"id":3018},"macos",[91,3020,3021,3022,3025],{},"Usa ",[120,3023,154],{"className":3024,"href":152,"target":153},[123],"\ny el archivo de Compose de arriba funciona sin cambios, tanto en Intel como en Apple Silicon.",[91,3027,3028],{},"Otros entornos de Docker para macOS (Colima, OrbStack, Rancher Desktop) usan kernels distintos y\nno se han verificado, así que no podemos decir si el túnel se levanta en ellos.",[103,3030,43],{"id":3031},"windows",[91,3033,3034,3035,207],{},"El archivo de Compose de arriba no necesita cambios en Windows con ",[120,3036,154],{"className":3037,"href":152,"target":153},[123],[91,3039,3040],{},"Docker Desktop necesita Windows 10 u 11 de 64 bits, en una versión que Microsoft siga\nadmitiendo, y el backend WSL 2, que es el predeterminado. Después, hay dos cosas que comprobar\nantes de empezar.",[91,3042,3043,3046],{},[115,3044,3045],{},"1. Docker Desktop tiene que estar en modo de contenedores Linux."," El motor de contenedores\nWindows no puede ejecutar esta imagen y, de todos modos, no está disponible con el backend\nWSL 2.",[91,3048,3049,3052,3053,3056],{},[115,3050,3051],{},"2. Tu kernel de WSL2 tiene que ser 6.6.x."," A los kernels anteriores, entre ellos el 5.15,\nles falta un módulo de netfilter que el túnel necesita, y no hay forma de solucionarlo desde\ndentro del contenedor. El túnel no llega a levantarse y muestra\n",[95,3054,3055],{},"unknown option '--save-mark'",". Compruébalo y actualiza desde PowerShell:",[224,3058,3062],{"className":3059,"code":3060,"language":3061,"meta":229,"style":229},"language-powershell shiki shiki-themes monokai","wsl --version    # need \"Kernel version: 6.6.x\"\nwsl --update     # if it reports anything older\n","powershell",[95,3063,3064,3069],{"__ignoreMap":229},[233,3065,3066],{"class":235,"line":236},[233,3067,3068],{},"wsl --version    # need \"Kernel version: 6.6.x\"\n",[233,3070,3071],{"class":235,"line":286},[233,3072,3073],{},"wsl --update     # if it reports anything older\n",[91,3075,3076],{},"La 6.6 no se consolidó como versión predeterminada hasta, aproximadamente, WSL 2.4 a 2.7, así que un\nequipo que lleve tiempo sin actualizarse puede seguir en la 5.15. El mismo requisito se aplica\nsi ejecutas Docker CE dentro de una distribución de WSL2 en lugar de Docker Desktop, porque\ncomparte el mismo kernel.",[91,3078,3079,3080,3083],{},"En la 6.6, ",[95,3081,3082],{},"tun"," es un módulo y no viene integrado en el kernel, así que comprueba que el nodo\nde dispositivo existe antes de buscar el problema en el agente. Este comando falla al crear el\ncontenedor si falta:",[224,3085,3087],{"className":3059,"code":3086,"language":3061,"meta":229,"style":229},"docker run --rm --device \u002Fdev\u002Fnet\u002Ftun alpine ls -l \u002Fdev\u002Fnet\u002Ftun\n",[95,3088,3089],{"__ignoreMap":229},[233,3090,3091],{"class":235,"line":236},[233,3092,3086],{},[91,3094,3095],{},"No hace falta ninguna regla del Firewall de Windows ni reenviar ningún puerto. El tráfico\nentrante llega por el túnel, así que ni el Firewall de Windows ni el NAT de WSL están en el\ncamino.",[103,3097,3099],{"id":3098},"portátiles-y-suspensión","Portátiles y suspensión",[91,3101,3102,3105],{},[115,3103,3104],{},"La suspensión corta el túnel."," En macOS y Windows, la máquina virtual Linux se suspende\ncuando lo hace tu equipo, y tu IP pública deja de ser accesible hasta que se reactiva; en ese\nmomento el túnel se restablece automáticamente. Pruébalo en tu portátil si quieres, pero\nejecútalo en un servidor: una máquina que se suspende es un mal host para una IP pública que\ntiene que estar siempre disponible.",[103,3107,3109],{"id":3108},"una-clave-api-un-túnel","Una clave API, un túnel",[3111,3112,3113],"blockquote",{},[91,3114,3115],{},"Una clave de WireGuard pertenece a un único extremo. Si dos contenedores se ejecutan con la\nmisma clave API, se desconectarán el uno al otro. Gana el que haya hecho el handshake más\nreciente, y el otro descarta tráfico sin avisar hasta su siguiente keepalive. Parece una\ninestabilidad aleatoria en lugar de un error claro. La causa habitual es probar en un portátil\nmientras un servidor ya está conectado con la misma clave.",[91,3117,3118],{},"Este caso se diagnostica solo: los dos contenedores se reinician una y otra vez, porque cada uno\nconcluye que el averiado es él. Un contenedor que se reinicia en bucle en una máquina cuya\nconexión a internet funciona bien casi siempre significa que un segundo agente está usando la\nmisma clave.",[91,3120,3121],{},"Usa una clave API por cada túnel en funcionamiento.",[103,3123,3125],{"id":3124},"solución-de-problemas","Solución de problemas",[91,3127,3128,3131],{},[95,3129,3130],{},"docker compose logs -f getpublicip"," es el punto de partida.",[730,3133,3134,3144],{},[733,3135,3136],{},[736,3137,3138,3141],{},[739,3139,3140],{},"Lo que ves",[739,3142,3143],{},"Qué significa",[749,3145,3146,3158,3168,3177,3194,3210,3220,3228,3242,3254,3264,3273,3295,3305,3318,3336,3356,3369,3379,3397],{},[736,3147,3148,3153],{},[754,3149,3150],{},[95,3151,3152],{},"GETPUBLICIP_API_KEY is required",[754,3154,3155,3156],{},"La variable no está definida, o no se está leyendo tu archivo ",[95,3157,217],{},[736,3159,3160,3165],{},[754,3161,3162],{},[95,3163,3164],{},"tunnel up: … 401",[754,3166,3167],{},"La clave API no es válida",[736,3169,3170,3174],{},[754,3171,3172],{},[95,3173,1407],{},[754,3175,3176],{},"El destino todavía no está en marcha, el nombre del servicio es incorrecto o el agente no comparte ninguna red con él",[736,3178,3179,3185],{},[754,3180,3181,3182,3184],{},"Errores de ",[95,3183,3005],{}," o de permisos",[754,3186,3187,3188,784,3191],{},"Falta ",[95,3189,3190],{},"NET_ADMIN",[95,3192,3193],{},"\u002Fdev\u002Fnet\u002Ftun",[736,3195,3196,3201],{},[754,3197,3198],{},[95,3199,3200],{},"iptables-restore … unknown option '--save-mark'",[754,3202,3203,3204,3206,3207],{},"Solo en Windows: un kernel de WSL2 anterior a 6.6. Ejecuta ",[95,3205,179],{},". Consulta ",[120,3208,43],{"className":3209,"href":192},[123],[736,3211,3212,3217],{},[754,3213,3214],{},[95,3215,3216],{},"error gathering device information … \u002Fdev\u002Fnet\u002Ftun",[754,3218,3219],{},"El nodo de dispositivo no existe en el host. En Docker Desktop, comprueba la versión de tu kernel de WSL2",[736,3221,3222,3225],{},[754,3223,3224],{},"El tráfico llega, pero las respuestas se quedan colgadas",[754,3226,3227],{},"Los sysctls de reenvío no están configurados",[736,3229,3230,3233],{},[754,3231,3232],{},"Se rechaza una redirección al host",[754,3234,3235,3236,3238,3239,3241],{},"El servicio del host está vinculado a ",[95,3237,1255],{}," en lugar de a ",[95,3240,1251],{},", o un firewall del host está descartando la subred del bridge",[736,3243,3244,3248],{},[754,3245,3246],{},[95,3247,1521],{},[754,3249,3250,3251],{},"Se ha caído la conexión. El agente ya se está ocupando de ello. Consulta ",[120,3252,456],{"className":3253,"href":455},[123],[736,3255,3256,3261],{},[754,3257,3258],{},[95,3259,3260],{},"tunnel health cannot be determined",[754,3262,3263],{},"Esta vez el agente no pudo leer el estado del túnel, lo cual no significa que el túnel esté caído. Se le da más tiempo para resolverse solo antes de reiniciar el contenedor",[736,3265,3266,3270],{},[754,3267,3268],{},[95,3269,1525],{},[754,3271,3272],{},"Recuperación normal, no un error. El contenedor vuelve con una conexión nueva. Si se repite durante mucho tiempo, o la máquina no tiene internet o dos agentes comparten una misma clave API",[736,3274,3275,3281],{},[754,3276,3277,3278,3280],{},"Nada en el log parece incorrecto, pero el tráfico entrante se queda colgado y ",[95,3279,1550],{}," está activado",[754,3282,3283,3284,3287,3288,3291,3292],{},"El destino no envía sus respuestas de vuelta a través del agente. Ejecuta ",[95,3285,3286],{},"docker exec \u003Ctarget> ip route",": la ruta predeterminada tiene que apuntar al agente, y también ",[95,3289,3290],{},"ip -6 route"," si rediriges IPv6. Consulta ",[120,3293,1283],{"className":3294,"href":1282},[123],[736,3296,3297,3302],{},[754,3298,3299],{},[95,3300,3301],{},"these destinations cannot work while preserving client IPs",[754,3303,3304],{},"Hay un destino en el host redirigido mientras la preservación de la IP del cliente está activada, y eso no puede funcionar. Pasa esas redirecciones a un segundo agente que deje el ajuste desactivado",[736,3306,3307,3311],{},[754,3308,3309],{},[95,3310,966],{},[754,3312,3313,3314],{},"Una redirección de rango apunta a puertos distintos en el destino, o hay un rango en un lado y un solo puerto en el otro. Omite el puerto interno o repite el mismo rango. Consulta ",[120,3315,937],{"className":3316,"href":3317},[123],"#rangos-de-puertos",[736,3319,3320,3324],{},[754,3321,3322],{},[95,3323,1095],{},[754,3325,3326,3327,3329,3330,3206,3332],{},"Una redirección ",[95,3328,807],{}," que apunta a un servicio sin dirección IPv6, normalmente una red de Compose sin ",[95,3331,1000],{},[120,3333,981],{"className":3334,"href":3335},[123],"#redirigir-ipv6",[736,3337,3338,3343],{},[754,3339,3340,3341,3280],{},"Un contenedor que enrutaste a través del agente no tiene internet y ",[95,3342,2667],{},[754,3344,3345,3346,3348,3349,3351,3352],{},"O el túnel está caído (este modo falla en modo cerrado a propósito) o la ruta predeterminada del contenedor no apunta al agente. Ejecuta ",[95,3347,3286],{},", y también ",[95,3350,3290],{}," si usas IPv6. Consulta ",[120,3353,2661],{"className":3354,"href":3355},[123],"#enviar-el-tráfico-saliente-por-tu-ip",[736,3357,3358,3363],{},[754,3359,3360],{},[95,3361,3362],{},"GETPUBLICIP_MAPPINGS is required (or set GETPUBLICIP_OUTBOUND=true for egress with no inbound ports)",[754,3364,3365,3366],{},"Iniciaste el agente sin redirecciones de puertos. Eso solo se permite en una configuración solo de salida, que necesita ",[95,3367,3368],{},"GETPUBLICIP_OUTBOUND=true",[736,3370,3371,3376],{},[754,3372,3373],{},[95,3374,3375],{},"skipping API push: no mappings configured (egress-only)",[754,3377,3378],{},"No es un error. Un agente solo de salida deja intactas las redirecciones de puertos de tu dirección IP en lugar de borrarlas",[736,3380,3381,3386],{},[754,3382,3383],{},[95,3384,3385],{},"preserveClientIp and masqueradeOutbound are mutually exclusive",[754,3387,3388,3389,188,3391,3394,3395],{},"Se activaron a la vez ",[95,3390,1550],{},[95,3392,3393],{},"GETPUBLICIP_MASQUERADE",". Quita ",[95,3396,3393],{},[736,3398,3399,3404],{},[754,3400,3401],{},[95,3402,3403],{},"is not a boolean (use true or false)",[754,3405,3406,3407,3409,3410,784,3412,1465,3415,188,3418,3421],{},"Un ajuste como ",[95,3408,1550],{}," recibió un valor distinto de ",[95,3411,1472],{},[95,3413,3414],{},"false",[95,3416,3417],{},"yes",[95,3419,3420],{},"on"," se rechazan a propósito, para que una errata no pueda dejar el ajuste desactivado sin que te des cuenta",[91,3423,3424],{},"Para comprobar una configuración sin levantar nada ni contactar con la API, ejecútala en modo de\nsimulación (dry run). Muestra las reglas que aplicaría y termina:",[224,3426,3428],{"className":226,"code":3427,"language":228,"meta":229,"style":229},"docker run --rm \\\n  -e GETPUBLICIP_API_KEY=x -e GETPUBLICIP_DRY_RUN=true \\\n  -e GETPUBLICIP_ISOLATED_INTERFACE=eth0 \\\n  -e GETPUBLICIP_MAPPINGS=\"8080\u002Ftcp->web:80\" \\\n  ghcr.io\u002Fgetpublicip\u002Fgetpublicip:latest\n",[95,3429,3430,3443,3461,3470,3479],{"__ignoreMap":229},[233,3431,3432,3434,3437,3440],{"class":235,"line":236},[233,3433,89],{"class":672},[233,3435,3436],{"class":247}," run",[233,3438,3439],{"class":396}," --rm",[233,3441,3442],{"class":396}," \\\n",[233,3444,3445,3448,3451,3454,3457,3459],{"class":235,"line":286},[233,3446,3447],{"class":396},"  -e",[233,3449,3450],{"class":247}," GETPUBLICIP_API_KEY=x",[233,3452,3453],{"class":396}," -e",[233,3455,3456],{"class":247}," GETPUBLICIP_DRY_RUN=",[233,3458,1472],{"class":396},[233,3460,3442],{"class":396},[233,3462,3463,3465,3468],{"class":235,"line":294},[233,3464,3447],{"class":396},[233,3466,3467],{"class":247}," GETPUBLICIP_ISOLATED_INTERFACE=eth0",[233,3469,3442],{"class":396},[233,3471,3472,3474,3477],{"class":235,"line":306},[233,3473,3447],{"class":396},[233,3475,3476],{"class":247}," GETPUBLICIP_MAPPINGS=\"8080\u002Ftcp->web:80\"",[233,3478,3442],{"class":396},[233,3480,3481],{"class":235,"line":317},[233,3482,3483],{"class":247},"  ghcr.io\u002Fgetpublicip\u002Fgetpublicip:latest\n",[103,3485,3487],{"id":3486},"preguntas-frecuentes","Preguntas frecuentes",[3489,3490,3493,3497],"details",{"className":3491},[3492],"faq-item",[3494,3495,3496],"summary",{},"¿Tengo que publicar puertos en mis contenedores para usar GetPublicIP?",[91,3498,3499,3500,3502,3503,3505],{},"No. El tráfico llega por el túnel WireGuard, no por un puerto publicado en el host, así que los servicios que expones no necesitan entradas ",[95,3501,97],{}," ni ningún otro cambio. Añadir ",[95,3504,97],{}," expondría también el servicio en tu red local, y normalmente eso no es lo que quieres.",[3489,3507,3509,3512],{"className":3508},[3492],[3494,3510,3511],{},"¿El contenedor de GetPublicIP tiene que ejecutarse en modo privilegiado?",[91,3513,3514,3515,3517,3518,3520],{},"No. El contenedor necesita la capacidad ",[95,3516,3190],{},", el dispositivo ",[95,3519,3193],{}," y los sysctls de reenvío, y nada más.",[3489,3522,3524,3527],{"className":3523},[3492],[3494,3525,3526],{},"¿Tengo que instalar el módulo de kernel de WireGuard en el host?",[91,3528,3529,3530,3533],{},"No. La imagen usa el módulo de kernel del host cuando está disponible y, si no, recurre a ",[95,3531,3532],{},"wireguard-go",", la implementación en espacio de usuario que incluye. No hay nada que instalar en el host en ningún caso, en ninguna plataforma.",[3489,3535,3537,3540],{"className":3536},[3492],[3494,3538,3539],{},"¿Funciona en macOS y Windows?",[91,3541,3542,3543,176,3545,3547],{},"Sí, y el archivo de Compose no necesita cambios en ninguno de los dos. El host de tu contenedor es una máquina virtual Linux y no el sistema operativo de escritorio, así que el dispositivo del túnel lo proporciona esa máquina virtual y no hay nada que instalar en macOS ni en Windows. macOS funciona sin cambios en Intel y Apple Silicon con Docker Desktop. En Windows, Docker Desktop tiene que estar en modo de contenedores Linux y tu kernel de WSL2 tiene que ser 6.6.x. Compruébalo con ",[95,3544,175],{},[95,3546,179],{}," si muestra una versión anterior, porque a los kernels anteriores a 6.6 les falta un módulo de netfilter que el túnel necesita.",[3489,3549,3551,3554],{"className":3550},[3492],[3494,3552,3553],{},"¿GetPublicIP descifra mi tráfico HTTPS?",[91,3555,3556],{},"No. GetPublicIP reenvía paquetes y nunca termina TLS, así que no tiene ninguno de tus certificados ni de tus claves privadas, ni nada con lo que descifrar. La sesión TLS se negocia directamente entre el navegador de tu visitante y el servicio tuyo que la termine, y se descifra por primera vez al llegar allí. Ese servicio necesita su propio certificado válido, igual que en cualquier otro host público. Let's Encrypt es gratuito y automatizado, y encaja bien aquí; si usas un desafío HTTP-01, recuerda redirigir el puerto 80 además del 443.",[3489,3558,3560,3563],{"className":3559},[3492],[3494,3561,3562],{},"¿Puedo redirigir un puerto a un servicio que se ejecuta en el host de Docker en lugar de en un contenedor?",[91,3564,3565,3566,3568,3569,3572,3573,3575,3576,3578,3579,207],{},"Sí. Apunta la redirección a ",[95,3567,1191],{}," y, en Linux, añade ",[95,3570,3571],{},"extra_hosts: - \"host.docker.internal:host-gateway\"",". En Docker Desktop viene incluido. También funciona una dirección IP literal. Además, el servicio del host tiene que escuchar en ",[95,3574,1251],{}," y no en ",[95,3577,1255],{},", y un firewall en el host tiene que permitir el tráfico entrante desde la subred del bridge. Los destinos en el host son lo único que no se puede combinar con ",[95,3580,1550],{},[3489,3582,3584,3587],{"className":3583},[3492],[3494,3585,3586],{},"¿Pueden mis contenedores ver la dirección IP real del visitante?",[91,3588,3589,3590,3593],{},"Sí, con ",[95,3591,3592],{},"GETPUBLICIP_PRESERVE_CLIENT_IP=true",", y viene desactivado de forma predeterminada porque requiere trabajo por tu parte. Normalmente, el agente reescribe la dirección de origen del tráfico entrante con la suya propia para que las respuestas vuelvan a través de él, y por eso tus logs de acceso muestran la misma dirección para todos los visitantes. Desactivar esa reescritura significa que cada servicio al que reenvías tiene que enviar sus respuestas de vuelta a través del agente, lo que implica cambiar la ruta predeterminada de ese servicio. Se aplica a todo tu archivo de Compose y no a una sola redirección, y mientras está activado no se puede reenviar a un servicio del host de Docker. Configúralo siempre junto con la ruta, nunca por separado: la variable por sí sola te deja con un servicio que se queda colgado mientras los logs siguen pareciendo correctos.",[3489,3595,3597,3600],{"className":3596},[3492],[3494,3598,3599],{},"¿Puedo usar X-Forwarded-For en lugar de GETPUBLICIP_PRESERVE_CLIENT_IP?",[91,3601,3602,3603,3606],{},"Por sí solo, no. ",[95,3604,3605],{},"X-Forwarded-For"," solo sirve si lo que añade la cabecera puede ver la dirección real del cliente desde el principio. La dirección de origen se reescribe a nivel de paquete, antes de que nada lea una solicitud HTTP, así que un proxy inverso dentro de tu archivo de Compose recibe paquetes que ya dicen venir del contenedor de GetPublicIP y no tiene nada verdadero que poner en la cabecera. Añadir uno ahí solo registra la dirección equivocada en un segundo lugar. Hay un caso en el que la cabecera sí funciona y no necesitas nada de esto: si tu tráfico pasa por una CDN o un proxy externo como Cloudflare antes de llegar a tu IP pública, ese servicio ve al cliente real y añade la cabecera él mismo, y tus contenedores deberían leerla de la forma habitual.",[3489,3608,3610,3613],{"className":3609},[3492],[3494,3611,3612],{},"¿Pueden mis contenedores usar también mi IP pública para el tráfico saliente?",[91,3614,3589,3615,3617],{},[95,3616,3368],{},". De forma predeterminada, solo el tráfico entrante usa el túnel y tus contenedores siguen saliendo a internet por tu conexión normal. Al activarlo, su tráfico saliente también pasa por el túnel, de modo que sale desde tu dirección de GetPublicIP. Necesita el mismo cambio que ver la IP real del cliente (la ruta predeterminada de cada contenedor tiene que apuntar al contenedor de GetPublicIP), así que, si ya lo tienes configurado, solo te queda añadir el ajuste. Todos los contenedores que hay detrás comparten la misma dirección. Además, falla en modo cerrado a propósito: mientras el túnel está caído, esos contenedores no tienen internet en absoluto, en lugar de volver a la dirección de tu operador.",[3489,3619,3621,3624],{"className":3620},[3492],[3494,3622,3623],{},"¿Qué pasa si se cae mi conexión a internet?",[91,3625,3626,3627,3629],{},"El túnel se restablece solo, y no hay nada que reiniciar ni que configurar. La mayoría de las caídas las repara el keepalive que mantiene abierta la conexión, sin que el agente tenga que intervenir; en un túnel real medimos que el tráfico volvía a fluir unos 17 segundos después de recuperarse la conectividad. Para los fallos menos frecuentes que un keepalive no puede arreglar, el agente detiene el contenedor en lugar de intentar reparar el túnel sobre la marcha, y tu política de reinicio lo vuelve a levantar enseguida con una conexión nueva; por eso el fragmento de Compose usa ",[95,3628,450],{},". Mientras tu internet esté caído, tu servicio no es accesible, y el túnel se recupera en cuanto vuelve a haber conexión.",[3489,3631,3633,3636],{"className":3632},[3492],[3494,3634,3635],{},"¿Qué pasa cuando uno de mis contenedores se reinicia con una dirección IP nueva?",[91,3637,3638,3639,3642],{},"El agente vuelve a resolver el nombre de servicio de cada destino a intervalos regulares (",[95,3640,3641],{},"GETPUBLICIP_RESOLVE_INTERVAL",", 30 segundos de forma predeterminada) y vuelve a aplicar las reglas de reenvío si un contenedor ha cambiado de dirección. No tienes que reiniciar nada. Es normal que se pierda una sola solicitud justo después de una resincronización, mientras se estabiliza el seguimiento de conexiones.",[3489,3644,3646,3649],{"className":3645},[3492],[3494,3647,3648],{},"¿Puedo usar la misma clave API en dos lugares a la vez?",[91,3650,3651],{},"No. Una clave de WireGuard pertenece a un único extremo, así que dos contenedores que usan la misma clave API se desconectan el uno al otro. Gana el que haya hecho el handshake más reciente. Se manifiesta como fallos aleatorios e intermitentes en lugar de un error claro, aunque hay una señal inequívoca: los dos contenedores se reinician una y otra vez, porque cada uno concluye que el averiado es él. Usa una clave API por cada túnel en funcionamiento.",[3653,3654],"hr",{},[91,3656,3657,3661,3662,3666,3667,207],{},[120,3658,73],{"className":3659,"href":3660},[123],"\u002Fes\u002Fdocs\u002Fgetting-started"," explica cómo funciona el\nservicio. Para ejecutar tus servicios directamente en un host en lugar de en contenedores,\nconsulta las guías de ",[120,3663,35],{"className":3664,"href":3665},[123],"\u002Fes\u002Fdocs\u002Flinux"," y\n",[120,3668,43],{"className":3669,"href":3670},[123],"\u002Fes\u002Fdocs\u002Fwindows",[3672,3673,3674],"style",{},"html pre.shiki code .sCdxs, html code.shiki .sCdxs{--shiki-default:#F8F8F2}html pre.shiki code .s8I7P, html code.shiki .s8I7P{--shiki-default:#F92672}html pre.shiki code .s_Ekj, html code.shiki .s_Ekj{--shiki-default:#E6DB74}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 pre.shiki code .s7s5_, html code.shiki .s7s5_{--shiki-default:#AE81FF}html pre.shiki code .sHkqI, html code.shiki .sHkqI{--shiki-default:#A6E22E}html pre.shiki code .snpHw, html code.shiki .snpHw{--shiki-default:#88846F}",{"title":229,"searchDepth":286,"depth":286,"links":3676},[3677,3678,3679,3682,3686,3691,3692,3693,3694,3695,3696,3702,3706,3707,3708,3709,3710,3711,3712],{"id":105,"depth":286,"text":106},{"id":210,"depth":286,"text":211},{"id":264,"depth":286,"text":265,"children":3680},[3681],{"id":460,"depth":294,"text":461},{"id":709,"depth":286,"text":710,"children":3683},[3684,3685],{"id":936,"depth":294,"text":937},{"id":980,"depth":294,"text":981},{"id":1105,"depth":286,"text":1106,"children":3687},[3688,3689,3690],{"id":1126,"depth":294,"text":1127},{"id":1136,"depth":294,"text":1137},{"id":1177,"depth":294,"text":1178},{"id":1184,"depth":286,"text":1185},{"id":1287,"depth":286,"text":1288},{"id":1411,"depth":286,"text":1412},{"id":1476,"depth":286,"text":1477},{"id":1509,"depth":286,"text":456},{"id":1538,"depth":286,"text":1283,"children":3697},[3698,3699,3700,3701],{"id":1573,"depth":294,"text":1574},{"id":1607,"depth":294,"text":1608},{"id":2540,"depth":294,"text":2541},{"id":2602,"depth":294,"text":2603},{"id":2660,"depth":286,"text":2661,"children":3703},[3704,3705],{"id":2849,"depth":294,"text":2850},{"id":2889,"depth":294,"text":2890},{"id":2947,"depth":286,"text":2948},{"id":3018,"depth":286,"text":39},{"id":3031,"depth":286,"text":43},{"id":3098,"depth":286,"text":3099},{"id":3108,"depth":286,"text":3109},{"id":3124,"depth":286,"text":3125},{"id":3486,"depth":286,"text":3487},"2026-08-09","Expón tus servicios de Docker Compose a internet con una IP pública dedicada. Añade un contenedor, redirige tus puertos y tus servicios siguen igual.","md",[3717,3719,3721,3723,3725,3726,3728,3730,3732,3734,3736,3738],{"question":3496,"answer":3718},"No. El tráfico llega por el túnel WireGuard, no por un puerto publicado en el host, así que los servicios que expones no necesitan entradas `ports:` ni ningún otro cambio. Añadir `ports:` expondría también el servicio en tu red local, y normalmente eso no es lo que quieres.",{"question":3511,"answer":3720},"No. El contenedor necesita la capacidad `NET_ADMIN`, el dispositivo `\u002Fdev\u002Fnet\u002Ftun` y los sysctls de reenvío, y nada más.",{"question":3526,"answer":3722},"No. La imagen usa el módulo de kernel del host cuando está disponible y, si no, recurre a `wireguard-go`, la implementación en espacio de usuario que incluye. No hay nada que instalar en el host en ningún caso, en ninguna plataforma.",{"question":3539,"answer":3724},"Sí, y el archivo de Compose no necesita cambios en ninguno de los dos. El host de tu contenedor es una máquina virtual Linux y no el sistema operativo de escritorio, así que el dispositivo del túnel lo proporciona esa máquina virtual y no hay nada que instalar en macOS ni en Windows. macOS funciona sin cambios en Intel y Apple Silicon con Docker Desktop. En Windows, Docker Desktop tiene que estar en modo de contenedores Linux y tu kernel de WSL2 tiene que ser 6.6.x. Compruébalo con `wsl --version` y ejecuta `wsl --update` si muestra una versión anterior, porque a los kernels anteriores a 6.6 les falta un módulo de netfilter que el túnel necesita.",{"question":3553,"answer":3556},{"question":3562,"answer":3727},"Sí. Apunta la redirección a `host.docker.internal` y, en Linux, añade `extra_hosts: - \"host.docker.internal:host-gateway\"`. En Docker Desktop viene incluido. También funciona una dirección IP literal. Además, el servicio del host tiene que escuchar en `0.0.0.0` y no en `127.0.0.1`, y un firewall en el host tiene que permitir el tráfico entrante desde la subred del bridge. Los destinos en el host son lo único que no se puede combinar con `GETPUBLICIP_PRESERVE_CLIENT_IP`.",{"question":3586,"answer":3729},"Sí, con `GETPUBLICIP_PRESERVE_CLIENT_IP=true`, y viene desactivado de forma predeterminada porque requiere trabajo por tu parte. Normalmente, el agente reescribe la dirección de origen del tráfico entrante con la suya propia para que las respuestas vuelvan a través de él, y por eso tus logs de acceso muestran la misma dirección para todos los visitantes. Desactivar esa reescritura significa que cada servicio al que reenvías tiene que enviar sus respuestas de vuelta a través del agente, lo que implica cambiar la ruta predeterminada de ese servicio. Se aplica a todo tu archivo de Compose y no a una sola redirección, y mientras está activado no se puede reenviar a un servicio del host de Docker. Configúralo siempre junto con la ruta, nunca por separado: la variable por sí sola te deja con un servicio que se queda colgado mientras los logs siguen pareciendo correctos.",{"question":3599,"answer":3731},"Por sí solo, no. `X-Forwarded-For` solo sirve si lo que añade la cabecera puede ver la dirección real del cliente desde el principio. La dirección de origen se reescribe a nivel de paquete, antes de que nada lea una solicitud HTTP, así que un proxy inverso dentro de tu archivo de Compose recibe paquetes que ya dicen venir del contenedor de GetPublicIP y no tiene nada verdadero que poner en la cabecera. Añadir uno ahí solo registra la dirección equivocada en un segundo lugar. Hay un caso en el que la cabecera sí funciona y no necesitas nada de esto: si tu tráfico pasa por una CDN o un proxy externo como Cloudflare antes de llegar a tu IP pública, ese servicio ve al cliente real y añade la cabecera él mismo, y tus contenedores deberían leerla de la forma habitual.",{"question":3612,"answer":3733},"Sí, con `GETPUBLICIP_OUTBOUND=true`. De forma predeterminada, solo el tráfico entrante usa el túnel y tus contenedores siguen saliendo a internet por tu conexión normal. Al activarlo, su tráfico saliente también pasa por el túnel, de modo que sale desde tu dirección de GetPublicIP. Necesita el mismo cambio que ver la IP real del cliente (la ruta predeterminada de cada contenedor tiene que apuntar al contenedor de GetPublicIP), así que, si ya lo tienes configurado, solo te queda añadir el ajuste. Todos los contenedores que hay detrás comparten la misma dirección. Además, falla en modo cerrado a propósito: mientras el túnel está caído, esos contenedores no tienen internet en absoluto, en lugar de volver a la dirección de tu operador.",{"question":3623,"answer":3735},"El túnel se restablece solo, y no hay nada que reiniciar ni que configurar. La mayoría de las caídas las repara el keepalive que mantiene abierta la conexión, sin que el agente tenga que intervenir; en un túnel real medimos que el tráfico volvía a fluir unos 17 segundos después de recuperarse la conectividad. Para los fallos menos frecuentes que un keepalive no puede arreglar, el agente detiene el contenedor en lugar de intentar reparar el túnel sobre la marcha, y tu política de reinicio lo vuelve a levantar enseguida con una conexión nueva; por eso el fragmento de Compose usa `restart: unless-stopped`. Mientras tu internet esté caído, tu servicio no es accesible, y el túnel se recupera en cuanto vuelve a haber conexión.",{"question":3635,"answer":3737},"El agente vuelve a resolver el nombre de servicio de cada destino a intervalos regulares (`GETPUBLICIP_RESOLVE_INTERVAL`, 30 segundos de forma predeterminada) y vuelve a aplicar las reglas de reenvío si un contenedor ha cambiado de dirección. No tienes que reiniciar nada. Es normal que se pierda una sola solicitud justo después de una resincronización, mientras se estabiliza el seguimiento de conexiones.",{"question":3648,"answer":3651},{},{"title":47,"icon":48,"description":3741},"Expón tus servicios de Docker Compose a internet a través de un túnel de GetPublicIP.",{"title":82,"description":3714},"2026-10-31","q-tsYM9YeWTdR6ykX4qbhEhQ0L3kfvtCnahtLf_yBDw",1793914055421]