Container connection issues in swarm when using offical nginx:latest image

I apologize if this has been answered before, or if this is the wrong place to post this, but this has me completely perplexed.

I’m having a strange issue when running with swarm mode on docker for Windows. I’m trying to deploy two containers, one based on the nginx:latest image and another custom build django app image. The nginx image is to act as the proxy for the web app.

However, when I try to run in swarm mode, the nginx container cannot contact the web app container. I have confirmed that the web app is running.

The nginx log looks like the following:

NGINX logs
2018/05/06 20:18:48 [error] 5#5: *2 connect() failed (111: Connection refused) while connecting to upstream, client: 10.255.0.2, server: localhost, request: "GET / HTTP/1.1", upstream: "http://92.242.140.2:8000/", host: "localhost", referrer: "http://localhost/about"
10.255.0.2 - - [06/May/2018:20:18:48 +0000] "GET / HTTP/1.1" 502 174 "http://localhost/about" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0"

The compose file looks like:

docker-compose.yml
version: "3.3"
services:
  nginx:
    image: nginx:latest
    ports:
      - "80:80"
    # This only works in swarm mode
    configs:
      - source: nginx_config
        # need to overwrite the nginx.conf with ours.
        target: /etc/nginx/nginx.conf
        uid: "65534"
        gid: "65534"
    volumes:
      - static:/static
    depends_on:
      - web
  web:
    image: mat-marketing:latest
    # we want to mount the env file as a secret since it contains passwords,
    # secret keys, etc...
    secrets:
      - source: django_secret
        target: /app/django-mat-marketing-site/.env
    volumes:
      - static:/static
    expose:
      - "8000"
configs:
  nginx_config:
    file: ./nginx/mat_marketing.conf
secrets:
  django_secret:
    file: ./django-env/.env
# a named volume for the nginx container to share the /static folder from
# the web container for serving django collected static files.
volumes:
  static:

The NGINX config looks like:

mat_marketing.conf
# This was started from the gunicorn deployment example NGINX conf file:
# https://github.com/benoitc/gunicorn/blob/master/examples/nginx.conf
worker_processes 1;

# 'user nobody nobody;' for systems with 'nobody' as a group instead
user nobody nogroup;

# Done to match the defualt nginx.conf from nginx:latest. Not sure if it matters.
# The NGINX Dockerfile link is in the comment below.
pid /var/run/nginx.pid;
# set this to /var/log/nginx/error.log so the stderr/stdout redirect done by the
# NGINX container works. Here's the dockerfile line that does this:
# https://github.com/nginxinc/docker-nginx/blob/d377983a14b214fcae4b8e34357761282aca788f/mainline/alpine/Dockerfile#L135
error_log /var/log/nginx/error.log;

events {
  worker_connections 1024; # increase if you have lots of clients
  accept_mutex off; # set to 'on' if nginx worker_processes > 1
  # 'use epoll;' to enable for Linux 2.6+
  # 'use kqueue;' to enable for FreeBSD, OSX
  use epoll;
}

http {
  include mime.types;
  # fallback in case we can't determine a type
  default_type application/octet-stream;
  # same reason for this log location as the error.log above
  access_log /var/log/nginx/access.log combined;
  sendfile on;

  # The upstream must have the same name as the service configured in
  # the docker-compose.yml file.
  upstream web {
# fail_timeout=0 means we always retry an upstream even if it failed
# to return a good HTTP response

# for UNIX domain socket setups
# server unix:/tmp/gunicorn.sock fail_timeout=0;

# for a TCP configuration
# server 192.168.0.7:8000 fail_timeout=0;

# We need to use the service name here since we don't know what IP
# the web docker container will have
server web:8000 fail_timeout=0;
  }

  server {
# if no Host match, close the connection to prevent host spoofing
listen 80 default_server;
return 444;
  }

  server {
# use 'listen 80 deferred;' for Linux
# use 'listen 80 accept_filter=httpready;' for FreeBSD
listen 80 deferred;

client_max_body_size 4G;

# set the correct host(s) for your site
server_name localhost;

keepalive_timeout 5;

# configure nginx to serve static files
location /static/ {
    autoindex on;
    alias /static/;
}

# proxy everything else
location / {
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Forwarded-Proto $scheme;
  proxy_set_header Host $http_host;
  # we don't want nginx trying to do something clever with
  # redirects, we set the Host: header above already.
  proxy_redirect off;
  proxy_pass http://web/;
}

# error_page 500 502 503 504 /500.html;
# location = /500.html {
#   root /path/to/app/current/public;
# }
  }
}

Here’s where things get strange. If I instead “build my own” nginx image named nginx-mat and change the compose file to reference the nginx-mat image, there is no issues contacting the web app container. The nginx configuration is unchanged.

Here’s the dockerfile for my own nginx build:

Dockerfile

FROM nginx:latest

Here’s the build command:

build command

docker build -t nginx-mat .\nginx\

Here’s the modified compose file that points to the image I built:

docker-compose.yml
version: "3.3"
services:
  nginx:
    # This makes zero sense, but I need to use the nginx-mat image otherwise the NGINX container cant
    # contect the web app container.
    image: nginx-mat:latest

I feel like the only possible answer has something to do with permissions, but I’m at a loss. Any help is greatly appreciated, as I’d much rather be able to pull the offical nginx:latest image than have to build my own.

Thanks,
-Ryan Causey