Tengo dos contenedores App y Webserver. El servidor web es nginx simple: imagen alpina y la aplicación es la aplicación expressjs que se ejecuta en el puerto 3030 en ubuntu: focal. Escuché que esta es una práctica común para usar contenedores separados para la aplicación y el servidor. Así que agregué proxy_pass http://app:3030/; a la configuración de nginx. Algo salió mal y profundicé un poco en esto. Para excluir la configuración incorrecta de nginx, verifiqué las solicitudes de curl sin formato del servidor web al contenedor de la aplicación sin suerte. Aquí está mi docker-compose:
version: '3.5' services: webserver: image: nginx:alpine env_file: .env restart: always tty: true ports: - ${NGINX_HOST_HTTP_PORT}:80 - ${NGINX_HOST_HTTPS_PORT}:443 volumes: - ${APP_CODE_PATH_HOST}:${APP_DIR} - ./nginx/nginx.conf:/etc/nginx/nginx.conf - ./nginx/sites/:/etc/nginx/conf.d/ - ./nginx/ssl/:/etc/ssl/ depends_on: - app container_name: ${CONTAINER_NAME_PREFIX}-webserver networks: - app-network app: env_file: .env restart: on-failure tty: true build: dockerfile: ./docker/app/Dockerfile args: APP_ENV: ${APP_ENV} APP_DIR: ${APP_DIR} PRODUCT_ID: ${PRODUCT_ID} context: ../ environment: - DEBIAN_FRONTEND=noninteractive container_name: ${CONTAINER_NAME_PREFIX}-app networks: - app-network networks: app-network: driver: bridgePuedo solicitar express desde el contenedor de la aplicación CLI:
/ # curl -X GET http://127.0.0.1:3030/multichannel/4034?uid=a6O5iTje8sR2PESbWpAM {"status": "OK"}Y ahora desde Webserver:
/ # ping app PING app (172.19.0.2): 56 data bytes 64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.090 ms / # curl -X GET http://172.19.0.2:3030/multichannel/4034?uid=a6O5iTje8sR2PESbWpAM curl: (7) Failed to connect to 172.19.0.2 port 3030 after 0 ms: Connection refused / # curl -X GET http://app:3030/multichannel/4034?uid=a6O5iTje8sR2PESbWpAM curl: (7) Failed to connect to app port 3030 after 0 ms: Connection refusedRegistro de Nginx (no preste atención a la IP, es correcta, después de que se reconstruyeron los contenedores, cambió):
2021/10/29 15:40:46 [error] 24#24: *12 connect() failed (111: Connection refused) while connecting to upstream, client: 172.20.0.1, server: api.test, request: "GET /multichannel/4034?uid=a6O5iTje8sR2PESbWpAM HTTP/1.1", upstream: "http://172.20.0.3:3030/multichannel/4034?uid=a6O5iTje8sR2PESbWpAM", host: "api.test"Por supuesto, Nginx conf tiene:
location / { proxy_pass http://app:3030; }¿Por qué se rechazó la conexión? Ambos contenedores están en la misma red.
Debe exponer al menos el puerto 3030 en el contenedor de la aplicación para que esté disponible para otros contenedores:
app: expose: - "3030"Consulte los documentos de exposición .
Alternativamente, puede publicar el puerto : especifique ambos puertos (HOST: CONTAINER), o solo el puerto del contenedor (se elegirá un puerto de host aleatorio):
app: ports: - "3030"Como no tenía el código de la aplicación express, traté de simular el problema con la imagen de la ventana acoplable de otra aplicación con una versión simplificada del archivo de composición de la ventana acoplable y la configuración de nginx. Estoy usando una máquina ubuntu también. Pero la llamada de nginx a la aplicación funciona bien en mi caso.
docker-compose.yml:
version: '3.5' services: webserver: image: nginx:alpine restart: always tty: true ports: - 8081:80 volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf depends_on: - app container_name: test-webserver networks: - app-network app: image: devatherock/artifactory-badge:latest environment: - ARTIFACTORY_URL=http://localhost:8081 - ARTIFACTORY_API_KEY=dummy restart: on-failure tty: true container_name: test-app networks: - app-network networks: app-network: driver: bridgenginx.conf:
events { } http { server { listen 80; location / { proxy_pass http://app:8080; } } } Incluso yo asumí lo mismo que Robert, que necesitamos especificar la sección de ports para el servicio de la app , pero la llamada de nginx a la aplicación funcionó incluso sin ella. Cuando llego al punto final http://localhost:8081/health en nginx, reenvía la solicitud a la aplicación en http://app:8080/health y devuelve la respuesta {"status":"UP"} de que la aplicación devoluciones de chequeo de salud
Finalmente encontré la razón por la cual no puedo conectarme. Cuando @devatherock mencionó ARTIFACTORY_URL ARTIFACTORY_URL=http://localhost:8081 , revisé el código de la aplicación en qué host se usa y encontré esto:
server.listen(3030, "127.0.0.1", () => { logger.debug(`Server is running on ${serverConfig.port} port`); }); Luego probé "localhost" como host y todavía obtuve 502. Así que es hora de leer los documentos. Expressjs server.listen funciona como nodejs server.listen https://nodejs.org/api/net.html#serverlistenport-host-backlog-callback
Si se omite host, el servidor aceptará conexiones en la dirección IPv6 no especificada (::) cuando IPv6 esté disponible, o la dirección IPv4 no especificada (0.0.0.0) en caso contrario. En la mayoría de los sistemas operativos, escuchar la dirección IPv6 no especificada (::) puede hacer que net.Server también escuche la dirección IPv4 no especificada (0.0.0.0).
Y la respuesta es usar '0.0.0.0' o simplemente omitir el parámetro de host. 127.0.0.1 o localhost accesible solo en la máquina local porque está limitado a la interfaz de bucle invertido.